aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/arcnet/arcnet.c10
-rw-r--r--drivers/net/bonding/bond_alb.c6
-rw-r--r--drivers/net/bonding/bond_main.c26
-rw-r--r--drivers/net/bonding/bonding_priv.h4
-rw-r--r--drivers/net/can/Kconfig7
-rw-r--r--drivers/net/can/at91_can.c6
-rw-r--r--drivers/net/can/bxcan.c17
-rw-r--r--drivers/net/can/c_can/c_can_platform.c6
-rw-r--r--drivers/net/can/cc770/cc770_isa.c6
-rw-r--r--drivers/net/can/cc770/cc770_platform.c6
-rw-r--r--drivers/net/can/ctucanfd/ctucanfd_platform.c6
-rw-r--r--drivers/net/can/dev/length.c15
-rw-r--r--drivers/net/can/dev/rx-offload.c2
-rw-r--r--drivers/net/can/flexcan/flexcan-core.c6
-rw-r--r--drivers/net/can/grcan.c6
-rw-r--r--drivers/net/can/ifi_canfd/ifi_canfd.c6
-rw-r--r--drivers/net/can/janz-ican3.c6
-rw-r--r--drivers/net/can/kvaser_pciefd.c955
-rw-r--r--drivers/net/can/m_can/m_can.c4
-rw-r--r--drivers/net/can/m_can/m_can_platform.c6
-rw-r--r--drivers/net/can/m_can/tcan4x5x-regmap.c1
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c6
-rw-r--r--drivers/net/can/rcar/rcar_can.c5
-rw-r--r--drivers/net/can/rcar/rcar_canfd.c6
-rw-r--r--drivers/net/can/sja1000/sja1000.c40
-rw-r--r--drivers/net/can/sja1000/sja1000.h1
-rw-r--r--drivers/net/can/sja1000/sja1000_isa.c6
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c11
-rw-r--r--drivers/net/can/softing/softing_main.c5
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c10
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd.h1
-rw-r--r--drivers/net/can/sun4i_can.c28
-rw-r--r--drivers/net/can/ti_hecc.c8
-rw-r--r--drivers/net/can/usb/Kconfig12
-rw-r--r--drivers/net/can/usb/Makefile1
-rw-r--r--drivers/net/can/usb/esd_usb.c352
-rw-r--r--drivers/net/can/usb/f81604.c1201
-rw-r--r--drivers/net/can/usb/gs_usb.c137
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c2
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c13
-rw-r--r--drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c6
-rw-r--r--drivers/net/can/vxcan.c7
-rw-r--r--drivers/net/can/xilinx_can.c25
-rw-r--r--drivers/net/dsa/b53/b53_serdes.c3
-rw-r--r--drivers/net/dsa/bcm_sf2.c8
-rw-r--r--drivers/net/dsa/hirschmann/hellcreek.c14
-rw-r--r--drivers/net/dsa/lan9303-core.c1
-rw-r--r--drivers/net/dsa/lan9303_i2c.c2
-rw-r--r--drivers/net/dsa/microchip/ksz8795.c36
-rw-r--r--drivers/net/dsa/microchip/ksz8863_smi.c13
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c116
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c4
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c110
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h83
-rw-r--r--drivers/net/dsa/microchip/ksz_spi.c2
-rw-r--r--drivers/net/dsa/microchip/lan937x_main.c8
-rw-r--r--drivers/net/dsa/mt7530.c7
-rw-r--r--drivers/net/dsa/mt7530.h2
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c193
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h15
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c5
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c29
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h15
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.c47
-rw-r--r--drivers/net/dsa/mv88e6xxx/serdes.h4
-rw-r--r--drivers/net/dsa/ocelot/felix.c24
-rw-r--r--drivers/net/dsa/ocelot/felix.h1
-rw-r--r--drivers/net/dsa/ocelot/felix_vsc9959.c87
-rw-r--r--drivers/net/dsa/ocelot/seville_vsc9953.c20
-rw-r--r--drivers/net/dsa/qca/ar9331.c20
-rw-r--r--drivers/net/dsa/qca/qca8k-8xxx.c25
-rw-r--r--drivers/net/dsa/qca/qca8k-common.c25
-rw-r--r--drivers/net/dsa/qca/qca8k-leds.c201
-rw-r--r--drivers/net/dsa/sja1105/sja1105.h6
-rw-r--r--drivers/net/dsa/sja1105/sja1105_dynamic_config.c93
-rw-r--r--drivers/net/dsa/sja1105/sja1105_main.c148
-rw-r--r--drivers/net/dsa/sja1105/sja1105_mdio.c11
-rw-r--r--drivers/net/dsa/sja1105/sja1105_ptp.c48
-rw-r--r--drivers/net/dsa/sja1105/sja1105_spi.c4
-rw-r--r--drivers/net/dsa/sja1105/sja1105_tas.c7
-rw-r--r--drivers/net/dsa/vitesse-vsc73xx-core.c6
-rw-r--r--drivers/net/dsa/xrs700x/xrs700x_i2c.c2
-rw-r--r--drivers/net/ethernet/8390/8390.h2
-rw-r--r--drivers/net/ethernet/8390/apne.c7
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c6
-rw-r--r--drivers/net/ethernet/8390/hydra.c6
-rw-r--r--drivers/net/ethernet/8390/lib8390.c5
-rw-r--r--drivers/net/ethernet/8390/mac8390.c6
-rw-r--r--drivers/net/ethernet/8390/mcf8390.c4
-rw-r--r--drivers/net/ethernet/8390/ne.c4
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c1
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c5
-rw-r--r--drivers/net/ethernet/8390/smc-ultra.c4
-rw-r--r--drivers/net/ethernet/8390/stnic.c5
-rw-r--r--drivers/net/ethernet/8390/wd.c4
-rw-r--r--drivers/net/ethernet/8390/zorro8390.c7
-rw-r--r--drivers/net/ethernet/adi/adin1110.c10
-rw-r--r--drivers/net/ethernet/altera/Kconfig4
-rw-r--r--drivers/net/ethernet/altera/altera_tse_main.c65
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_admin_defs.h6
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_com.c3
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c136
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.h4
-rw-r--r--drivers/net/ethernet/amd/pds_core/core.c15
-rw-r--r--drivers/net/ethernet/amd/pds_core/dev.c9
-rw-r--r--drivers/net/ethernet/amd/pds_core/devlink.c3
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c13
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_macsec.c40
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ring.c6
-rw-r--r--drivers/net/ethernet/arc/emac.h2
-rw-r--r--drivers/net/ethernet/arc/emac_arc.c6
-rw-r--r--drivers/net/ethernet/arc/emac_main.c4
-rw-r--r--drivers/net/ethernet/arc/emac_rockchip.c5
-rw-r--r--drivers/net/ethernet/atheros/alx/ethtool.c5
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c7
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c7
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c7
-rw-r--r--drivers/net/ethernet/broadcom/b44.c8
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c6
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c21
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c32
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c17
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c95
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h54
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c14
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h2
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c14
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c7
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_debugfs.c5
-rw-r--r--drivers/net/ethernet/cadence/macb.h13
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c61
-rw-r--r--drivers/net/ethernet/cavium/Kconfig5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/Makefile8
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c8
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c7
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn66xx_device.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/cn68xx_device.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_core.c16
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_ethtool.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c18
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_vf_main.c15
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c24
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_droq.c4
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_nic.c3
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c14
-rw-r--r--drivers/net/ethernet/cavium/liquidio/response_manager.c3
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/sge.c5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h3
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c2
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c118
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c2
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c35
-rw-r--r--drivers/net/ethernet/engleder/tsnep_selftests.c12
-rw-r--r--drivers/net/ethernet/engleder/tsnep_tc.c4
-rw-r--r--drivers/net/ethernet/freescale/Kconfig2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c33
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c4
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c12
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h1
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c133
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_ptp.c2
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_qos.c113
-rw-r--r--drivers/net/ethernet/freescale/fec.h17
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c220
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_dtsec.c7
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_memac.c18
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mii-fec.c2
-rw-r--r--drivers/net/ethernet/fungible/funeth/funeth_rx.c5
-rw-r--r--drivers/net/ethernet/fungible/funeth/funeth_tx.c3
-rw-r--r--drivers/net/ethernet/google/gve/gve.h1
-rw-r--r--drivers/net/ethernet/google/gve/gve_ethtool.c5
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c16
-rw-r--r--drivers/net/ethernet/google/gve/gve_rx_dqo.c5
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx.c2
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx_dqo.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/Makefile4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h12
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c22
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h2
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c46
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c35
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c11
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h4
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c71
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c47
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c641
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h15
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c668
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h17
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c36
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h5
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c135
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h1
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c127
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h13
-rw-r--r--drivers/net/ethernet/i825xx/82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/lasi_82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c5
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c1
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.h1
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c2
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c121
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.c2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf.h16
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_alloc.h3
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_common.c45
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_ethtool.c54
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_fdir.c88
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_fdir.h2
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c326
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_osdep.h9
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_prototype.h5
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.c43
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_txrx.h4
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_virtchnl.c5
-rw-r--r--drivers/net/ethernet/intel/ice/Makefile1
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h51
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_arfs.c5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_base.c55
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_controlq.c12
-rw-r--r--drivers/net/ethernet/intel/ice/ice_controlq.h1
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ddp.h9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_devlink.c10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.c93
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.h14
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c324
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.h105
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_flow.c23
-rw-r--r--drivers/net/ethernet/intel/ice/ice_idc.c54
-rw-r--r--drivers/net/ethernet/intel/ice/ice_irq.c378
-rw-r--r--drivers/net/ethernet/intel/ice/ice_irq.h25
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.c12
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lag.h54
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.c359
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lib.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c426
-rw-r--r--drivers/net/ethernet/intel/ice/ice_protocol_type.h197
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c64
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h16
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.c55
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.h3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.c17
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c11
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sriov.c60
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c251
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.h13
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.c56
-rw-r--r--drivers/net/ethernet/intel/ice/ice_tc_lib.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.c69
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vf_lib.h8
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.c9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_vlan_mode.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_xsk.c5
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c28
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c24
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h4
-rw-r--r--drivers/net/ethernet/intel/igc/igc.h60
-rw-r--r--drivers/net/ethernet/intel/igc/igc_defines.h2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c303
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ptp.c167
-rw-r--r--drivers/net/ethernet/intel/igc/igc_tsn.c68
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c28
-rw-r--r--drivers/net/ethernet/korina.c3
-rw-r--r--drivers/net/ethernet/litex/litex_liteeth.c19
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c182
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c19
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c3
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c2
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c9
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_rx.c2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/Kconfig1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c33
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/common.h9
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h11
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/ptp.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c49
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.h5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h32
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c22
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c5
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c74
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c327
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c66
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/Makefile2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c6
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c224
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c259
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h96
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c29
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c8
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c150
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h13
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c58
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c73
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h10
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.c1363
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos.h69
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c296
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_flower.c6
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_main.c11
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_pci.c3
-rw-r--r--drivers/net/ethernet/marvell/prestera/prestera_router.c14
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c32
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c2
-rw-r--r--drivers/net/ethernet/mediatek/mtk_wed.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c65
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/debugfs.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/dev.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c87
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c106
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en.h17
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c44
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/qos.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/ct.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/redirect_ingress.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c31
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c53
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c157
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.h7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rx.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_stats.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c238
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c89
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c99
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.c266
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h88
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c529
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/events.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c108
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c177
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/health.c25
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c141
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c68
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c129
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h37
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/events.h40
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c215
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h42
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/rdma.c24
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/sriov.c53
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/thermal.c34
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/vport.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/minimal.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h9
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c45
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c832
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h12
-rw-r--r--drivers/net/ethernet/microchip/Kconfig2
-rw-r--r--drivers/net/ethernet/microchip/enc28j60.c28
-rw-r--r--drivers/net/ethernet/microchip/lan743x_main.c43
-rw-r--r--drivers/net/ethernet/microchip/lan966x/Kconfig11
-rw-r--r--drivers/net/ethernet/microchip/lan966x/Makefile1
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c365
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.c3
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_main.h60
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c7
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_port.c149
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c4
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_regs.h147
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_tc.c10
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c61
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c264
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c23
-rw-r--r--drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c82
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.c1
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c8
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_ag_api.h67
-rw-r--r--drivers/net/ethernet/microchip/vcap/vcap_api.c26
-rw-r--r--drivers/net/ethernet/microsoft/mana/hw_channel.c2
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c61
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c2
-rw-r--r--drivers/net/ethernet/mscc/ocelot_fdma.c3
-rw-r--r--drivers/net/ethernet/mscc/ocelot_flower.c10
-rw-r--r--drivers/net/ethernet/mscc/ocelot_mm.c14
-rw-r--r--drivers/net/ethernet/mscc/ocelot_ptp.c66
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_devlink.c10
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c11
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c32
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h7
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c54
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/Kconfig2
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c6
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_ethtool.c10
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c33
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev_api.h16
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_fcoe.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_fcoe.h17
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hw.c26
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_iscsi.h8
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c19
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.h24
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c6
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c10
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-mac.c7
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c82
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c46
-rw-r--r--drivers/net/ethernet/renesas/rswitch.h7
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c4
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c5
-rw-r--r--drivers/net/ethernet/sfc/Kconfig1
-rw-r--r--drivers/net/ethernet/sfc/Makefile3
-rw-r--r--drivers/net/ethernet/sfc/ef10.c13
-rw-r--r--drivers/net/ethernet/sfc/ef100_netdev.c85
-rw-r--r--drivers/net/ethernet/sfc/ef100_nic.c2
-rw-r--r--drivers/net/ethernet/sfc/efx.c9
-rw-r--r--drivers/net/ethernet/sfc/efx_devlink.c83
-rw-r--r--drivers/net/ethernet/sfc/falcon/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/mae.c141
-rw-r--r--drivers/net/ethernet/sfc/mae.h9
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h3
-rw-r--r--drivers/net/ethernet/sfc/ptp.c4
-rw-r--r--drivers/net/ethernet/sfc/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/siena/selftest.c58
-rw-r--r--drivers/net/ethernet/sfc/siena/tx_common.c1
-rw-r--r--drivers/net/ethernet/sfc/tc.c409
-rw-r--r--drivers/net/ethernet/sfc/tc.h51
-rw-r--r--drivers/net/ethernet/sfc/tc_bindings.c13
-rw-r--r--drivers/net/ethernet/sfc/tc_bindings.h14
-rw-r--r--drivers/net/ethernet/sfc/tc_counters.c58
-rw-r--r--drivers/net/ethernet/sfc/tc_counters.h3
-rw-r--r--drivers/net/ethernet/sfc/tc_encap_actions.c747
-rw-r--r--drivers/net/ethernet/sfc/tc_encap_actions.h114
-rw-r--r--drivers/net/ethernet/sfc/tx_common.c1
-rw-r--r--drivers/net/ethernet/socionext/netsec.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c257
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h29
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c297
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c108
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c30
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c15
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c168
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c7
-rw-r--r--drivers/net/ethernet/sun/cassini.c8
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.c1
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-qos.c11
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c24
-rw-r--r--drivers/net/ethernet/wangxun/Kconfig10
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c273
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.h3
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.c737
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.h1
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_type.h220
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_main.c20
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_type.h1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/Makefile1
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c28
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c35
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c98
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c673
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h10
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_type.h90
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c12
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c16
-rw-r--r--drivers/net/gtp.c2
-rw-r--r--drivers/net/hyperv/hyperv_net.h5
-rw-r--r--drivers/net/hyperv/netvsc_drv.c10
-rw-r--r--drivers/net/hyperv/rndis_filter.c29
-rw-r--r--drivers/net/ieee802154/ca8210.c4
-rw-r--r--drivers/net/ipa/ipa_table.c20
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c12
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c3
-rw-r--r--drivers/net/macsec.c31
-rw-r--r--drivers/net/macvlan.c1
-rw-r--r--drivers/net/mctp/mctp-i2c.c2
-rw-r--r--drivers/net/mdio/Kconfig11
-rw-r--r--drivers/net/mdio/Makefile1
-rw-r--r--drivers/net/mdio/mdio-bitbang.c4
-rw-r--r--drivers/net/mdio/mdio-mux-mmioreg.c7
-rw-r--r--drivers/net/mdio/mdio-regmap.c93
-rw-r--r--drivers/net/netdevsim/dev.c9
-rw-r--r--drivers/net/ntb_netdev.c2
-rw-r--r--drivers/net/pcs/Kconfig6
-rw-r--r--drivers/net/pcs/Makefile1
-rw-r--r--drivers/net/pcs/pcs-altera-tse.c160
-rw-r--r--drivers/net/pcs/pcs-lynx.c123
-rw-r--r--drivers/net/pcs/pcs-mtk-lynxi.c39
-rw-r--r--drivers/net/pcs/pcs-rzn1-miic.c10
-rw-r--r--drivers/net/pcs/pcs-xpcs.c265
-rw-r--r--drivers/net/pcs/pcs-xpcs.h3
-rw-r--r--drivers/net/phy/Kconfig17
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/at803x.c91
-rw-r--r--drivers/net/phy/bcm-phy-lib.c264
-rw-r--r--drivers/net/phy/bcm-phy-lib.h10
-rw-r--r--drivers/net/phy/broadcom.c190
-rw-r--r--drivers/net/phy/dp83869.c13
-rw-r--r--drivers/net/phy/dp83td510.c23
-rw-r--r--drivers/net/phy/marvell10g.c7
-rw-r--r--drivers/net/phy/mediatek-ge-soc.c1116
-rw-r--r--drivers/net/phy/mediatek-ge.c3
-rw-r--r--drivers/net/phy/micrel.c334
-rw-r--r--drivers/net/phy/microchip_t1s.c274
-rw-r--r--drivers/net/phy/mscc/mscc.h1
-rw-r--r--drivers/net/phy/mscc/mscc_main.c51
-rw-r--r--drivers/net/phy/phy-c45.c9
-rw-r--r--drivers/net/phy/phy.c22
-rw-r--r--drivers/net/phy/phy_device.c55
-rw-r--r--drivers/net/phy/phylink.c209
-rw-r--r--drivers/net/phy/realtek.c34
-rw-r--r--drivers/net/phy/sfp-bus.c30
-rw-r--r--drivers/net/phy/sfp.c345
-rw-r--r--drivers/net/phy/sfp.h1
-rw-r--r--drivers/net/ppp/Kconfig34
-rw-r--r--drivers/net/ppp/pppoe.c2
-rw-r--r--drivers/net/ppp/pptp.c31
-rw-r--r--drivers/net/tap.c3
-rw-r--r--drivers/net/team/team.c13
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/usb/Kconfig10
-rw-r--r--drivers/net/usb/cdc_ether.c27
-rw-r--r--drivers/net/usb/ipheth.c186
-rw-r--r--drivers/net/usb/lan78xx.c7
-rw-r--r--drivers/net/usb/qmi_wwan.c2
-rw-r--r--drivers/net/usb/r8152.c4
-rw-r--r--drivers/net/usb/usbnet.c6
-rw-r--r--drivers/net/usb/zaurus.c21
-rw-r--r--drivers/net/veth.c40
-rw-r--r--drivers/net/virtio_net.c667
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c4
-rw-r--r--drivers/net/vrf.c12
-rw-r--r--drivers/net/vxlan/vxlan_core.c186
-rw-r--r--drivers/net/vxlan/vxlan_vnifilter.c11
-rw-r--r--drivers/net/wireguard/allowedips.c8
-rw-r--r--drivers/net/wireguard/device.c1
-rw-r--r--drivers/net/wireguard/netlink.c14
-rw-r--r--drivers/net/wireguard/queueing.c1
-rw-r--r--drivers/net/wireguard/queueing.h25
-rw-r--r--drivers/net/wireguard/receive.c2
-rw-r--r--drivers/net/wireguard/selftest/allowedips.c16
-rw-r--r--drivers/net/wireguard/send.c2
-rw-r--r--drivers/net/wireguard/timers.c10
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c34
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h2
-rw-r--r--drivers/net/wireless/ath/ath11k/ahb.c9
-rw-r--r--drivers/net/wireless/ath/ath11k/ce.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c89
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h16
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath11k/debug.h49
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c114
-rw-r--r--drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h43
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c22
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.c10
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.c24
-rw-r--r--drivers/net/wireless/ath/ath11k/htc.c42
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.c5
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c539
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c37
-rw-r--r--drivers/net/wireless/ath/ath11k/pcic.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/peer.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c76
-rw-r--r--drivers/net/wireless/ath/ath11k/reg.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.c387
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode.h6
-rw-r--r--drivers/net/wireless/ath/ath11k/testmode_i.h18
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c628
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h70
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c3
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c30
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c27
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.c16
-rw-r--r--drivers/net/wireless/ath/ath12k/hal.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c62
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c26
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c9
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c130
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h10
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile5
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.c24
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/fw.h4
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h6
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx_edma.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx_edma.h6
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h2
-rw-r--r--drivers/net/wireless/atmel/Kconfig2
-rw-r--r--drivers/net/wireless/atmel/at76c50x-usb.c8
-rw-r--r--drivers/net/wireless/atmel/atmel_cs.c13
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c6
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c4
-rw-r--r--drivers/net/wireless/cisco/airo.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/Makefile1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/1000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/2000.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/22000.c837
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/5000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/6000.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/7000.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/8000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/9000.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/ax210.c301
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c183
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/sc.c166
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/rs.c43
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.c121
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/acpi.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/binding.h14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/commands.h23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/config.h15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/context.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/d3.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/location.h16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h65
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/mac.h24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/offload.h3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/phy.h10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/power.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rs.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/rx.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/scan.h41
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/tx.h13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c72
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.h18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/debugfs.c35
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dump.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/file.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.c234
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/pnvm.h27
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.c272
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/uefi.h47
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h71
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h32
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-context-info.h5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c56
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.c75
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fh.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-io.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c155
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-prph.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-trans.h108
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/main.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/binding.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c420
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c202
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c48
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c23
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c93
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c122
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c200
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c99
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c177
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c28
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h107
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c63
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/offloading.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c16
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c15
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c56
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c77
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c10
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c46
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c163
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sf.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c90
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h20
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c150
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c273
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c528
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/internal.h12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/rx.c31
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c73
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c7
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/queue/tx.h8
-rw-r--r--drivers/net/wireless/intersil/hostap/Kconfig2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_cs.c13
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_usb.c12
-rw-r--r--drivers/net/wireless/intersil/orinoco/spectrum_cs.c13
-rw-r--r--drivers/net/wireless/intersil/p54/p54spi.c1
-rw-r--r--drivers/net/wireless/legacy/ray_cs.c33
-rw-r--r--drivers/net/wireless/legacy/rayctl.h2
-rw-r--r--drivers/net/wireless/legacy/rndis_wlan.c2
-rw-r--r--drivers/net/wireless/legacy/wl3501_cs.c16
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n.h4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/debugfs.c9
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c8
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c25
-rw-r--r--drivers/net/wireless/marvell/mwifiex/scan.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_rx.c12
-rw-r--r--drivers/net/wireless/marvell/mwifiex/tdls.c9
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_txrx.c30
-rw-r--r--drivers/net/wireless/marvell/mwifiex/util.c10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/wmm.h15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7603/Kconfig2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/Kconfig2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c18
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/Kconfig2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/init.c7
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/main.c93
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mcu.c105
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mmio.c30
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h15
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/dma.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/init.c3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mac.c4
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/mcu.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/pci.c8
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/Kconfig2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/dma.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mac.c13
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mcu.c11
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h1
-rw-r--r--drivers/net/wireless/mediatek/mt76/testmode.c1
-rw-r--r--drivers/net/wireless/mediatek/mt76/tx.c9
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/Kconfig2
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/debugfs.c2
-rw-r--r--drivers/net/wireless/mediatek/mt7601u/trace.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.c8
-rw-r--r--drivers/net/wireless/microchip/wilc1000/hif.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan_cfg.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/wlan_if.h2
-rw-r--r--drivers/net/wireless/purelifi/plfxlc/Kconfig2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/Kconfig2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00link.c2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Kconfig3
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h84
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c3
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c25
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c28
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c2090
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c37
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c5
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c567
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h52
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c20
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c10
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c41
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c56
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c40
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c16
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c14
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c60
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c42
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h29
-rw-r--r--drivers/net/wireless/realtek/rtw88/Kconfig11
-rw-r--r--drivers/net/wireless/realtek/rtw88/Makefile3
-rw-r--r--drivers/net/wireless/realtek/rtw88/debug.c59
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.c68
-rw-r--r--drivers/net/wireless/realtek/rtw88/fw.h13
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/mac80211.c13
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.c19
-rw-r--r--drivers/net/wireless/realtek/rtw88/main.h1
-rw-r--r--drivers/net/wireless/realtek/rtw88/pci.c7
-rw-r--r--drivers/net/wireless/realtek/rtw88/ps.c3
-rw-r--r--drivers/net/wireless/realtek/rtw88/reg.h2
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.c15
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723d.h6
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8723ds.c41
-rw-r--r--drivers/net/wireless/realtek/rtw88/sdio.c24
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.c94
-rw-r--r--drivers/net/wireless/realtek/rtw88/tx.h124
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c24
-rw-r--r--drivers/net/wireless/realtek/rtw89/Kconfig14
-rw-r--r--drivers/net/wireless/realtek/rtw89/Makefile12
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.c52
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.h21
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c9
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c261
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h217
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c73
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.c21
-rw-r--r--drivers/net/wireless/realtek/rtw89/efuse.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c202
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h281
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c162
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c16
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c27
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c344
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h12
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h134
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c324
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c2442
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.h76
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c3621
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h28
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.c252
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851be.c86
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c36
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c12
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c11
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.c27992
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_table.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c48
-rw-r--r--drivers/net/wireless/realtek/rtw89/txrx.h176
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c9
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c25
-rw-r--r--drivers/net/wireless/zydas/zd1201.c6
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_imem.h15
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_mux.h4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_pcie.c4
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_port.c17
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_trace.c8
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_wwan.c23
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_cldma.c13
-rw-r--r--drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c5
-rw-r--r--drivers/net/xen-netback/netback.c21
1051 files changed, 65575 insertions, 19303 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d0a1ed216d15..368c6f5b327e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -403,7 +403,6 @@ config TUN_VNET_CROSS_LE
config VETH
tristate "Virtual ethernet pair device"
select PAGE_POOL
- select PAGE_POOL_STATS
help
This device is a local ethernet tunnel. Devices are created in pairs.
When one end receives the packet it appears on its pair and vice
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 1bad1866ae46..d9e052c49ba1 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -196,13 +196,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
{
struct arcnet_local *lp = netdev_priv(dev);
- unsigned long led_delay = 350;
- unsigned long tx_delay = 50;
switch (event) {
case ARCNET_LED_EVENT_RECON:
- led_trigger_blink_oneshot(lp->recon_led_trig,
- &led_delay, &led_delay, 0);
+ led_trigger_blink_oneshot(lp->recon_led_trig, 350, 350, 0);
break;
case ARCNET_LED_EVENT_OPEN:
led_trigger_event(lp->tx_led_trig, LED_OFF);
@@ -213,8 +210,7 @@ void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
led_trigger_event(lp->recon_led_trig, LED_OFF);
break;
case ARCNET_LED_EVENT_TX:
- led_trigger_blink_oneshot(lp->tx_led_trig,
- &tx_delay, &tx_delay, 0);
+ led_trigger_blink_oneshot(lp->tx_led_trig, 50, 50, 0);
break;
}
}
@@ -468,7 +464,7 @@ static void arcnet_reply_tasklet(struct tasklet_struct *t)
ret = sock_queue_err_skb(sk, ackskb);
if (ret)
- kfree_skb(ackskb);
+ dev_kfree_skb_irq(ackskb);
local_irq_enable();
};
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index b9dbad3a8af8..fc5da5d7744d 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -660,10 +660,10 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
return NULL;
arp = (struct arp_pkt *)skb_network_header(skb);
- /* Don't modify or load balance ARPs that do not originate locally
- * (e.g.,arrive via a bridge).
+ /* Don't modify or load balance ARPs that do not originate
+ * from the bond itself or a VLAN directly above the bond.
*/
- if (!bond_slave_has_mac_rx(bond, arp->mac_src))
+ if (!bond_slave_has_mac_rcu(bond, arp->mac_src))
return NULL;
dev = ip_dev_find(dev_net(bond->dev), arp->ip_src);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index edbaa1444f8e..447b06ea4fc9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1,8 +1,9 @@
+// SPDX-License-Identifier: GPL-1.0+
/*
* originally based on the dummy device.
*
* Copyright 1999, Thomas Davis, tadavis@lbl.gov.
- * Licensed under the GPL. Based on dummy.c, and eql.c devices.
+ * Based on dummy.c, and eql.c devices.
*
* bonding.c: an Ethernet Bonding driver
*
@@ -1507,6 +1508,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
memcpy(bond_dev->broadcast, slave_dev->broadcast,
slave_dev->addr_len);
+
+ if (slave_dev->flags & IFF_POINTOPOINT) {
+ bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+ bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+ }
}
/* On bonding slaves other than the currently active slave, suppress
@@ -2871,6 +2877,8 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
return ret;
}
+#define BOND_VLAN_PROTO_NONE cpu_to_be16(0xffff)
+
static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags,
struct sk_buff *skb)
{
@@ -2878,13 +2886,13 @@ static bool bond_handle_vlan(struct slave *slave, struct bond_vlan_tag *tags,
struct net_device *slave_dev = slave->dev;
struct bond_vlan_tag *outer_tag = tags;
- if (!tags || tags->vlan_proto == VLAN_N_VID)
+ if (!tags || tags->vlan_proto == BOND_VLAN_PROTO_NONE)
return true;
tags++;
/* Go through all the tags backwards and add them to the packet */
- while (tags->vlan_proto != VLAN_N_VID) {
+ while (tags->vlan_proto != BOND_VLAN_PROTO_NONE) {
if (!tags->vlan_id) {
tags++;
continue;
@@ -2960,7 +2968,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
tags = kcalloc(level + 1, sizeof(*tags), GFP_ATOMIC);
if (!tags)
return ERR_PTR(-ENOMEM);
- tags[level].vlan_proto = VLAN_N_VID;
+ tags[level].vlan_proto = BOND_VLAN_PROTO_NONE;
return tags;
}
@@ -4197,7 +4205,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
return skb->hash;
return __bond_xmit_hash(bond, skb, skb->data, skb->protocol,
- skb_mac_offset(skb), skb_network_offset(skb),
+ 0, skb_network_offset(skb),
skb_headlen(skb));
}
@@ -5439,7 +5447,7 @@ static netdev_tx_t bond_tls_device_xmit(struct bonding *bond, struct sk_buff *sk
{
struct net_device *tls_netdev = rcu_dereference(tls_get_ctx(skb->sk)->netdev);
- /* tls_netdev might become NULL, even if tls_is_sk_tx_device_offloaded
+ /* tls_netdev might become NULL, even if tls_is_skb_tx_device_offloaded
* was true, if tls_device_down is running in parallel, but it's OK,
* because bond_get_slave_by_dev has a NULL check.
*/
@@ -5458,7 +5466,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
return NETDEV_TX_OK;
#if IS_ENABLED(CONFIG_TLS_DEVICE)
- if (skb->sk && tls_is_sk_tx_device_offloaded(skb->sk))
+ if (tls_is_skb_tx_device_offloaded(skb))
return bond_tls_device_xmit(bond, skb, dev);
#endif
@@ -5893,7 +5901,9 @@ void bond_setup(struct net_device *bond_dev)
bond_dev->hw_features = BOND_VLAN_FEATURES |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER;
+ NETIF_F_HW_VLAN_CTAG_FILTER |
+ NETIF_F_HW_VLAN_STAG_RX |
+ NETIF_F_HW_VLAN_STAG_FILTER;
bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
bond_dev->features |= bond_dev->hw_features;
diff --git a/drivers/net/bonding/bonding_priv.h b/drivers/net/bonding/bonding_priv.h
index 48cdf3a49a7d..fef6288c6944 100644
--- a/drivers/net/bonding/bonding_priv.h
+++ b/drivers/net/bonding/bonding_priv.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-1.0+ */
/*
* Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
*
@@ -7,9 +8,6 @@
* BUT, I'm the one who modified it for ethernet, so:
* (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
*
- * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
- *
*/
#ifndef _BONDING_PRIV_H
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index b190007c01be..e626de33e735 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -153,8 +153,7 @@ config CAN_JANZ_ICAN3
config CAN_KVASER_PCIEFD
depends on PCI
tristate "Kvaser PCIe FD cards"
- select CRC32
- help
+ help
This is a driver for the Kvaser PCI Express CAN FD family.
Supported devices:
@@ -186,10 +185,10 @@ config CAN_SLCAN
config CAN_SUN4I
tristate "Allwinner A10 CAN controller"
- depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
+ depends on MACH_SUN4I || MACH_SUN7I || RISCV || COMPILE_TEST
help
Say Y here if you want to use CAN controller found on Allwinner
- A10/A20 SoCs.
+ A10/A20/D1 SoCs.
To compile this driver as a module, choose M here: the module will
be called sun4i_can.
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 199cb200f2bd..4621266851ed 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -1346,7 +1346,7 @@ static int at91_can_probe(struct platform_device *pdev)
return err;
}
-static int at91_can_remove(struct platform_device *pdev)
+static void at91_can_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct at91_priv *priv = netdev_priv(dev);
@@ -1362,8 +1362,6 @@ static int at91_can_remove(struct platform_device *pdev)
clk_put(priv->clk);
free_candev(dev);
-
- return 0;
}
static const struct platform_device_id at91_can_id_table[] = {
@@ -1381,7 +1379,7 @@ MODULE_DEVICE_TABLE(platform, at91_can_id_table);
static struct platform_driver at91_can_driver = {
.probe = at91_can_probe,
- .remove = at91_can_remove,
+ .remove_new = at91_can_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(at91_can_dt_ids),
diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c
index 027a8a162fe4..39de7164bc4e 100644
--- a/drivers/net/can/bxcan.c
+++ b/drivers/net/can/bxcan.c
@@ -966,22 +966,16 @@ static int bxcan_probe(struct platform_device *pdev)
}
rx_irq = platform_get_irq_byname(pdev, "rx0");
- if (rx_irq < 0) {
- dev_err(dev, "failed to get rx0 irq\n");
+ if (rx_irq < 0)
return rx_irq;
- }
tx_irq = platform_get_irq_byname(pdev, "tx");
- if (tx_irq < 0) {
- dev_err(dev, "failed to get tx irq\n");
+ if (tx_irq < 0)
return tx_irq;
- }
sce_irq = platform_get_irq_byname(pdev, "sce");
- if (sce_irq < 0) {
- dev_err(dev, "failed to get sce irq\n");
+ if (sce_irq < 0)
return sce_irq;
- }
ndev = alloc_candev(sizeof(struct bxcan_priv), BXCAN_TX_MB_NUM);
if (!ndev) {
@@ -1039,7 +1033,7 @@ out_free_candev:
return err;
}
-static int bxcan_remove(struct platform_device *pdev)
+static void bxcan_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct bxcan_priv *priv = netdev_priv(ndev);
@@ -1048,7 +1042,6 @@ static int bxcan_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clk);
can_rx_offload_del(&priv->offload);
free_candev(ndev);
- return 0;
}
static int __maybe_unused bxcan_suspend(struct device *dev)
@@ -1100,7 +1093,7 @@ static struct platform_driver bxcan_driver = {
.of_match_table = bxcan_of_match,
},
.probe = bxcan_probe,
- .remove = bxcan_remove,
+ .remove_new = bxcan_remove,
};
module_platform_driver(bxcan_driver);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 03ccb7cfacaf..925930b6c4ca 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -410,7 +410,7 @@ exit:
return ret;
}
-static int c_can_plat_remove(struct platform_device *pdev)
+static void c_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct c_can_priv *priv = netdev_priv(dev);
@@ -418,8 +418,6 @@ static int c_can_plat_remove(struct platform_device *pdev)
unregister_c_can_dev(dev);
pm_runtime_disable(priv->device);
free_c_can_dev(dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -487,7 +485,7 @@ static struct platform_driver c_can_plat_driver = {
.of_match_table = c_can_of_table,
},
.probe = c_can_plat_probe,
- .remove = c_can_plat_remove,
+ .remove_new = c_can_plat_remove,
.suspend = c_can_suspend,
.resume = c_can_resume,
.id_table = c_can_id_table,
diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
index 8f6dccd5a587..22009440a983 100644
--- a/drivers/net/can/cc770/cc770_isa.c
+++ b/drivers/net/can/cc770/cc770_isa.c
@@ -285,7 +285,7 @@ exit:
return err;
}
-static int cc770_isa_remove(struct platform_device *pdev)
+static void cc770_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -303,13 +303,11 @@ static int cc770_isa_remove(struct platform_device *pdev)
release_region(port[idx], CC770_IOSIZE);
}
free_cc770dev(dev);
-
- return 0;
}
static struct platform_driver cc770_isa_driver = {
.probe = cc770_isa_probe,
- .remove = cc770_isa_remove,
+ .remove_new = cc770_isa_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index 8dcc32e4e30e..13bcfba05f18 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -230,7 +230,7 @@ exit_release_mem:
return err;
}
-static int cc770_platform_remove(struct platform_device *pdev)
+static void cc770_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct cc770_priv *priv = netdev_priv(dev);
@@ -242,8 +242,6 @@ static int cc770_platform_remove(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
-
- return 0;
}
static const struct of_device_id cc770_platform_table[] = {
@@ -259,7 +257,7 @@ static struct platform_driver cc770_platform_driver = {
.of_match_table = cc770_platform_table,
},
.probe = cc770_platform_probe,
- .remove = cc770_platform_remove,
+ .remove_new = cc770_platform_remove,
};
module_platform_driver(cc770_platform_driver);
diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c
index a17561d97192..55bb10b157b4 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_platform.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c
@@ -86,7 +86,7 @@ err:
* This function frees all the resources allocated to the device.
* Return: 0 always
*/
-static int ctucan_platform_remove(struct platform_device *pdev)
+static void ctucan_platform_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ctucan_priv *priv = netdev_priv(ndev);
@@ -97,8 +97,6 @@ static int ctucan_platform_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
netif_napi_del(&priv->napi);
free_candev(ndev);
-
- return 0;
}
static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume);
@@ -113,7 +111,7 @@ MODULE_DEVICE_TABLE(of, ctucan_of_match);
static struct platform_driver ctucanfd_driver = {
.probe = ctucan_platform_probe,
- .remove = ctucan_platform_remove,
+ .remove_new = ctucan_platform_remove,
.driver = {
.name = DRV_NAME,
.pm = &ctucan_platform_pm_ops,
diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
index b48140b1102e..b7f4d76dd444 100644
--- a/drivers/net/can/dev/length.c
+++ b/drivers/net/can/dev/length.c
@@ -78,18 +78,7 @@ unsigned int can_skb_get_frame_len(const struct sk_buff *skb)
else
len = cf->len;
- if (can_is_canfd_skb(skb)) {
- if (cf->can_id & CAN_EFF_FLAG)
- len += CANFD_FRAME_OVERHEAD_EFF;
- else
- len += CANFD_FRAME_OVERHEAD_SFF;
- } else {
- if (cf->can_id & CAN_EFF_FLAG)
- len += CAN_FRAME_OVERHEAD_EFF;
- else
- len += CAN_FRAME_OVERHEAD_SFF;
- }
-
- return len;
+ return can_frame_bytes(can_is_canfd_skb(skb), cf->can_id & CAN_EFF_FLAG,
+ false, len);
}
EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index 81ebf0562c89..161e45a7e8c1 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -220,7 +220,7 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
- struct sk_buff *skb, u32 timestamp)
+ struct sk_buff *skb, u32 timestamp)
{
struct can_rx_offload_cb *cb;
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index 6d638c93977b..ff0fc18baf13 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev)
return err;
}
-static int flexcan_remove(struct platform_device *pdev)
+static void flexcan_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
@@ -2227,8 +2227,6 @@ static int flexcan_remove(struct platform_device *pdev)
unregister_flexcandev(dev);
pm_runtime_disable(&pdev->dev);
free_candev(dev);
-
- return 0;
}
static int __maybe_unused flexcan_suspend(struct device *device)
@@ -2379,7 +2377,7 @@ static struct platform_driver flexcan_driver = {
.of_match_table = flexcan_of_match,
},
.probe = flexcan_probe,
- .remove = flexcan_remove,
+ .remove_new = flexcan_remove,
.id_table = flexcan_id_table,
};
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 4bedcc3eea0d..3174efdae271 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1696,7 +1696,7 @@ exit_error:
return err;
}
-static int grcan_remove(struct platform_device *ofdev)
+static void grcan_remove(struct platform_device *ofdev)
{
struct net_device *dev = platform_get_drvdata(ofdev);
struct grcan_priv *priv = netdev_priv(dev);
@@ -1706,8 +1706,6 @@ static int grcan_remove(struct platform_device *ofdev)
irq_dispose_mapping(dev->irq);
netif_napi_del(&priv->napi);
free_candev(dev);
-
- return 0;
}
static const struct of_device_id grcan_match[] = {
@@ -1726,7 +1724,7 @@ static struct platform_driver grcan_driver = {
.of_match_table = grcan_match,
},
.probe = grcan_probe,
- .remove = grcan_remove,
+ .remove_new = grcan_remove,
};
module_platform_driver(grcan_driver);
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index 07eaf724a572..1d6642c94f2f 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -1013,15 +1013,13 @@ err_reg:
return ret;
}
-static int ifi_canfd_plat_remove(struct platform_device *pdev)
+static void ifi_canfd_plat_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
unregister_candev(ndev);
platform_set_drvdata(pdev, NULL);
free_candev(ndev);
-
- return 0;
}
static const struct of_device_id ifi_canfd_of_table[] = {
@@ -1036,7 +1034,7 @@ static struct platform_driver ifi_canfd_plat_driver = {
.of_match_table = ifi_canfd_of_table,
},
.probe = ifi_canfd_plat_probe,
- .remove = ifi_canfd_plat_remove,
+ .remove_new = ifi_canfd_plat_remove,
};
module_platform_driver(ifi_canfd_plat_driver);
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index 0732a5092141..d048ea565b89 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -2023,7 +2023,7 @@ out_return:
return ret;
}
-static int ican3_remove(struct platform_device *pdev)
+static void ican3_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ican3_dev *mod = netdev_priv(ndev);
@@ -2042,8 +2042,6 @@ static int ican3_remove(struct platform_device *pdev)
iounmap(mod->dpm);
free_candev(ndev);
-
- return 0;
}
static struct platform_driver ican3_driver = {
@@ -2051,7 +2049,7 @@ static struct platform_driver ican3_driver = {
.name = DRV_NAME,
},
.probe = ican3_probe,
- .remove = ican3_remove,
+ .remove_new = ican3_remove,
};
module_platform_driver(ican3_driver);
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index be189edb256c..db6256f2b1b3 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -3,19 +3,19 @@
* Parts of this driver are based on the following:
* - Kvaser linux pciefd driver (version 5.25)
* - PEAK linux canfd driver
- * - Altera Avalon EPCS flash controller driver
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/bitfield.h>
+#include <linux/can/dev.h>
#include <linux/device.h>
#include <linux/ethtool.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <linux/can/dev.h>
#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/crc32.h>
-#include <linux/iopoll.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Kvaser AB <support@kvaser.com>");
@@ -25,42 +25,25 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000)
#define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200))
-#define KVASER_PCIEFD_MAX_ERR_REP 256
-#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17
-#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4
-#define KVASER_PCIEFD_DMA_COUNT 2
+#define KVASER_PCIEFD_MAX_ERR_REP 256U
+#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U
+#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL
+#define KVASER_PCIEFD_DMA_COUNT 2U
-#define KVASER_PCIEFD_DMA_SIZE (4 * 1024)
-#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0)
+#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U)
#define KVASER_PCIEFD_VENDOR 0x1a07
-#define KVASER_PCIEFD_4HS_ID 0x0d
-#define KVASER_PCIEFD_2HS_ID 0x0e
-#define KVASER_PCIEFD_HS_ID 0x0f
-#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10
-#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11
+#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d
+#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e
+#define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f
+#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010
+#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011
/* PCIe IRQ registers */
#define KVASER_PCIEFD_IRQ_REG 0x40
#define KVASER_PCIEFD_IEN_REG 0x50
-/* DMA map */
+/* DMA address translation map register base */
#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000
-/* Kvaser KCAN CAN controller registers */
-#define KVASER_PCIEFD_KCAN0_BASE 0x10000
-#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
-#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
-#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
-#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
-#define KVASER_PCIEFD_KCAN_CMD_REG 0x400
-#define KVASER_PCIEFD_KCAN_IEN_REG 0x408
-#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
-#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414
-#define KVASER_PCIEFD_KCAN_STAT_REG 0x418
-#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
-#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
-#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
-#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
-#define KVASER_PCIEFD_KCAN_PWM_REG 0x430
/* Loopback control register */
#define KVASER_PCIEFD_LOOP_REG 0x1f000
/* System identification and information registers */
@@ -78,183 +61,196 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
-/* EPCS flash controller registers */
-#define KVASER_PCIEFD_SPI_BASE 0x1fc00
-#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE
-#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4)
-#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8)
-#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc)
-#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14)
-
-#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f
+/* Kvaser KCAN CAN controller registers */
+#define KVASER_PCIEFD_KCAN0_BASE 0x10000
+#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
+#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
+#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
+#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
+#define KVASER_PCIEFD_KCAN_CMD_REG 0x400
+#define KVASER_PCIEFD_KCAN_IEN_REG 0x408
+#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414
+#define KVASER_PCIEFD_KCAN_STAT_REG 0x418
+#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
+#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
+#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
+#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
+#define KVASER_PCIEFD_KCAN_PWM_REG 0x430
+
+/* PCI interrupt fields */
#define KVASER_PCIEFD_IRQ_SRB BIT(4)
+#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0)
-#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24
-#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16
-#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1
+/* Enable 64-bit DMA address translation */
+#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0)
+
+/* System build information fields */
+#define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24)
+#define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16)
+#define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0)
+#define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1)
/* Reset DMA buffer 0, 1 and FIFO offset */
-#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
#define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5)
+#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
#define KVASER_PCIEFD_SRB_CMD_FOR BIT(0)
-/* DMA packet done, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
-#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
-/* DMA overflow, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
-#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
/* DMA underflow, buffer 0 and 1 */
-#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
#define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13)
+#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
+/* DMA overflow, buffer 0 and 1 */
+#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
+#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
+/* DMA packet done, buffer 0 and 1 */
+#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
+#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
+/* Got DMA support */
+#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
/* DMA idle */
#define KVASER_PCIEFD_SRB_STAT_DI BIT(15)
-/* DMA support */
-#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
/* SRB current packet level */
-#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0)
/* DMA Enable */
#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
-/* EPCS flash controller definitions */
-#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024)
-#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L)
-#define KVASER_PCIEFD_CFG_MAX_PARAMS 256
-#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d
-#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24
-#define KVASER_PCIEFD_CFG_SYS_VER 1
-#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130
-#define KVASER_PCIEFD_SPI_TMT BIT(5)
-#define KVASER_PCIEFD_SPI_TRDY BIT(6)
-#define KVASER_PCIEFD_SPI_RRDY BIT(7)
-#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14
-/* Commands for controlling the onboard flash */
-#define KVASER_PCIEFD_FLASH_RES_CMD 0xab
-#define KVASER_PCIEFD_FLASH_READ_CMD 0x3
-#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5
-
-/* Kvaser KCAN definitions */
-#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29)
-#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29)
-
-#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16
-/* Request status packet */
-#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
+/* KCAN CTRL packet types */
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29)
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4
+#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5
+
+/* Command sequence number */
+#define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16)
+/* Command bits */
+#define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0)
/* Abort, flush and reset */
#define KVASER_PCIEFD_KCAN_CMD_AT BIT(1)
+/* Request status packet */
+#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
-/* Tx FIFO unaligned read */
-#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
-/* Tx FIFO unaligned end */
-#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
-/* Bus parameter protection error */
-#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
-/* FDF bit when controller is in classic mode */
-#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
-/* Rx FIFO overflow */
-#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
-/* Abort done */
-#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
-/* Tx buffer flush done */
-#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
-/* Tx FIFO overflow */
-#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
-/* Tx FIFO empty */
-#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
/* Transmitter unaligned */
#define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17)
+/* Tx FIFO empty */
+#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
+/* Tx FIFO overflow */
+#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
+/* Tx buffer flush done */
+#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
+/* Abort done */
+#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
+/* Rx FIFO overflow */
+#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
+/* FDF bit when controller is in classic CAN mode */
+#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
+/* Bus parameter protection error */
+#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
+/* Tx FIFO unaligned end */
+#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
+/* Tx FIFO unaligned read */
+#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
-#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16
+/* Tx FIFO size */
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16)
+/* Tx FIFO current packet level */
+#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0)
-#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24
-/* Abort request */
-#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
-/* Idle state. Controller in reset mode and no abort or flush pending */
-#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
-/* Bus off */
-#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
-/* Reset mode request */
-#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
-/* Controller in reset mode */
-#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
-/* Controller got one-shot capability */
-#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
+/* Current status packet sequence number */
+#define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24)
/* Controller got CAN FD capability */
#define KVASER_PCIEFD_KCAN_STAT_FD BIT(19)
-#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \
- KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \
- KVASER_PCIEFD_KCAN_STAT_IRM)
+/* Controller got one-shot capability */
+#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
+/* Controller in reset mode */
+#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
+/* Reset mode request */
+#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
+/* Bus off */
+#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
+/* Idle state. Controller in reset mode and no abort or flush pending */
+#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
+/* Abort request */
+#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
+/* Controller is bus off */
+#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \
+ (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \
+ KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM)
-/* Reset mode */
-#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
-/* Listen only mode */
-#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
-/* Error packet enable */
-#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
-/* CAN FD non-ISO */
-#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
-/* Acknowledgment packet type */
-#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
-/* Active error flag enable. Clear to force error passive */
-#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
/* Classic CAN mode */
#define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31)
+/* Active error flag enable. Clear to force error passive */
+#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
+/* Acknowledgment packet type */
+#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
+/* CAN FD non-ISO */
+#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
+/* Error packet enable */
+#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
+/* Listen only mode */
+#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
+/* Reset mode */
+#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
-#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13
-#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17
-#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26
-
-#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16
-
-/* Kvaser KCAN packet types */
-#define KVASER_PCIEFD_PACK_TYPE_DATA 0
-#define KVASER_PCIEFD_PACK_TYPE_ACK 1
-#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2
-#define KVASER_PCIEFD_PACK_TYPE_ERROR 3
-#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4
-#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5
-#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6
-#define KVASER_PCIEFD_PACK_TYPE_STATUS 8
-#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9
-
-/* Kvaser KCAN packet common definitions */
-#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff
-#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25
-#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28
-
-/* Kvaser KCAN TDATA and RDATA first word */
+/* BTRN and BTRD fields */
+#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26)
+#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17)
+#define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13)
+#define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0)
+
+/* PWM Control fields */
+#define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16)
+#define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0)
+
+/* KCAN packet type IDs */
+#define KVASER_PCIEFD_PACK_TYPE_DATA 0x0
+#define KVASER_PCIEFD_PACK_TYPE_ACK 0x1
+#define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2
+#define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3
+#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4
+#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5
+#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6
+#define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8
+#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9
+
+/* Common KCAN packet definitions, second word */
+#define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28)
+#define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25)
+#define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0)
+
+/* KCAN Transmit/Receive data packet, first word */
#define KVASER_PCIEFD_RPACKET_IDE BIT(30)
#define KVASER_PCIEFD_RPACKET_RTR BIT(29)
-/* Kvaser KCAN TDATA and RDATA second word */
-#define KVASER_PCIEFD_RPACKET_ESI BIT(13)
-#define KVASER_PCIEFD_RPACKET_BRS BIT(14)
-#define KVASER_PCIEFD_RPACKET_FDF BIT(15)
-#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8
-/* Kvaser KCAN TDATA second word */
-#define KVASER_PCIEFD_TPACKET_SMS BIT(16)
+#define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0)
+/* KCAN Transmit data packet, second word */
#define KVASER_PCIEFD_TPACKET_AREQ BIT(31)
+#define KVASER_PCIEFD_TPACKET_SMS BIT(16)
+/* KCAN Transmit/Receive data packet, second word */
+#define KVASER_PCIEFD_RPACKET_FDF BIT(15)
+#define KVASER_PCIEFD_RPACKET_BRS BIT(14)
+#define KVASER_PCIEFD_RPACKET_ESI BIT(13)
+#define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8)
-/* Kvaser KCAN APACKET */
-#define KVASER_PCIEFD_APACKET_FLU BIT(8)
-#define KVASER_PCIEFD_APACKET_CT BIT(9)
-#define KVASER_PCIEFD_APACKET_ABL BIT(10)
+/* KCAN Transmit acknowledge packet, first word */
#define KVASER_PCIEFD_APACKET_NACK BIT(11)
+#define KVASER_PCIEFD_APACKET_ABL BIT(10)
+#define KVASER_PCIEFD_APACKET_CT BIT(9)
+#define KVASER_PCIEFD_APACKET_FLU BIT(8)
-/* Kvaser KCAN SPACK first word */
-#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8
-#define KVASER_PCIEFD_SPACK_BOFF BIT(16)
-#define KVASER_PCIEFD_SPACK_IDET BIT(20)
-#define KVASER_PCIEFD_SPACK_IRM BIT(21)
+/* KCAN Status packet, first word */
#define KVASER_PCIEFD_SPACK_RMCD BIT(22)
-/* Kvaser KCAN SPACK second word */
-#define KVASER_PCIEFD_SPACK_AUTO BIT(21)
-#define KVASER_PCIEFD_SPACK_EWLR BIT(23)
+#define KVASER_PCIEFD_SPACK_IRM BIT(21)
+#define KVASER_PCIEFD_SPACK_IDET BIT(20)
+#define KVASER_PCIEFD_SPACK_BOFF BIT(16)
+#define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8)
+#define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0)
+/* KCAN Status packet, second word */
#define KVASER_PCIEFD_SPACK_EPLR BIT(24)
+#define KVASER_PCIEFD_SPACK_EWLR BIT(23)
+#define KVASER_PCIEFD_SPACK_AUTO BIT(21)
-/* Kvaser KCAN_EPACK second word */
+/* KCAN Error detected packet, second word */
#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
struct kvaser_pciefd;
@@ -306,195 +302,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
.brp_inc = 1,
};
-struct kvaser_pciefd_cfg_param {
- __le32 magic;
- __le32 nr;
- __le32 len;
- u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ];
-};
-
-struct kvaser_pciefd_cfg_img {
- __le32 version;
- __le32 magic;
- __le32 crc;
- struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS];
-};
-
static struct pci_device_id kvaser_pciefd_id_table[] = {
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), },
- { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), },
- { 0,},
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID),
+ },
+ {
+ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
+ },
+ {
+ 0,
+ },
};
MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
-/* Onboard flash memory functions */
-static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk)
-{
- u32 res;
-
- return readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG,
- res, res & msk, 0, 10);
-}
-
-static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx,
- u32 tx_len, u8 *rx, u32 rx_len)
-{
- int c;
-
- iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG);
- iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
- ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
-
- c = tx_len;
- while (c--) {
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
- return -EIO;
-
- iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
- return -EIO;
-
- ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
- }
-
- c = rx_len;
- while (c-- > 0) {
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
- return -EIO;
-
- iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
- return -EIO;
-
- *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
- }
-
- if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT))
- return -EIO;
-
- iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
-
- if (c != -1) {
- dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_cfg_img *img)
-{
- int offset = KVASER_PCIEFD_CFG_IMG_OFFSET;
- int res, crc;
- u8 *crc_buff;
-
- u8 cmd[] = {
- KVASER_PCIEFD_FLASH_READ_CMD,
- (u8)((offset >> 16) & 0xff),
- (u8)((offset >> 8) & 0xff),
- (u8)(offset & 0xff)
- };
-
- res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img,
- KVASER_PCIEFD_CFG_IMG_SZ);
- if (res)
- return res;
-
- crc_buff = (u8 *)img->params;
-
- if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) {
- dev_err(&pcie->pci->dev,
- "Config flash corrupted, version number is wrong\n");
- return -ENODEV;
- }
-
- if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) {
- dev_err(&pcie->pci->dev,
- "Config flash corrupted, magic number is wrong\n");
- return -ENODEV;
- }
-
- crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params));
- if (le32_to_cpu(img->crc) != crc) {
- dev_err(&pcie->pci->dev,
- "Stored CRC does not match flash image contents\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_cfg_img *img)
+static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd)
{
- struct kvaser_pciefd_cfg_param *param;
-
- param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN];
- memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len));
+ iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq),
+ can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
}
-static int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie)
+static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
{
- int res;
- struct kvaser_pciefd_cfg_img *img;
-
- /* Read electronic signature */
- u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0};
-
- res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1);
- if (res)
- return -EIO;
-
- img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL);
- if (!img)
- return -ENOMEM;
-
- if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) {
- dev_err(&pcie->pci->dev,
- "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n",
- cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16);
-
- res = -ENODEV;
- goto image_free;
- }
-
- cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD;
- res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1);
- if (res) {
- goto image_free;
- } else if (cmd[0] & 1) {
- res = -EIO;
- /* No write is ever done, the WIP should never be set */
- dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n");
- goto image_free;
- }
-
- res = kvaser_pciefd_cfg_read_and_verify(pcie, img);
- if (res) {
- res = -EIO;
- goto image_free;
- }
-
- kvaser_pciefd_cfg_read_params(pcie, img);
-
-image_free:
- kfree(img);
- return res;
+ kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ);
}
-static void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
+static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can)
{
- u32 cmd;
-
- cmd = KVASER_PCIEFD_KCAN_CMD_SRQ;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT);
}
static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can)
@@ -523,7 +367,7 @@ static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
spin_unlock_irqrestore(&can->lock, irq);
}
-static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
+static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
{
u32 msk;
@@ -534,8 +378,13 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
KVASER_PCIEFD_KCAN_IRQ_TAR;
iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+}
- return 0;
+static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie,
+ struct sk_buff *skb, u64 timestamp)
+{
+ skb_hwtstamps(skb)->hwtstamp =
+ ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div));
}
static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
@@ -544,7 +393,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
unsigned long irq;
spin_lock_irqsave(&can->lock, irq);
-
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
if (can->can.ctrlmode & CAN_CTRLMODE_FD) {
mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM;
@@ -561,7 +409,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
else
mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
-
mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
/* Use ACK packet type */
@@ -578,18 +425,13 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
unsigned long irq;
spin_lock_irqsave(&can->lock, irq);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
-
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
- u32 cmd;
-
/* If controller is already idle, run abort, flush and reset */
- cmd = KVASER_PCIEFD_KCAN_CMD_AT;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_abort_flush_reset(can);
} else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) {
u32 mode;
@@ -598,7 +440,6 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
mode |= KVASER_PCIEFD_KCAN_MODE_RM;
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
}
-
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -608,7 +449,6 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
unsigned long irq;
del_timer(&can->bec_poll_timer);
-
if (!completion_done(&can->flush_comp))
kvaser_pciefd_start_controller_flush(can);
@@ -620,11 +460,9 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
spin_lock_irqsave(&can->lock, irq);
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
-
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
@@ -637,11 +475,10 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
}
/* Reset interrupt handling */
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
kvaser_pciefd_set_tx_irq(can);
kvaser_pciefd_setup_controller(can);
-
can->can.state = CAN_STATE_ERROR_ACTIVE;
netif_wake_queue(can->can.dev);
can->bec.txerr = 0;
@@ -659,10 +496,9 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
spin_lock_irqsave(&can->lock, irq);
pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
- top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
-
+ top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl);
/* Set duty cycle to zero */
- pwm_ctrl |= top;
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -675,18 +511,17 @@ static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
kvaser_pciefd_pwm_stop(can);
spin_lock_irqsave(&can->lock, irq);
-
- /* Set frequency to 500 KHz*/
+ /* Set frequency to 500 KHz */
top = can->kv_pcie->bus_freq / (2 * 500000) - 1;
- pwm_ctrl = top & 0xff;
- pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
+ pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
/* Set duty cycle to 95 */
trigger = (100 * top - 95 * (top + 1) + 50) / 100;
- pwm_ctrl = trigger & 0xff;
- pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
+ pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger);
+ pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
spin_unlock_irqrestore(&can->lock, irq);
}
@@ -741,7 +576,6 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
int seq = can->echo_idx;
memset(p, 0, sizeof(*p));
-
if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
p->header[1] |= KVASER_PCIEFD_TPACKET_SMS;
@@ -751,19 +585,24 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
if (cf->can_id & CAN_EFF_FLAG)
p->header[0] |= KVASER_PCIEFD_RPACKET_IDE;
- p->header[0] |= cf->can_id & CAN_EFF_MASK;
- p->header[1] |= can_fd_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT;
+ p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id);
p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ;
if (can_is_canfd_skb(skb)) {
+ p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ can_fd_len2dlc(cf->len));
p->header[1] |= KVASER_PCIEFD_RPACKET_FDF;
if (cf->flags & CANFD_BRS)
p->header[1] |= KVASER_PCIEFD_RPACKET_BRS;
if (cf->flags & CANFD_ESI)
p->header[1] |= KVASER_PCIEFD_RPACKET_ESI;
+ } else {
+ p->header[1] |=
+ FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode));
}
- p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK;
+ p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq);
packet_size = cf->len;
memcpy(p->data, cf->data, packet_size);
@@ -777,16 +616,15 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
struct kvaser_pciefd_can *can = netdev_priv(netdev);
unsigned long irq_flags;
struct kvaser_pciefd_tx_packet packet;
- int nwords;
+ int nr_words;
u8 count;
if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK;
- nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
+ nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
spin_lock_irqsave(&can->echo_lock, irq_flags);
-
/* Prepare and save echo skb in internal slot */
can_put_echo_skb(skb, netdev, can->echo_idx, 0);
@@ -799,13 +637,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
iowrite32(packet.header[1],
can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
- if (nwords) {
- u32 data_last = ((u32 *)packet.data)[nwords - 1];
+ if (nr_words) {
+ u32 data_last = ((u32 *)packet.data)[nr_words - 1];
/* Write data to fifo, except last word */
iowrite32_rep(can->reg_base +
KVASER_PCIEFD_KCAN_FIFO_REG, packet.data,
- nwords - 1);
+ nr_words - 1);
/* Write last word to end of fifo */
__raw_writel(data_last, can->reg_base +
KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
@@ -815,14 +653,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
}
- count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
/* No room for a new message, stop the queue until at least one
* successful transmit
*/
- if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT ||
- can->can.echo_skb[can->echo_idx])
+ if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx])
netif_stop_queue(netdev);
-
spin_unlock_irqrestore(&can->echo_lock, irq_flags);
return NETDEV_TX_OK;
@@ -840,25 +677,20 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
else
bt = &can->can.bittiming;
- btrn = ((bt->phase_seg2 - 1) & 0x1f) <<
- KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT |
- (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) <<
- KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT |
- ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT |
- ((bt->brp - 1) & 0x1fff);
+ btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) |
+ FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1);
spin_lock_irqsave(&can->lock, irq_flags);
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
-
/* Put the circuit in reset mode */
iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM,
can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
/* Can only set bittiming if in reset mode */
ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG,
- test, test & KVASER_PCIEFD_KCAN_MODE_RM,
- 0, 10);
-
+ test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10);
if (ret) {
spin_unlock_irqrestore(&can->lock, irq_flags);
return -EBUSY;
@@ -868,11 +700,10 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG);
else
iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG);
-
/* Restore previous reset mode status */
iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
-
spin_unlock_irqrestore(&can->lock, irq_flags);
+
return 0;
}
@@ -910,6 +741,7 @@ static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev,
bec->rxerr = can->bec.rxerr;
bec->txerr = can->bec.txerr;
+
return 0;
}
@@ -941,7 +773,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
for (i = 0; i < pcie->nr_channels; i++) {
struct net_device *netdev;
struct kvaser_pciefd_can *can;
- u32 status, tx_npackets;
+ u32 status, tx_nr_packets_max;
netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
KVASER_PCIEFD_CAN_TX_MAX_COUNT);
@@ -953,7 +785,6 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE +
i * KVASER_PCIEFD_KCAN_BASE_OFFSET;
-
can->kv_pcie = pcie;
can->cmd_seq = 0;
can->err_rep_cnt = 0;
@@ -962,41 +793,31 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
init_completion(&can->start_comp);
init_completion(&can->flush_comp);
- timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer,
- 0);
+ timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0);
/* Disable Bus load reporting */
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
- tx_npackets = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
- if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) &
- 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) {
- dev_err(&pcie->pci->dev,
- "Max Tx count is smaller than expected\n");
-
- free_candev(netdev);
- return -ENODEV;
- }
+ tx_nr_packets_max =
+ FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
can->can.clock.freq = pcie->freq;
- can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT;
+ can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1);
can->echo_idx = 0;
spin_lock_init(&can->echo_lock);
spin_lock_init(&can->lock);
+
can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
-
can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
- can->can.do_set_data_bittiming =
- kvaser_pciefd_set_data_bittiming;
-
+ can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
can->can.do_set_mode = kvaser_pciefd_set_mode;
can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
-
can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO;
+ CAN_CTRLMODE_FD_NON_ISO |
+ CAN_CTRLMODE_CC_LEN8_DLC;
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
@@ -1011,10 +832,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
netdev->flags |= IFF_ECHO;
-
SET_NETDEV_DEV(netdev, &pcie->pci->dev);
- iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
+ iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
@@ -1073,18 +893,16 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i;
- pcie->dma_data[i] =
- dmam_alloc_coherent(&pcie->pci->dev,
- KVASER_PCIEFD_DMA_SIZE,
- &dma_addr[i],
- GFP_KERNEL);
+ pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev,
+ KVASER_PCIEFD_DMA_SIZE,
+ &dma_addr[i],
+ GFP_KERNEL);
if (!pcie->dma_data[i] || !dma_addr[i]) {
dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n",
KVASER_PCIEFD_DMA_SIZE);
return -ENOMEM;
}
-
kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset);
}
@@ -1092,10 +910,10 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
KVASER_PCIEFD_SRB_CMD_RDB1,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
-
/* Empty Rx FIFO */
- srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
- KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
+ srb_packet_count =
+ FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK,
+ ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG));
while (srb_packet_count) {
/* Drop current packet in FIFO */
ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
@@ -1117,37 +935,21 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
{
- u32 sysid, srb_status, build;
- u8 sysid_nr_chan;
- int ret;
-
- ret = kvaser_pciefd_read_cfg(pcie);
- if (ret)
- return ret;
-
- sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG);
- sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff;
- if (pcie->nr_channels != sysid_nr_chan) {
- dev_err(&pcie->pci->dev,
- "Number of channels does not match: %u vs %u\n",
- pcie->nr_channels,
- sysid_nr_chan);
- return -ENODEV;
- }
+ u32 version, srb_status, build;
- if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS)
- pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS;
+ version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG);
+ pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS,
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version));
build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG);
- dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n",
- (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff,
- sysid & 0xff,
- (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff);
+ dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n",
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version),
+ FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version),
+ FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build));
srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
- dev_err(&pcie->pci->dev,
- "Hardware without DMA is not supported\n");
+ dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n");
return -ENODEV;
}
@@ -1157,10 +959,10 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
pcie->freq_to_ticks_div = pcie->freq / 1000000;
if (pcie->freq_to_ticks_div == 0)
pcie->freq_to_ticks_div = 1;
-
/* Turn off all loopback functionality */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG);
- return ret;
+
+ return 0;
}
static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
@@ -1170,56 +972,48 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
struct sk_buff *skb;
struct canfd_frame *cf;
struct can_priv *priv;
- struct net_device_stats *stats;
- struct skb_shared_hwtstamps *shhwtstamps;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
+ u8 dlc;
if (ch_id >= pcie->nr_channels)
return -EIO;
priv = &pcie->can[ch_id]->can;
- stats = &priv->dev->stats;
+ dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]);
if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) {
skb = alloc_canfd_skb(priv->dev, &cf);
if (!skb) {
- stats->rx_dropped++;
+ priv->dev->stats.rx_dropped++;
return -ENOMEM;
}
+ cf->len = can_fd_dlc2len(dlc);
if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS)
cf->flags |= CANFD_BRS;
-
if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI)
cf->flags |= CANFD_ESI;
} else {
skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf);
if (!skb) {
- stats->rx_dropped++;
+ priv->dev->stats.rx_dropped++;
return -ENOMEM;
}
+ can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode);
}
- cf->can_id = p->header[0] & CAN_EFF_MASK;
+ cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]);
if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE)
cf->can_id |= CAN_EFF_FLAG;
- cf->len = can_fd_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT);
-
if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) {
cf->can_id |= CAN_RTR_FLAG;
} else {
memcpy(cf->data, data, cf->len);
-
- stats->rx_bytes += cf->len;
+ priv->dev->stats.rx_bytes += cf->len;
}
- stats->rx_packets++;
-
- shhwtstamps = skb_hwtstamps(skb);
-
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- pcie->freq_to_ticks_div));
+ priv->dev->stats.rx_packets++;
+ kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
return netif_rx(skb);
}
@@ -1239,7 +1033,6 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
spin_lock_irqsave(&can->lock, irq_flags);
netif_stop_queue(can->can.dev);
spin_unlock_irqrestore(&can->lock, irq_flags);
-
/* Prevent CAN controller from auto recover from bus off */
if (!can->can.restart_ms) {
kvaser_pciefd_start_controller_flush(can);
@@ -1257,7 +1050,7 @@ static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF ||
p->header[0] & KVASER_PCIEFD_SPACK_IRM)
*new_state = CAN_STATE_BUS_OFF;
- else if (bec->txerr >= 255 || bec->rxerr >= 255)
+ else if (bec->txerr >= 255 || bec->rxerr >= 255)
*new_state = CAN_STATE_BUS_OFF;
else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR)
*new_state = CAN_STATE_ERROR_PASSIVE;
@@ -1282,23 +1075,16 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
struct net_device *ndev = can->can.dev;
struct sk_buff *skb;
struct can_frame *cf = NULL;
- struct skb_shared_hwtstamps *shhwtstamps;
- struct net_device_stats *stats = &ndev->stats;
old_state = can->can.state;
- bec.txerr = p->header[0] & 0xff;
- bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
-
- kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
- &rx_state);
+ bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
+ bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
+ kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
skb = alloc_can_err_skb(ndev, &cf);
-
if (new_state != old_state) {
- kvaser_pciefd_change_state(can, cf, new_state, tx_state,
- rx_state);
-
+ kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
if (old_state == CAN_STATE_BUS_OFF &&
new_state == CAN_STATE_ERROR_ACTIVE &&
can->can.restart_ms) {
@@ -1311,28 +1097,25 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
can->err_rep_cnt++;
can->can.can_stats.bus_error++;
if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
- stats->tx_errors++;
+ ndev->stats.tx_errors++;
else
- stats->rx_errors++;
+ ndev->stats.rx_errors++;
can->bec.txerr = bec.txerr;
can->bec.rxerr = bec.rxerr;
if (!skb) {
- stats->rx_dropped++;
+ ndev->stats.rx_dropped++;
return -ENOMEM;
}
- shhwtstamps = skb_hwtstamps(skb);
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- can->kv_pcie->freq_to_ticks_div));
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
-
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
netif_rx(skb);
+
return 0;
}
@@ -1340,19 +1123,19 @@ static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_rx_packet *p)
{
struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
can = pcie->can[ch_id];
-
kvaser_pciefd_rx_error_frame(can, p);
if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP)
/* Do not report more errors, until bec_poll_timer expires */
kvaser_pciefd_disable_err_gen(can);
/* Start polling the error counters */
mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
+
return 0;
}
@@ -1364,29 +1147,22 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
old_state = can->can.state;
- bec.txerr = p->header[0] & 0xff;
- bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
-
- kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
- &rx_state);
+ bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
+ bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
+ kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
if (new_state != old_state) {
struct net_device *ndev = can->can.dev;
struct sk_buff *skb;
struct can_frame *cf;
- struct skb_shared_hwtstamps *shhwtstamps;
skb = alloc_can_err_skb(ndev, &cf);
if (!skb) {
- struct net_device_stats *stats = &ndev->stats;
-
- stats->rx_dropped++;
+ ndev->stats.rx_dropped++;
return -ENOMEM;
}
- kvaser_pciefd_change_state(can, cf, new_state, tx_state,
- rx_state);
-
+ kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
if (old_state == CAN_STATE_BUS_OFF &&
new_state == CAN_STATE_ERROR_ACTIVE &&
can->can.restart_ms) {
@@ -1394,10 +1170,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
cf->can_id |= CAN_ERR_RESTARTED;
}
- shhwtstamps = skb_hwtstamps(skb);
- shhwtstamps->hwtstamp =
- ns_to_ktime(div_u64(p->timestamp * 1000,
- can->kv_pcie->freq_to_ticks_div));
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
@@ -1419,7 +1192,7 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_can *can;
u8 cmdseq;
u32 status;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1427,43 +1200,40 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
can = pcie->can[ch_id];
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
- cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff;
+ cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status);
/* Reset done, start abort and flush */
if (p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
p->header[1] & KVASER_PCIEFD_SPACK_AUTO &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
- u32 cmd;
-
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
- cmd = KVASER_PCIEFD_KCAN_CMD_AT;
- cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
- iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
+ kvaser_pciefd_abort_flush_reset(can);
} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
/* Reset detected, send end of flush if no packet are in FIFO */
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
+ u8 count;
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
if (!count)
- iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
+ iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK,
+ KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH),
can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
} else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) &&
- cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) {
+ cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) {
/* Response to status request received */
kvaser_pciefd_handle_status_resp(can, p);
if (can->can.state != CAN_STATE_BUS_OFF &&
can->can.state != CAN_STATE_ERROR_ACTIVE) {
- mod_timer(&can->bec_poll_timer,
- KVASER_PCIEFD_BEC_POLL_FREQ);
+ mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
}
} else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
- !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) {
+ !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) {
/* Reset to bus on detected */
if (!completion_done(&can->start_comp))
complete(&can->start_comp);
@@ -1472,50 +1242,14 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
return 0;
}
-static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie,
- struct kvaser_pciefd_rx_packet *p)
-{
- struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
-
- if (ch_id >= pcie->nr_channels)
- return -EIO;
-
- can = pcie->can[ch_id];
-
- /* If this is the last flushed packet, send end of flush */
- if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
-
- if (count == 0)
- iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
- can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
- } else {
- int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
- int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
- struct net_device_stats *stats = &can->can.dev->stats;
-
- stats->tx_bytes += dlc;
- stats->tx_packets++;
-
- if (netif_queue_stopped(can->can.dev))
- netif_wake_queue(can->can.dev);
- }
-
- return 0;
-}
-
static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
struct kvaser_pciefd_rx_packet *p)
{
struct sk_buff *skb;
- struct net_device_stats *stats = &can->can.dev->stats;
struct can_frame *cf;
skb = alloc_can_err_skb(can->can.dev, &cf);
-
- stats->tx_errors++;
+ can->can.dev->stats.tx_errors++;
if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) {
if (skb)
cf->can_id |= CAN_ERR_LOSTARB;
@@ -1526,9 +1260,10 @@ static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
if (skb) {
cf->can_id |= CAN_ERR_BUSERROR;
+ kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
netif_rx(skb);
} else {
- stats->rx_dropped++;
+ can->can.dev->stats.rx_dropped++;
netdev_warn(can->can.dev, "No memory left for err_skb\n");
}
}
@@ -1538,7 +1273,7 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
{
struct kvaser_pciefd_can *can;
bool one_shot_fail = false;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1556,20 +1291,24 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
netdev_dbg(can->can.dev, "Packet was flushed\n");
} else {
- int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
- int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
- u8 count = ioread32(can->reg_base +
- KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
+ int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]);
+ int len;
+ u8 count;
+ struct sk_buff *skb;
- if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT &&
- netif_queue_stopped(can->can.dev))
+ skb = can->can.echo_skb[echo_idx];
+ if (skb)
+ kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
+ len = can_get_echo_skb(can->can.dev, echo_idx, NULL);
+ count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
+ ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
+
+ if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev))
netif_wake_queue(can->can.dev);
if (!one_shot_fail) {
- struct net_device_stats *stats = &can->can.dev->stats;
-
- stats->tx_bytes += dlc;
- stats->tx_packets++;
+ can->can.dev->stats.tx_bytes += len;
+ can->can.dev->stats.tx_packets++;
}
}
@@ -1580,7 +1319,7 @@ static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie,
struct kvaser_pciefd_rx_packet *p)
{
struct kvaser_pciefd_can *can;
- u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
+ u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
if (ch_id >= pcie->nr_channels)
return -EIO;
@@ -1619,15 +1358,15 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
pos += 2;
p->timestamp = le64_to_cpu(timestamp);
- type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf;
+ type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]);
switch (type) {
case KVASER_PCIEFD_PACK_TYPE_DATA:
ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
u8 data_len;
- data_len = can_fd_dlc2len(p->header[1] >>
- KVASER_PCIEFD_RPACKET_DLC_SHIFT);
+ data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ p->header[1]));
pos += DIV_ROUND_UP(data_len, 4);
}
break;
@@ -1644,16 +1383,13 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
ret = kvaser_pciefd_handle_error_packet(pcie, p);
break;
- case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
- ret = kvaser_pciefd_handle_eack_packet(pcie, p);
- break;
-
case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK:
ret = kvaser_pciefd_handle_eflush_packet(pcie, p);
break;
case KVASER_PCIEFD_PACK_TYPE_ACK_DATA:
case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD:
+ case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
case KVASER_PCIEFD_PACK_TYPE_TXRQ:
dev_info(&pcie->pci->dev,
"Received unexpected packet type 0x%08X\n", type);
@@ -1692,7 +1428,7 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
return res;
}
-static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
+static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
{
u32 irq;
@@ -1718,10 +1454,9 @@ static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
- return 0;
}
-static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
+static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
{
u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
@@ -1739,7 +1474,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
netdev_err(can->can.dev, "Rx FIFO overflow\n");
iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
- return 0;
}
static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
@@ -1750,7 +1484,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
- if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK))
+ if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK))
return IRQ_NONE;
if (board_irq & KVASER_PCIEFD_IRQ_SRB)
@@ -1768,20 +1502,18 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
kvaser_pciefd_transmit_irq(pcie->can[i]);
}
- iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
return IRQ_HANDLED;
}
static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
{
int i;
- struct kvaser_pciefd_can *can;
for (i = 0; i < pcie->nr_channels; i++) {
- can = pcie->can[i];
+ struct kvaser_pciefd_can *can = pcie->can[i];
+
if (can) {
- iowrite32(0,
- can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
kvaser_pciefd_pwm_stop(can);
free_candev(can->can.dev);
}
@@ -1842,10 +1574,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG);
- /* Reset IRQ handling, expected to be off before */
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
- pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
+ /* Enable PCI interrupts */
+ iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK,
pcie->reg_base + KVASER_PCIEFD_IEN_REG);
/* Ready the DMA buffers */
@@ -1884,14 +1614,13 @@ err_disable_pci:
static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
{
- struct kvaser_pciefd_can *can;
int i;
for (i = 0; i < pcie->nr_channels; i++) {
- can = pcie->can[i];
+ struct kvaser_pciefd_can *can = pcie->can[i];
+
if (can) {
- iowrite32(0,
- can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
+ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
unregister_candev(can->can.dev);
del_timer(&can->bec_poll_timer);
kvaser_pciefd_pwm_stop(can);
@@ -1906,10 +1635,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
kvaser_pciefd_remove_all_ctrls(pcie);
- /* Turn off IRQ generation */
+ /* Disable interrupts */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
- iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
- pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
free_irq(pcie->pci->irq, pcie);
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index a5003435802b..c5af92bcc9c9 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -469,7 +469,7 @@ static void m_can_receive_skb(struct m_can_classdev *cdev,
int err;
err = can_rx_offload_queue_timestamp(&cdev->offload, skb,
- timestamp);
+ timestamp);
if (err)
stats->rx_fifo_errors++;
} else {
@@ -895,7 +895,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus,
netdev_dbg(dev, "Arbitration phase error detected\n");
work_done += m_can_handle_lec_err(dev, lec);
}
-
+
if (is_lec_err(dlec)) {
netdev_dbg(dev, "Data phase error detected\n");
work_done += m_can_handle_lec_err(dev, dlec);
diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
index 9c1dcf838006..94dc82644113 100644
--- a/drivers/net/can/m_can/m_can_platform.c
+++ b/drivers/net/can/m_can/m_can_platform.c
@@ -164,7 +164,7 @@ static __maybe_unused int m_can_resume(struct device *dev)
return m_can_class_resume(dev);
}
-static int m_can_plat_remove(struct platform_device *pdev)
+static void m_can_plat_remove(struct platform_device *pdev)
{
struct m_can_plat_priv *priv = platform_get_drvdata(pdev);
struct m_can_classdev *mcan_class = &priv->cdev;
@@ -172,8 +172,6 @@ static int m_can_plat_remove(struct platform_device *pdev)
m_can_class_unregister(mcan_class);
m_can_class_free_dev(mcan_class->net);
-
- return 0;
}
static int __maybe_unused m_can_runtime_suspend(struct device *dev)
@@ -223,7 +221,7 @@ static struct platform_driver m_can_plat_driver = {
.pm = &m_can_pmops,
},
.probe = m_can_plat_probe,
- .remove = m_can_plat_remove,
+ .remove_new = m_can_plat_remove,
};
module_platform_driver(m_can_plat_driver);
diff --git a/drivers/net/can/m_can/tcan4x5x-regmap.c b/drivers/net/can/m_can/tcan4x5x-regmap.c
index 2b218ce04e9f..fafa6daa67e6 100644
--- a/drivers/net/can/m_can/tcan4x5x-regmap.c
+++ b/drivers/net/can/m_can/tcan4x5x-regmap.c
@@ -95,7 +95,6 @@ static const struct regmap_range tcan4x5x_reg_table_wr_range[] = {
regmap_reg_range(0x000c, 0x0010),
/* Device configuration registers and Interrupt Flags*/
regmap_reg_range(0x0800, 0x080c),
- regmap_reg_range(0x0814, 0x0814),
regmap_reg_range(0x0820, 0x0820),
regmap_reg_range(0x0830, 0x0830),
/* M_CAN */
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index b0ed798ae70f..4837df6efa92 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -349,7 +349,7 @@ exit_unmap_mem:
return err;
}
-static int mpc5xxx_can_remove(struct platform_device *ofdev)
+static void mpc5xxx_can_remove(struct platform_device *ofdev)
{
const struct of_device_id *match;
const struct mpc5xxx_can_data *data;
@@ -365,8 +365,6 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev)
iounmap(priv->reg_base);
irq_dispose_mapping(dev->irq);
free_candev(dev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -437,7 +435,7 @@ static struct platform_driver mpc5xxx_can_driver = {
.of_match_table = mpc5xxx_can_table,
},
.probe = mpc5xxx_can_probe,
- .remove = mpc5xxx_can_remove,
+ .remove_new = mpc5xxx_can_remove,
#ifdef CONFIG_PM
.suspend = mpc5xxx_can_suspend,
.resume = mpc5xxx_can_resume,
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index cc43c9c5e38c..f5aa5dbacaf2 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -824,7 +824,7 @@ fail:
return err;
}
-static int rcar_can_remove(struct platform_device *pdev)
+static void rcar_can_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct rcar_can_priv *priv = netdev_priv(ndev);
@@ -832,7 +832,6 @@ static int rcar_can_remove(struct platform_device *pdev)
unregister_candev(ndev);
netif_napi_del(&priv->napi);
free_candev(ndev);
- return 0;
}
static int __maybe_unused rcar_can_suspend(struct device *dev)
@@ -908,7 +907,7 @@ static struct platform_driver rcar_can_driver = {
.pm = &rcar_can_pm_ops,
},
.probe = rcar_can_probe,
- .remove = rcar_can_remove,
+ .remove_new = rcar_can_remove,
};
module_platform_driver(rcar_can_driver);
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 963c42f43755..e4d748913439 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2078,7 +2078,7 @@ fail_dev:
return err;
}
-static int rcar_canfd_remove(struct platform_device *pdev)
+static void rcar_canfd_remove(struct platform_device *pdev)
{
struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);
u32 ch;
@@ -2096,8 +2096,6 @@ static int rcar_canfd_remove(struct platform_device *pdev)
clk_disable_unprepare(gpriv->clkp);
reset_control_assert(gpriv->rstc1);
reset_control_assert(gpriv->rstc2);
-
- return 0;
}
static int __maybe_unused rcar_canfd_suspend(struct device *dev)
@@ -2130,7 +2128,7 @@ static struct platform_driver rcar_canfd_driver = {
.pm = &rcar_canfd_pm_ops,
},
.probe = rcar_canfd_probe,
- .remove = rcar_canfd_remove,
+ .remove_new = rcar_canfd_remove,
};
module_platform_driver(rcar_canfd_driver);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index aac5956e4a53..0ada0e160e93 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -387,6 +387,16 @@ static void sja1000_rx(struct net_device *dev)
netif_rx(skb);
}
+static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+
+ netdev_dbg(dev, "performing a soft reset upon overrun\n");
+ sja1000_start(dev);
+
+ return IRQ_HANDLED;
+}
+
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
{
struct sja1000_priv *priv = netdev_priv(dev);
@@ -397,6 +407,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
enum can_state rx_state, tx_state;
unsigned int rxerr, txerr;
uint8_t ecc, alc;
+ int ret = 0;
skb = alloc_can_err_skb(dev, &cf);
if (skb == NULL)
@@ -413,6 +424,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
stats->rx_over_errors++;
stats->rx_errors++;
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
+
+ /* Some controllers needs additional handling upon overrun
+ * condition: the controller may sometimes be totally confused
+ * and refuse any new frame while its buffer is empty. The only
+ * way to re-sync the read vs. write buffer offsets is to
+ * stop any current handling and perform a reset.
+ */
+ if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
+ ret = IRQ_WAKE_THREAD;
}
if (isrc & IRQ_EI) {
@@ -492,7 +512,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
netif_rx(skb);
- return 0;
+ return ret;
}
irqreturn_t sja1000_interrupt(int irq, void *dev_id)
@@ -501,7 +521,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
struct sja1000_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
uint8_t isrc, status;
- int n = 0;
+ irqreturn_t ret = 0;
+ int n = 0, err;
if (priv->pre_irq)
priv->pre_irq(priv);
@@ -546,19 +567,25 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
}
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
/* error interrupt */
- if (sja1000_err(dev, isrc, status))
+ err = sja1000_err(dev, isrc, status);
+ if (err == IRQ_WAKE_THREAD)
+ ret = err;
+ if (err)
break;
}
n++;
}
out:
+ if (!ret)
+ ret = (n) ? IRQ_HANDLED : IRQ_NONE;
+
if (priv->post_irq)
priv->post_irq(priv);
if (n >= SJA1000_MAX_IRQ)
netdev_dbg(dev, "%d messages handled in ISR", n);
- return (n) ? IRQ_HANDLED : IRQ_NONE;
+ return ret;
}
EXPORT_SYMBOL_GPL(sja1000_interrupt);
@@ -577,8 +604,9 @@ static int sja1000_open(struct net_device *dev)
/* register interrupt handler, if not done by the device driver */
if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
- err = request_irq(dev->irq, sja1000_interrupt, priv->irq_flags,
- dev->name, (void *)dev);
+ err = request_threaded_irq(dev->irq, sja1000_interrupt,
+ sja1000_reset_interrupt,
+ priv->irq_flags, dev->name, (void *)dev);
if (err) {
close_candev(dev);
return -EAGAIN;
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 7f736f1df547..f015e39e2224 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -147,6 +147,7 @@
*/
#define SJA1000_CUSTOM_IRQ_HANDLER BIT(0)
#define SJA1000_QUIRK_NO_CDR_REG BIT(1)
+#define SJA1000_QUIRK_RESET_ON_OVERRUN BIT(2)
/*
* SJA1000 private data structure
diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c
index db3e767d5320..fca5a9a1d857 100644
--- a/drivers/net/can/sja1000/sja1000_isa.c
+++ b/drivers/net/can/sja1000/sja1000_isa.c
@@ -223,7 +223,7 @@ exit:
return err;
}
-static int sja1000_isa_remove(struct platform_device *pdev)
+static void sja1000_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct sja1000_priv *priv = netdev_priv(dev);
@@ -241,13 +241,11 @@ static int sja1000_isa_remove(struct platform_device *pdev)
release_region(port[idx], SJA1000_IOSIZE);
}
free_sja1000dev(dev);
-
- return 0;
}
static struct platform_driver sja1000_isa_driver = {
.probe = sja1000_isa_probe,
- .remove = sja1000_isa_remove,
+ .remove_new = sja1000_isa_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 6779d5357069..4e59952c66d4 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -106,7 +106,7 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o
static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of)
{
- priv->flags = SJA1000_QUIRK_NO_CDR_REG;
+ priv->flags = SJA1000_QUIRK_NO_CDR_REG | SJA1000_QUIRK_RESET_ON_OVERRUN;
}
static void sp_populate(struct sja1000_priv *priv,
@@ -277,6 +277,9 @@ static int sp_probe(struct platform_device *pdev)
priv->irq_flags = IRQF_SHARED;
}
+ if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
+ priv->irq_flags |= IRQF_ONESHOT;
+
dev->irq = irq;
priv->reg_base = addr;
@@ -317,19 +320,17 @@ static int sp_probe(struct platform_device *pdev)
return err;
}
-static int sp_remove(struct platform_device *pdev)
+static void sp_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_sja1000dev(dev);
free_sja1000dev(dev);
-
- return 0;
}
static struct platform_driver sp_driver = {
.probe = sp_probe,
- .remove = sp_remove,
+ .remove_new = sp_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sp_of_table,
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index c72f505d29fe..bd25137062c5 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -729,7 +729,7 @@ static const struct attribute_group softing_pdev_group = {
/*
* platform driver
*/
-static int softing_pdev_remove(struct platform_device *pdev)
+static void softing_pdev_remove(struct platform_device *pdev)
{
struct softing *card = platform_get_drvdata(pdev);
int j;
@@ -747,7 +747,6 @@ static int softing_pdev_remove(struct platform_device *pdev)
iounmap(card->dpram);
kfree(card);
- return 0;
}
static int softing_pdev_probe(struct platform_device *pdev)
@@ -855,7 +854,7 @@ static struct platform_driver softing_driver = {
.name = KBUILD_MODNAME,
},
.probe = softing_pdev_probe,
- .remove = softing_pdev_remove,
+ .remove_new = softing_pdev_remove,
};
module_platform_driver(softing_driver);
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 68df6d4641b5..eebf967f4711 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -227,6 +227,8 @@ static int
__mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
const u8 mode_req, bool nowait)
{
+ const struct can_bittiming *bt = &priv->can.bittiming;
+ unsigned long timeout_us = MCP251XFD_POLL_TIMEOUT_US;
u32 con = 0, con_reqop, osc = 0;
u8 mode;
int err;
@@ -246,12 +248,16 @@ __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
return 0;
+ if (bt->bitrate)
+ timeout_us = max_t(unsigned long, timeout_us,
+ MCP251XFD_FRAME_LEN_MAX_BITS * USEC_PER_SEC /
+ bt->bitrate);
+
err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
!mcp251xfd_reg_invalid(con) &&
FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
con) == mode_req,
- MCP251XFD_POLL_SLEEP_US,
- MCP251XFD_POLL_TIMEOUT_US);
+ MCP251XFD_POLL_SLEEP_US, timeout_us);
if (err != -ETIMEDOUT && err != -EBADMSG)
return err;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 7024ff0cc2c0..24510b3b8020 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -387,6 +387,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
#define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
#define MCP251XFD_POLL_SLEEP_US (10)
#define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
+#define MCP251XFD_FRAME_LEN_MAX_BITS (736)
/* Misc */
#define MCP251XFD_NAPI_WEIGHT 32
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index 2b78f9197681..c508a328e38d 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -91,6 +91,8 @@
#define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */
#define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */
#define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */
+#define SUN4I_REG_ACPC_ADDR_D1 0x0028 /* CAN Acceptance Code 0 on the D1 */
+#define SUN4I_REG_ACPM_ADDR_D1 0x002C /* CAN Acceptance Mask 0 on the D1 */
#define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */
#define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */
@@ -205,9 +207,11 @@
* struct sun4ican_quirks - Differences between SoC variants.
*
* @has_reset: SoC needs reset deasserted.
+ * @acp_offset: Offset of ACPC and ACPM registers
*/
struct sun4ican_quirks {
bool has_reset;
+ int acp_offset;
};
struct sun4ican_priv {
@@ -216,6 +220,7 @@ struct sun4ican_priv {
struct clk *clk;
struct reset_control *reset;
spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
+ int acp_offset;
};
static const struct can_bittiming_const sun4ican_bittiming_const = {
@@ -338,8 +343,8 @@ static int sun4i_can_start(struct net_device *dev)
}
/* set filters - we accept all */
- writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR);
- writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR);
+ writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR + priv->acp_offset);
+ writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR + priv->acp_offset);
/* clear error counters and error code capture */
writel(0, priv->base + SUN4I_REG_ERRC_ADDR);
@@ -768,10 +773,17 @@ static const struct ethtool_ops sun4ican_ethtool_ops = {
static const struct sun4ican_quirks sun4ican_quirks_a10 = {
.has_reset = false,
+ .acp_offset = 0,
};
static const struct sun4ican_quirks sun4ican_quirks_r40 = {
.has_reset = true,
+ .acp_offset = 0,
+};
+
+static const struct sun4ican_quirks sun4ican_quirks_d1 = {
+ .has_reset = true,
+ .acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR),
};
static const struct of_device_id sun4ican_of_match[] = {
@@ -785,20 +797,21 @@ static const struct of_device_id sun4ican_of_match[] = {
.compatible = "allwinner,sun8i-r40-can",
.data = &sun4ican_quirks_r40
}, {
+ .compatible = "allwinner,sun20i-d1-can",
+ .data = &sun4ican_quirks_d1
+ }, {
/* sentinel */
},
};
MODULE_DEVICE_TABLE(of, sun4ican_of_match);
-static int sun4ican_remove(struct platform_device *pdev)
+static void sun4ican_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_netdev(dev);
free_candev(dev);
-
- return 0;
}
static int sun4ican_probe(struct platform_device *pdev)
@@ -872,6 +885,7 @@ static int sun4ican_probe(struct platform_device *pdev)
priv->base = addr;
priv->clk = clk;
priv->reset = reset;
+ priv->acp_offset = quirks->acp_offset;
spin_lock_init(&priv->cmdreg_lock);
platform_set_drvdata(pdev, dev);
@@ -901,7 +915,7 @@ static struct platform_driver sun4i_can_driver = {
.of_match_table = sun4ican_of_match,
},
.probe = sun4ican_probe,
- .remove = sun4ican_remove,
+ .remove_new = sun4ican_remove,
};
module_platform_driver(sun4i_can_driver);
@@ -909,4 +923,4 @@ module_platform_driver(sun4i_can_driver);
MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)");
+MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20/D1)");
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 27700f72eac2..54284661992e 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -625,7 +625,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
timestamp = hecc_read(priv, HECC_CANLNT);
err = can_rx_offload_queue_timestamp(&priv->offload, skb,
- timestamp);
+ timestamp);
if (err)
ndev->stats.rx_fifo_errors++;
}
@@ -963,7 +963,7 @@ probe_exit_candev:
return err;
}
-static int ti_hecc_remove(struct platform_device *pdev)
+static void ti_hecc_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct ti_hecc_priv *priv = netdev_priv(ndev);
@@ -973,8 +973,6 @@ static int ti_hecc_remove(struct platform_device *pdev)
clk_put(priv->clk);
can_rx_offload_del(&priv->offload);
free_candev(ndev);
-
- return 0;
}
#ifdef CONFIG_PM
@@ -1028,7 +1026,7 @@ static struct platform_driver ti_hecc_driver = {
.of_match_table = ti_hecc_dt_ids,
},
.probe = ti_hecc_probe,
- .remove = ti_hecc_remove,
+ .remove_new = ti_hecc_remove,
.suspend = ti_hecc_suspend,
.resume = ti_hecc_resume,
};
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 445504ababce..58fcd2b34820 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -38,6 +38,18 @@ config CAN_ETAS_ES58X
To compile this driver as a module, choose M here: the module
will be called etas_es58x.
+config CAN_F81604
+ tristate "Fintek F81604 USB to 2CAN interface"
+ help
+ This driver supports the Fintek F81604 USB to 2CAN interface.
+ The device can support CAN2.0A/B protocol and also support
+ 2 output pins to control external terminator (optional).
+
+ To compile this driver as a module, choose M here: the module will
+ be called f81604.
+
+ (see also https://www.fintek.com.tw).
+
config CAN_GS_USB
tristate "Geschwister Schneider UG and candleLight compatible interfaces"
help
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index 1ea16be5743b..8b11088e9a59 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o
obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/
+obj-$(CONFIG_CAN_F81604) += f81604.o
obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/
obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o
diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
index d33bac3a6c10..6201637ac0ff 100644
--- a/drivers/net/can/usb/esd_usb.c
+++ b/drivers/net/can/usb/esd_usb.c
@@ -3,18 +3,19 @@
* CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro
*
* Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu>
- * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu>
+ * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu>
*/
-#include <linux/ethtool.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/usb.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/units.h>
+#include <linux/usb.h>
MODULE_AUTHOR("Matthias Fuchs <socketcan@esd.eu>");
MODULE_AUTHOR("Frank Jungclaus <frank.jungclaus@esd.eu>");
@@ -22,95 +23,87 @@ MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Mi
MODULE_LICENSE("GPL v2");
/* USB vendor and product ID */
-#define USB_ESDGMBH_VENDOR_ID 0x0ab4
-#define USB_CANUSB2_PRODUCT_ID 0x0010
-#define USB_CANUSBM_PRODUCT_ID 0x0011
+#define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4
+#define ESD_USB_CANUSB2_PRODUCT_ID 0x0010
+#define ESD_USB_CANUSBM_PRODUCT_ID 0x0011
/* CAN controller clock frequencies */
-#define ESD_USB2_CAN_CLOCK 60000000
-#define ESD_USBM_CAN_CLOCK 36000000
+#define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */
+#define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */
/* Maximum number of CAN nets */
#define ESD_USB_MAX_NETS 2
/* USB commands */
-#define CMD_VERSION 1 /* also used for VERSION_REPLY */
-#define CMD_CAN_RX 2 /* device to host only */
-#define CMD_CAN_TX 3 /* also used for TX_DONE */
-#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */
-#define CMD_TS 5 /* also used for TS_REPLY */
-#define CMD_IDADD 6 /* also used for IDADD_REPLY */
+#define ESD_USB_CMD_VERSION 1 /* also used for VERSION_REPLY */
+#define ESD_USB_CMD_CAN_RX 2 /* device to host only */
+#define ESD_USB_CMD_CAN_TX 3 /* also used for TX_DONE */
+#define ESD_USB_CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */
+#define ESD_USB_CMD_TS 5 /* also used for TS_REPLY */
+#define ESD_USB_CMD_IDADD 6 /* also used for IDADD_REPLY */
/* esd CAN message flags - dlc field */
-#define ESD_RTR 0x10
+#define ESD_USB_RTR BIT(4)
/* esd CAN message flags - id field */
-#define ESD_EXTID 0x20000000
-#define ESD_EVENT 0x40000000
-#define ESD_IDMASK 0x1fffffff
+#define ESD_USB_EXTID BIT(29)
+#define ESD_USB_EVENT BIT(30)
+#define ESD_USB_IDMASK GENMASK(28, 0)
/* esd CAN event ids */
-#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */
+#define ESD_USB_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */
/* baudrate message flags */
-#define ESD_USB_UBR 0x80000000
-#define ESD_USB_LOM 0x40000000
-#define ESD_USB_NO_BAUDRATE 0x7fffffff
-
-/* bit timing CAN-USB/2 */
-#define ESD_USB2_TSEG1_MIN 1
-#define ESD_USB2_TSEG1_MAX 16
-#define ESD_USB2_TSEG1_SHIFT 16
-#define ESD_USB2_TSEG2_MIN 1
-#define ESD_USB2_TSEG2_MAX 8
-#define ESD_USB2_TSEG2_SHIFT 20
-#define ESD_USB2_SJW_MAX 4
-#define ESD_USB2_SJW_SHIFT 14
-#define ESD_USBM_SJW_SHIFT 24
-#define ESD_USB2_BRP_MIN 1
-#define ESD_USB2_BRP_MAX 1024
-#define ESD_USB2_BRP_INC 1
-#define ESD_USB2_3_SAMPLES 0x00800000
+#define ESD_USB_LOM BIT(30) /* Listen Only Mode */
+#define ESD_USB_UBR BIT(31) /* User Bit Rate (controller BTR) in bits 0..27 */
+#define ESD_USB_NO_BAUDRATE GENMASK(30, 0) /* bit rate unconfigured */
+
+/* bit timing esd CAN-USB */
+#define ESD_USB_2_TSEG1_SHIFT 16
+#define ESD_USB_2_TSEG2_SHIFT 20
+#define ESD_USB_2_SJW_SHIFT 14
+#define ESD_USB_M_SJW_SHIFT 24
+#define ESD_USB_TRIPLE_SAMPLES BIT(23)
/* esd IDADD message */
-#define ESD_ID_ENABLE 0x80
-#define ESD_MAX_ID_SEGMENT 64
+#define ESD_USB_ID_ENABLE BIT(7)
+#define ESD_USB_MAX_ID_SEGMENT 64
/* SJA1000 ECC register (emulated by usb firmware) */
-#define SJA1000_ECC_SEG 0x1F
-#define SJA1000_ECC_DIR 0x20
-#define SJA1000_ECC_ERR 0x06
-#define SJA1000_ECC_BIT 0x00
-#define SJA1000_ECC_FORM 0x40
-#define SJA1000_ECC_STUFF 0x80
-#define SJA1000_ECC_MASK 0xc0
+#define ESD_USB_SJA1000_ECC_SEG GENMASK(4, 0)
+#define ESD_USB_SJA1000_ECC_DIR BIT(5)
+#define ESD_USB_SJA1000_ECC_ERR BIT(2, 1)
+#define ESD_USB_SJA1000_ECC_BIT 0x00
+#define ESD_USB_SJA1000_ECC_FORM BIT(6)
+#define ESD_USB_SJA1000_ECC_STUFF BIT(7)
+#define ESD_USB_SJA1000_ECC_MASK GENMASK(7, 6)
/* esd bus state event codes */
-#define ESD_BUSSTATE_MASK 0xc0
-#define ESD_BUSSTATE_WARN 0x40
-#define ESD_BUSSTATE_ERRPASSIVE 0x80
-#define ESD_BUSSTATE_BUSOFF 0xc0
+#define ESD_USB_BUSSTATE_MASK GENMASK(7, 6)
+#define ESD_USB_BUSSTATE_WARN BIT(6)
+#define ESD_USB_BUSSTATE_ERRPASSIVE BIT(7)
+#define ESD_USB_BUSSTATE_BUSOFF GENMASK(7, 6)
-#define RX_BUFFER_SIZE 1024
-#define MAX_RX_URBS 4
-#define MAX_TX_URBS 16 /* must be power of 2 */
+#define ESD_USB_RX_BUFFER_SIZE 1024
+#define ESD_USB_MAX_RX_URBS 4
+#define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */
-struct header_msg {
- u8 len; /* len is always the total message length in 32bit words */
+struct esd_usb_header_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 rsvd[2];
};
-struct version_msg {
- u8 len;
+struct esd_usb_version_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 rsvd;
u8 flags;
__le32 drv_version;
};
-struct version_reply_msg {
- u8 len;
+struct esd_usb_version_reply_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 nets;
u8 features;
@@ -120,15 +113,15 @@ struct version_reply_msg {
__le32 ts;
};
-struct rx_msg {
- u8 len;
+struct esd_usb_rx_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 dlc;
__le32 ts;
__le32 id; /* upper 3 bits contain flags */
union {
- u8 data[8];
+ u8 data[CAN_MAX_DLEN];
struct {
u8 status; /* CAN Controller Status */
u8 ecc; /* Error Capture Register */
@@ -138,18 +131,18 @@ struct rx_msg {
};
};
-struct tx_msg {
- u8 len;
+struct esd_usb_tx_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 dlc;
u32 hnd; /* opaque handle, not used by device */
__le32 id; /* upper 3 bits contain flags */
- u8 data[8];
+ u8 data[CAN_MAX_DLEN];
};
-struct tx_done_msg {
- u8 len;
+struct esd_usb_tx_done_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 status;
@@ -157,16 +150,16 @@ struct tx_done_msg {
__le32 ts;
};
-struct id_filter_msg {
- u8 len;
+struct esd_usb_id_filter_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 option;
- __le32 mask[ESD_MAX_ID_SEGMENT + 1];
+ __le32 mask[ESD_USB_MAX_ID_SEGMENT + 1]; /* +1 for 29bit extended IDs */
};
-struct set_baudrate_msg {
- u8 len;
+struct esd_usb_set_baudrate_msg {
+ u8 len; /* total message length in 32bit words */
u8 cmd;
u8 net;
u8 rsvd;
@@ -175,19 +168,19 @@ struct set_baudrate_msg {
/* Main message type used between library and application */
union __packed esd_usb_msg {
- struct header_msg hdr;
- struct version_msg version;
- struct version_reply_msg version_reply;
- struct rx_msg rx;
- struct tx_msg tx;
- struct tx_done_msg txdone;
- struct set_baudrate_msg setbaud;
- struct id_filter_msg filter;
+ struct esd_usb_header_msg hdr;
+ struct esd_usb_version_msg version;
+ struct esd_usb_version_reply_msg version_reply;
+ struct esd_usb_rx_msg rx;
+ struct esd_usb_tx_msg tx;
+ struct esd_usb_tx_done_msg txdone;
+ struct esd_usb_set_baudrate_msg setbaud;
+ struct esd_usb_id_filter_msg filter;
};
static struct usb_device_id esd_usb_table[] = {
- {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
- {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
+ {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)},
+ {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb, esd_usb_table);
@@ -208,8 +201,8 @@ struct esd_usb {
int net_count;
u32 version;
int rxinitdone;
- void *rxbuf[MAX_RX_URBS];
- dma_addr_t rxbuf_dma[MAX_RX_URBS];
+ void *rxbuf[ESD_USB_MAX_RX_URBS];
+ dma_addr_t rxbuf_dma[ESD_USB_MAX_RX_URBS];
};
struct esd_usb_net_priv {
@@ -217,7 +210,7 @@ struct esd_usb_net_priv {
atomic_t active_tx_jobs;
struct usb_anchor tx_submitted;
- struct esd_tx_urb_context tx_contexts[MAX_TX_URBS];
+ struct esd_tx_urb_context tx_contexts[ESD_USB_MAX_TX_URBS];
struct esd_usb *usb;
struct net_device *netdev;
@@ -232,9 +225,9 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
struct net_device_stats *stats = &priv->netdev->stats;
struct can_frame *cf;
struct sk_buff *skb;
- u32 id = le32_to_cpu(msg->rx.id) & ESD_IDMASK;
+ u32 id = le32_to_cpu(msg->rx.id) & ESD_USB_IDMASK;
- if (id == ESD_EV_CAN_ERROR_EXT) {
+ if (id == ESD_USB_EV_CAN_ERROR_EXT) {
u8 state = msg->rx.ev_can_err_ext.status;
u8 ecc = msg->rx.ev_can_err_ext.ecc;
@@ -261,15 +254,15 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
priv->old_state = state;
- switch (state & ESD_BUSSTATE_MASK) {
- case ESD_BUSSTATE_BUSOFF:
+ switch (state & ESD_USB_BUSSTATE_MASK) {
+ case ESD_USB_BUSSTATE_BUSOFF:
new_state = CAN_STATE_BUS_OFF;
can_bus_off(priv->netdev);
break;
- case ESD_BUSSTATE_WARN:
+ case ESD_USB_BUSSTATE_WARN:
new_state = CAN_STATE_ERROR_WARNING;
break;
- case ESD_BUSSTATE_ERRPASSIVE:
+ case ESD_USB_BUSSTATE_ERRPASSIVE:
new_state = CAN_STATE_ERROR_PASSIVE;
break;
default:
@@ -291,14 +284,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- switch (ecc & SJA1000_ECC_MASK) {
- case SJA1000_ECC_BIT:
+ switch (ecc & ESD_USB_SJA1000_ECC_MASK) {
+ case ESD_USB_SJA1000_ECC_BIT:
cf->data[2] |= CAN_ERR_PROT_BIT;
break;
- case SJA1000_ECC_FORM:
+ case ESD_USB_SJA1000_ECC_FORM:
cf->data[2] |= CAN_ERR_PROT_FORM;
break;
- case SJA1000_ECC_STUFF:
+ case ESD_USB_SJA1000_ECC_STUFF:
cf->data[2] |= CAN_ERR_PROT_STUFF;
break;
default:
@@ -306,11 +299,11 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv,
}
/* Error occurred during transmission? */
- if (!(ecc & SJA1000_ECC_DIR))
+ if (!(ecc & ESD_USB_SJA1000_ECC_DIR))
cf->data[2] |= CAN_ERR_PROT_TX;
/* Bit stream position in CAN frame as the error was detected */
- cf->data[3] = ecc & SJA1000_ECC_SEG;
+ cf->data[3] = ecc & ESD_USB_SJA1000_ECC_SEG;
}
if (skb) {
@@ -337,7 +330,7 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv,
id = le32_to_cpu(msg->rx.id);
- if (id & ESD_EVENT) {
+ if (id & ESD_USB_EVENT) {
esd_usb_rx_event(priv, msg);
} else {
skb = alloc_can_skb(priv->netdev, &cf);
@@ -346,14 +339,14 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv,
return;
}
- cf->can_id = id & ESD_IDMASK;
- can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_RTR,
+ cf->can_id = id & ESD_USB_IDMASK;
+ can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR,
priv->can.ctrlmode);
- if (id & ESD_EXTID)
+ if (id & ESD_USB_EXTID)
cf->can_id |= CAN_EFF_FLAG;
- if (msg->rx.dlc & ESD_RTR) {
+ if (msg->rx.dlc & ESD_USB_RTR) {
cf->can_id |= CAN_RTR_FLAG;
} else {
for (i = 0; i < cf->len; i++)
@@ -377,7 +370,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
if (!netif_device_present(netdev))
return;
- context = &priv->tx_contexts[msg->txdone.hnd & (MAX_TX_URBS - 1)];
+ context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)];
if (!msg->txdone.status) {
stats->tx_packets++;
@@ -389,7 +382,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv,
}
/* Release context */
- context->echo_index = MAX_TX_URBS;
+ context->echo_index = ESD_USB_MAX_TX_URBS;
atomic_dec(&priv->active_tx_jobs);
netif_wake_queue(netdev);
@@ -424,7 +417,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
msg = (union esd_usb_msg *)(urb->transfer_buffer + pos);
switch (msg->hdr.cmd) {
- case CMD_CAN_RX:
+ case ESD_USB_CMD_CAN_RX:
if (msg->rx.net >= dev->net_count) {
dev_err(dev->udev->dev.parent, "format error\n");
break;
@@ -433,7 +426,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg);
break;
- case CMD_CAN_TX:
+ case ESD_USB_CMD_CAN_TX:
if (msg->txdone.net >= dev->net_count) {
dev_err(dev->udev->dev.parent, "format error\n");
break;
@@ -444,7 +437,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
break;
}
- pos += msg->hdr.len << 2;
+ pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */
if (pos > urb->actual_length) {
dev_err(dev->udev->dev.parent, "format error\n");
@@ -454,7 +447,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb)
resubmit_urb:
usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
- urb->transfer_buffer, RX_BUFFER_SIZE,
+ urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -538,7 +531,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg)
return usb_bulk_msg(dev->udev,
usb_sndbulkpipe(dev->udev, 2),
msg,
- msg->hdr.len << 2,
+ msg->hdr.len * sizeof(u32), /* convert to # of bytes */
&actual_length,
1000);
}
@@ -563,7 +556,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
if (dev->rxinitdone)
return 0;
- for (i = 0; i < MAX_RX_URBS; i++) {
+ for (i = 0; i < ESD_USB_MAX_RX_URBS; i++) {
struct urb *urb = NULL;
u8 *buf = NULL;
dma_addr_t buf_dma;
@@ -575,7 +568,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
break;
}
- buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+ buf = usb_alloc_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL,
&buf_dma);
if (!buf) {
dev_warn(dev->udev->dev.parent,
@@ -588,7 +581,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
usb_fill_bulk_urb(urb, dev->udev,
usb_rcvbulkpipe(dev->udev, 1),
- buf, RX_BUFFER_SIZE,
+ buf, ESD_USB_RX_BUFFER_SIZE,
esd_usb_read_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &dev->rx_submitted);
@@ -596,7 +589,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev)
err = usb_submit_urb(urb, GFP_KERNEL);
if (err) {
usb_unanchor_urb(urb);
- usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+ usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, buf,
urb->transfer_dma);
goto freeurb;
}
@@ -618,7 +611,7 @@ freeurb:
}
/* Warn if we've couldn't transmit all the URBs */
- if (i < MAX_RX_URBS) {
+ if (i < ESD_USB_MAX_RX_URBS) {
dev_warn(dev->udev->dev.parent,
"rx performance may be slow\n");
}
@@ -653,14 +646,14 @@ static int esd_usb_start(struct esd_usb_net_priv *priv)
* the number of the starting bitmask (0..64) to the filter.option
* field followed by only some bitmasks.
*/
- msg->hdr.cmd = CMD_IDADD;
- msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+ msg->hdr.cmd = ESD_USB_CMD_IDADD;
+ msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32); /* # of 32bit words */
msg->filter.net = priv->index;
- msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */
- for (i = 0; i < ESD_MAX_ID_SEGMENT; i++)
- msg->filter.mask[i] = cpu_to_le32(0xffffffff);
+ msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */
+ for (i = 0; i < ESD_USB_MAX_ID_SEGMENT; i++)
+ msg->filter.mask[i] = cpu_to_le32(GENMASK(31, 0));
/* enable 29bit extended IDs */
- msg->filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
+ msg->filter.mask[ESD_USB_MAX_ID_SEGMENT] = cpu_to_le32(BIT(0));
err = esd_usb_send_msg(dev, msg);
if (err)
@@ -689,8 +682,8 @@ static void unlink_all_urbs(struct esd_usb *dev)
usb_kill_anchored_urbs(&dev->rx_submitted);
- for (i = 0; i < MAX_RX_URBS; ++i)
- usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+ for (i = 0; i < ESD_USB_MAX_RX_URBS; ++i)
+ usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE,
dev->rxbuf[i], dev->rxbuf_dma[i]);
for (i = 0; i < dev->net_count; i++) {
@@ -699,8 +692,8 @@ static void unlink_all_urbs(struct esd_usb *dev)
usb_kill_anchored_urbs(&priv->tx_submitted);
atomic_set(&priv->active_tx_jobs, 0);
- for (j = 0; j < MAX_TX_URBS; j++)
- priv->tx_contexts[j].echo_index = MAX_TX_URBS;
+ for (j = 0; j < ESD_USB_MAX_TX_URBS; j++)
+ priv->tx_contexts[j].echo_index = ESD_USB_MAX_TX_URBS;
}
}
}
@@ -765,25 +758,27 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
msg = (union esd_usb_msg *)buf;
- msg->hdr.len = 3; /* minimal length */
- msg->hdr.cmd = CMD_CAN_TX;
+ /* minimal length as # of 32bit words */
+ msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32);
+ msg->hdr.cmd = ESD_USB_CMD_CAN_TX;
msg->tx.net = priv->index;
msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK);
if (cf->can_id & CAN_RTR_FLAG)
- msg->tx.dlc |= ESD_RTR;
+ msg->tx.dlc |= ESD_USB_RTR;
if (cf->can_id & CAN_EFF_FLAG)
- msg->tx.id |= cpu_to_le32(ESD_EXTID);
+ msg->tx.id |= cpu_to_le32(ESD_USB_EXTID);
for (i = 0; i < cf->len; i++)
msg->tx.data[i] = cf->data[i];
- msg->hdr.len += (cf->len + 3) >> 2;
+ /* round up, then divide by 4 to add the payload length as # of 32bit words */
+ msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32));
- for (i = 0; i < MAX_TX_URBS; i++) {
- if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+ for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) {
+ if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) {
context = &priv->tx_contexts[i];
break;
}
@@ -800,10 +795,10 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
context->echo_index = i;
/* hnd must not be 0 - MSB is stripped in txdone handling */
- msg->tx.hnd = 0x80000000 | i; /* returned in TX done message */
+ msg->tx.hnd = BIT(31) | i; /* returned in TX done message */
usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
- msg->hdr.len << 2,
+ msg->hdr.len * sizeof(u32), /* convert to # of bytes */
esd_usb_write_bulk_callback, context);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -815,7 +810,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
atomic_inc(&priv->active_tx_jobs);
/* Slow down tx path */
- if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS)
+ if (atomic_read(&priv->active_tx_jobs) >= ESD_USB_MAX_TX_URBS)
netif_stop_queue(netdev);
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -865,18 +860,18 @@ static int esd_usb_close(struct net_device *netdev)
return -ENOMEM;
/* Disable all IDs (see esd_usb_start()) */
- msg->hdr.cmd = CMD_IDADD;
- msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT;
+ msg->hdr.cmd = ESD_USB_CMD_IDADD;
+ msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32);/* # of 32bit words */
msg->filter.net = priv->index;
- msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */
- for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++)
+ msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */
+ for (i = 0; i <= ESD_USB_MAX_ID_SEGMENT; i++)
msg->filter.mask[i] = 0;
if (esd_usb_send_msg(priv->usb, msg) < 0)
netdev_err(netdev, "sending idadd message failed\n");
/* set CAN controller to reset mode */
- msg->hdr.len = 2;
- msg->hdr.cmd = CMD_SETBAUD;
+ msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */
+ msg->hdr.cmd = ESD_USB_CMD_SETBAUD;
msg->setbaud.net = priv->index;
msg->setbaud.rsvd = 0;
msg->setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE);
@@ -905,20 +900,21 @@ static const struct ethtool_ops esd_usb_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
-static const struct can_bittiming_const esd_usb2_bittiming_const = {
- .name = "esd_usb2",
- .tseg1_min = ESD_USB2_TSEG1_MIN,
- .tseg1_max = ESD_USB2_TSEG1_MAX,
- .tseg2_min = ESD_USB2_TSEG2_MIN,
- .tseg2_max = ESD_USB2_TSEG2_MAX,
- .sjw_max = ESD_USB2_SJW_MAX,
- .brp_min = ESD_USB2_BRP_MIN,
- .brp_max = ESD_USB2_BRP_MAX,
- .brp_inc = ESD_USB2_BRP_INC,
+static const struct can_bittiming_const esd_usb_2_bittiming_const = {
+ .name = "esd_usb_2",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
};
-static int esd_usb2_set_bittiming(struct net_device *netdev)
+static int esd_usb_2_set_bittiming(struct net_device *netdev)
{
+ const struct can_bittiming_const *btc = &esd_usb_2_bittiming_const;
struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *bt = &priv->can.bittiming;
union esd_usb_msg *msg;
@@ -930,35 +926,35 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
canbtr |= ESD_USB_LOM;
- canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
+ canbtr |= (bt->brp - 1) & (btc->brp_max - 1);
if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) ==
- USB_CANUSBM_PRODUCT_ID)
- sjw_shift = ESD_USBM_SJW_SHIFT;
+ ESD_USB_CANUSBM_PRODUCT_ID)
+ sjw_shift = ESD_USB_M_SJW_SHIFT;
else
- sjw_shift = ESD_USB2_SJW_SHIFT;
+ sjw_shift = ESD_USB_2_SJW_SHIFT;
- canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1))
+ canbtr |= ((bt->sjw - 1) & (btc->sjw_max - 1))
<< sjw_shift;
canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)
- & (ESD_USB2_TSEG1_MAX - 1))
- << ESD_USB2_TSEG1_SHIFT;
- canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1))
- << ESD_USB2_TSEG2_SHIFT;
+ & (btc->tseg1_max - 1))
+ << ESD_USB_2_TSEG1_SHIFT;
+ canbtr |= ((bt->phase_seg2 - 1) & (btc->tseg2_max - 1))
+ << ESD_USB_2_TSEG2_SHIFT;
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
- canbtr |= ESD_USB2_3_SAMPLES;
+ canbtr |= ESD_USB_TRIPLE_SAMPLES;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
- msg->hdr.len = 2;
- msg->hdr.cmd = CMD_SETBAUD;
+ msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */
+ msg->hdr.cmd = ESD_USB_CMD_SETBAUD;
msg->setbaud.net = priv->index;
msg->setbaud.rsvd = 0;
msg->setbaud.baud = cpu_to_le32(canbtr);
- netdev_info(netdev, "setting BTR=%#x\n", canbtr);
+ netdev_dbg(netdev, "setting BTR=%#x\n", canbtr);
err = esd_usb_send_msg(priv->usb, msg);
@@ -999,7 +995,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
int err = 0;
int i;
- netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+ netdev = alloc_candev(sizeof(*priv), ESD_USB_MAX_TX_URBS);
if (!netdev) {
dev_err(&intf->dev, "couldn't alloc candev\n");
err = -ENOMEM;
@@ -1011,8 +1007,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
init_usb_anchor(&priv->tx_submitted);
atomic_set(&priv->active_tx_jobs, 0);
- for (i = 0; i < MAX_TX_URBS; i++)
- priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+ for (i = 0; i < ESD_USB_MAX_TX_URBS; i++)
+ priv->tx_contexts[i].echo_index = ESD_USB_MAX_TX_URBS;
priv->usb = dev;
priv->netdev = netdev;
@@ -1024,15 +1020,15 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
CAN_CTRLMODE_BERR_REPORTING;
if (le16_to_cpu(dev->udev->descriptor.idProduct) ==
- USB_CANUSBM_PRODUCT_ID)
- priv->can.clock.freq = ESD_USBM_CAN_CLOCK;
+ ESD_USB_CANUSBM_PRODUCT_ID)
+ priv->can.clock.freq = ESD_USB_M_CAN_CLOCK;
else {
- priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+ priv->can.clock.freq = ESD_USB_2_CAN_CLOCK;
priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
}
- priv->can.bittiming_const = &esd_usb2_bittiming_const;
- priv->can.do_set_bittiming = esd_usb2_set_bittiming;
+ priv->can.bittiming_const = &esd_usb_2_bittiming_const;
+ priv->can.do_set_bittiming = esd_usb_2_set_bittiming;
priv->can.do_set_mode = esd_usb_set_mode;
priv->can.do_get_berr_counter = esd_usb_get_berr_counter;
@@ -1090,8 +1086,8 @@ static int esd_usb_probe(struct usb_interface *intf,
}
/* query number of CAN interfaces (nets) */
- msg->hdr.cmd = CMD_VERSION;
- msg->hdr.len = 2;
+ msg->hdr.cmd = ESD_USB_CMD_VERSION;
+ msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */
msg->version.rsvd = 0;
msg->version.flags = 0;
msg->version.drv_version = 0;
diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c
new file mode 100644
index 000000000000..ec8cef7fd2d5
--- /dev/null
+++ b/drivers/net/can/usb/f81604.c
@@ -0,0 +1,1201 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Fintek F81604 USB-to-2CAN controller driver.
+ *
+ * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
+ */
+#include <linux/bitfield.h>
+#include <linux/netdevice.h>
+#include <linux/units.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/platform/sja1000.h>
+
+#include <asm-generic/unaligned.h>
+
+/* vendor and product id */
+#define F81604_VENDOR_ID 0x2c42
+#define F81604_PRODUCT_ID 0x1709
+#define F81604_CAN_CLOCK (12 * MEGA)
+#define F81604_MAX_DEV 2
+#define F81604_SET_DEVICE_RETRY 10
+
+#define F81604_USB_TIMEOUT 2000
+#define F81604_SET_GET_REGISTER 0xA0
+#define F81604_PORT_OFFSET 0x1000
+#define F81604_MAX_RX_URBS 4
+
+#define F81604_CMD_DATA 0x00
+
+#define F81604_DLC_LEN_MASK GENMASK(3, 0)
+#define F81604_DLC_EFF_BIT BIT(7)
+#define F81604_DLC_RTR_BIT BIT(6)
+
+#define F81604_SFF_SHIFT 5
+#define F81604_EFF_SHIFT 3
+
+#define F81604_BRP_MASK GENMASK(5, 0)
+#define F81604_SJW_MASK GENMASK(7, 6)
+
+#define F81604_SEG1_MASK GENMASK(3, 0)
+#define F81604_SEG2_MASK GENMASK(6, 4)
+
+#define F81604_CLEAR_ALC 0
+#define F81604_CLEAR_ECC 1
+#define F81604_CLEAR_OVERRUN 2
+
+/* device setting */
+#define F81604_CTRL_MODE_REG 0x80
+#define F81604_TX_ONESHOT (0x03 << 3)
+#define F81604_TX_NORMAL (0x01 << 3)
+#define F81604_RX_AUTO_RELEASE_BUF BIT(1)
+#define F81604_INT_WHEN_CHANGE BIT(0)
+
+#define F81604_TERMINATOR_REG 0x105
+#define F81604_CAN0_TERM BIT(2)
+#define F81604_CAN1_TERM BIT(3)
+
+#define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
+#define F81604_TERMINATION_ENABLED 120
+
+/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
+#define F81604_SJA1000_MOD 0x00
+#define F81604_SJA1000_CMR 0x01
+#define F81604_SJA1000_IR 0x03
+#define F81604_SJA1000_IER 0x04
+#define F81604_SJA1000_ALC 0x0B
+#define F81604_SJA1000_ECC 0x0C
+#define F81604_SJA1000_RXERR 0x0E
+#define F81604_SJA1000_TXERR 0x0F
+#define F81604_SJA1000_ACCC0 0x10
+#define F81604_SJA1000_ACCM0 0x14
+#define F81604_MAX_FILTER_CNT 4
+
+/* Common registers - manual section 6.5 */
+#define F81604_SJA1000_BTR0 0x06
+#define F81604_SJA1000_BTR1 0x07
+#define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7)
+#define F81604_SJA1000_OCR 0x08
+#define F81604_SJA1000_CDR 0x1F
+
+/* mode register */
+#define F81604_SJA1000_MOD_RM 0x01
+#define F81604_SJA1000_MOD_LOM 0x02
+#define F81604_SJA1000_MOD_STM 0x04
+
+/* commands */
+#define F81604_SJA1000_CMD_CDO 0x08
+
+/* interrupt sources */
+#define F81604_SJA1000_IRQ_BEI 0x80
+#define F81604_SJA1000_IRQ_ALI 0x40
+#define F81604_SJA1000_IRQ_EPI 0x20
+#define F81604_SJA1000_IRQ_DOI 0x08
+#define F81604_SJA1000_IRQ_EI 0x04
+#define F81604_SJA1000_IRQ_TI 0x02
+#define F81604_SJA1000_IRQ_RI 0x01
+#define F81604_SJA1000_IRQ_ALL 0xFF
+#define F81604_SJA1000_IRQ_OFF 0x00
+
+/* status register content */
+#define F81604_SJA1000_SR_BS 0x80
+#define F81604_SJA1000_SR_ES 0x40
+#define F81604_SJA1000_SR_TCS 0x08
+
+/* ECC register */
+#define F81604_SJA1000_ECC_SEG 0x1F
+#define F81604_SJA1000_ECC_DIR 0x20
+#define F81604_SJA1000_ECC_BIT 0x00
+#define F81604_SJA1000_ECC_FORM 0x40
+#define F81604_SJA1000_ECC_STUFF 0x80
+#define F81604_SJA1000_ECC_MASK 0xc0
+
+/* ALC register */
+#define F81604_SJA1000_ALC_MASK 0x1f
+
+/* table of devices that work with this driver */
+static const struct usb_device_id f81604_table[] = {
+ { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, f81604_table);
+
+static const struct ethtool_ops f81604_ethtool_ops = {
+ .get_ts_info = ethtool_op_get_ts_info,
+};
+
+static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED,
+ F81604_TERMINATION_ENABLED };
+
+struct f81604_priv {
+ struct net_device *netdev[F81604_MAX_DEV];
+};
+
+struct f81604_port_priv {
+ struct can_priv can;
+ struct net_device *netdev;
+ struct sk_buff *echo_skb;
+
+ unsigned long clear_flags;
+ struct work_struct clear_reg_work;
+
+ struct usb_device *dev;
+ struct usb_interface *intf;
+
+ struct usb_anchor urbs_anchor;
+};
+
+/* Interrupt endpoint data format:
+ * Byte 0: Status register.
+ * Byte 1: Interrupt register.
+ * Byte 2: Interrupt enable register.
+ * Byte 3: Arbitration lost capture(ALC) register.
+ * Byte 4: Error code capture(ECC) register.
+ * Byte 5: Error warning limit register.
+ * Byte 6: RX error counter register.
+ * Byte 7: TX error counter register.
+ * Byte 8: Reserved.
+ */
+struct f81604_int_data {
+ u8 sr;
+ u8 isrc;
+ u8 ier;
+ u8 alc;
+ u8 ecc;
+ u8 ewlr;
+ u8 rxerr;
+ u8 txerr;
+ u8 val;
+} __packed __aligned(4);
+
+struct f81604_sff {
+ __be16 id;
+ u8 data[CAN_MAX_DLEN];
+} __packed __aligned(2);
+
+struct f81604_eff {
+ __be32 id;
+ u8 data[CAN_MAX_DLEN];
+} __packed __aligned(2);
+
+struct f81604_can_frame {
+ u8 cmd;
+
+ /* According for F81604 DLC define:
+ * bit 3~0: data length (0~8)
+ * bit6: is RTR flag.
+ * bit7: is EFF frame.
+ */
+ u8 dlc;
+
+ union {
+ struct f81604_sff sff;
+ struct f81604_eff eff;
+ };
+} __packed __aligned(2);
+
+static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 };
+static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 };
+static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 };
+
+static int f81604_write(struct usb_device *dev, u16 reg, u8 data)
+{
+ int ret;
+
+ ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER,
+ USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg,
+ &data, sizeof(data), F81604_USB_TIMEOUT,
+ GFP_KERNEL);
+ if (ret)
+ dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n",
+ __func__, reg, data, ERR_PTR(ret));
+
+ return ret;
+}
+
+static int f81604_read(struct usb_device *dev, u16 reg, u8 *data)
+{
+ int ret;
+
+ ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER,
+ USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data,
+ sizeof(*data), F81604_USB_TIMEOUT,
+ GFP_KERNEL);
+
+ if (ret < 0)
+ dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg,
+ ERR_PTR(ret));
+
+ return ret;
+}
+
+static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask,
+ u8 data)
+{
+ int ret;
+ u8 tmp;
+
+ ret = f81604_read(dev, reg, &tmp);
+ if (ret)
+ return ret;
+
+ tmp &= ~mask;
+ tmp |= (mask & data);
+
+ return f81604_write(dev, reg, tmp);
+}
+
+static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg,
+ u8 data)
+{
+ int port = priv->netdev->dev_port;
+ int real_reg;
+
+ real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
+ return f81604_write(priv->dev, real_reg, data);
+}
+
+static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg,
+ u8 *data)
+{
+ int port = priv->netdev->dev_port;
+ int real_reg;
+
+ real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET;
+ return f81604_read(priv->dev, real_reg, data);
+}
+
+static int f81604_set_reset_mode(struct f81604_port_priv *priv)
+{
+ int ret, i;
+ u8 tmp;
+
+ /* disable interrupts */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_IER,
+ F81604_SJA1000_IRQ_OFF);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
+ if (ret)
+ return ret;
+
+ /* check reset bit */
+ if (tmp & F81604_SJA1000_MOD_RM) {
+ priv->can.state = CAN_STATE_STOPPED;
+ return 0;
+ }
+
+ /* reset chip */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD,
+ F81604_SJA1000_MOD_RM);
+ if (ret)
+ return ret;
+ }
+
+ return -EPERM;
+}
+
+static int f81604_set_normal_mode(struct f81604_port_priv *priv)
+{
+ u8 tmp, ier = 0;
+ u8 mod_reg = 0;
+ int ret, i;
+
+ for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) {
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp);
+ if (ret)
+ return ret;
+
+ /* check reset bit */
+ if ((tmp & F81604_SJA1000_MOD_RM) == 0) {
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+ /* enable interrupts, RI handled by bulk-in */
+ ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI;
+ if (!(priv->can.ctrlmode &
+ CAN_CTRLMODE_BERR_REPORTING))
+ ier &= ~F81604_SJA1000_IRQ_BEI;
+
+ return f81604_sja1000_write(priv, F81604_SJA1000_IER,
+ ier);
+ }
+
+ /* set chip to normal mode */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ mod_reg |= F81604_SJA1000_MOD_LOM;
+ if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+ mod_reg |= F81604_SJA1000_MOD_STM;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg);
+ if (ret)
+ return ret;
+ }
+
+ return -EPERM;
+}
+
+static int f81604_chipset_init(struct f81604_port_priv *priv)
+{
+ int i, ret;
+
+ /* set clock divider and output control register */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR,
+ CDR_CBP | CDR_PELICAN);
+ if (ret)
+ return ret;
+
+ /* set acceptance filter (accept all) */
+ for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) {
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i,
+ 0xFF);
+ if (ret)
+ return ret;
+ }
+
+ return f81604_sja1000_write(priv, F81604_SJA1000_OCR,
+ OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL |
+ OCR_MODE_NORMAL);
+}
+
+static void f81604_process_rx_packet(struct net_device *netdev,
+ struct f81604_can_frame *frame)
+{
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ if (frame->cmd != F81604_CMD_DATA)
+ return;
+
+ skb = alloc_can_skb(netdev, &cf);
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK);
+
+ if (frame->dlc & F81604_DLC_EFF_BIT) {
+ cf->can_id = get_unaligned_be32(&frame->eff.id) >>
+ F81604_EFF_SHIFT;
+ cf->can_id |= CAN_EFF_FLAG;
+
+ if (!(frame->dlc & F81604_DLC_RTR_BIT))
+ memcpy(cf->data, frame->eff.data, cf->len);
+ } else {
+ cf->can_id = get_unaligned_be16(&frame->sff.id) >>
+ F81604_SFF_SHIFT;
+
+ if (!(frame->dlc & F81604_DLC_RTR_BIT))
+ memcpy(cf->data, frame->sff.data, cf->len);
+ }
+
+ if (frame->dlc & F81604_DLC_RTR_BIT)
+ cf->can_id |= CAN_RTR_FLAG;
+ else
+ stats->rx_bytes += cf->len;
+
+ stats->rx_packets++;
+ netif_rx(skb);
+}
+
+static void f81604_read_bulk_callback(struct urb *urb)
+{
+ struct f81604_can_frame *frame = urb->transfer_buffer;
+ struct net_device *netdev = urb->context;
+ int ret;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: URB aborted %pe\n", __func__,
+ ERR_PTR(urb->status));
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+
+ case -ENOENT:
+ case -EPIPE:
+ case -EPROTO:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ goto resubmit_urb;
+ }
+
+ if (urb->actual_length != sizeof(*frame)) {
+ netdev_warn(netdev, "URB length %u not equal to %zu\n",
+ urb->actual_length, sizeof(*frame));
+ goto resubmit_urb;
+ }
+
+ f81604_process_rx_packet(netdev, frame);
+
+resubmit_urb:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else if (ret)
+ netdev_err(netdev,
+ "%s: failed to resubmit read bulk urb: %pe\n",
+ __func__, ERR_PTR(ret));
+}
+
+static void f81604_handle_tx(struct f81604_port_priv *priv,
+ struct f81604_int_data *data)
+{
+ struct net_device *netdev = priv->netdev;
+ struct net_device_stats *stats = &netdev->stats;
+
+ /* transmission buffer released */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT &&
+ !(data->sr & F81604_SJA1000_SR_TCS)) {
+ stats->tx_errors++;
+ can_free_echo_skb(netdev, 0, NULL);
+ } else {
+ /* transmission complete */
+ stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL);
+ stats->tx_packets++;
+ }
+
+ netif_wake_queue(netdev);
+}
+
+static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
+ struct f81604_int_data *data)
+{
+ enum can_state can_state = priv->can.state;
+ struct net_device *netdev = priv->netdev;
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ /* Note: ALC/ECC will not auto clear by read here, must be cleared by
+ * read register (via clear_reg_work).
+ */
+
+ skb = alloc_can_err_skb(netdev, &cf);
+ if (skb) {
+ cf->can_id |= CAN_ERR_CNT;
+ cf->data[6] = data->txerr;
+ cf->data[7] = data->rxerr;
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_DOI) {
+ /* data overrun interrupt */
+ netdev_dbg(netdev, "data overrun interrupt\n");
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+
+ set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_EI) {
+ /* error warning interrupt */
+ netdev_dbg(netdev, "error warning interrupt\n");
+
+ if (data->sr & F81604_SJA1000_SR_BS)
+ can_state = CAN_STATE_BUS_OFF;
+ else if (data->sr & F81604_SJA1000_SR_ES)
+ can_state = CAN_STATE_ERROR_WARNING;
+ else
+ can_state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_BEI) {
+ /* bus error interrupt */
+ netdev_dbg(netdev, "bus error interrupt\n");
+
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ /* set error type */
+ switch (data->ecc & F81604_SJA1000_ECC_MASK) {
+ case F81604_SJA1000_ECC_BIT:
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ break;
+ case F81604_SJA1000_ECC_FORM:
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case F81604_SJA1000_ECC_STUFF:
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ default:
+ break;
+ }
+
+ /* set error location */
+ cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
+
+ /* Error occurred during transmission? */
+ if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ }
+
+ set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_EPI) {
+ if (can_state == CAN_STATE_ERROR_PASSIVE)
+ can_state = CAN_STATE_ERROR_WARNING;
+ else
+ can_state = CAN_STATE_ERROR_PASSIVE;
+
+ /* error passive interrupt */
+ netdev_dbg(netdev, "error passive interrupt: %d\n", can_state);
+ }
+
+ if (data->isrc & F81604_SJA1000_IRQ_ALI) {
+ /* arbitration lost interrupt */
+ netdev_dbg(netdev, "arbitration lost interrupt\n");
+
+ priv->can.can_stats.arbitration_lost++;
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_LOSTARB;
+ cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK;
+ }
+
+ set_bit(F81604_CLEAR_ALC, &priv->clear_flags);
+ }
+
+ if (can_state != priv->can.state) {
+ enum can_state tx_state, rx_state;
+
+ tx_state = data->txerr >= data->rxerr ? can_state : 0;
+ rx_state = data->txerr <= data->rxerr ? can_state : 0;
+
+ can_change_state(netdev, cf, tx_state, rx_state);
+
+ if (can_state == CAN_STATE_BUS_OFF)
+ can_bus_off(netdev);
+ }
+
+ if (priv->clear_flags)
+ schedule_work(&priv->clear_reg_work);
+
+ if (skb)
+ netif_rx(skb);
+}
+
+static void f81604_read_int_callback(struct urb *urb)
+{
+ struct f81604_int_data *data = urb->transfer_buffer;
+ struct net_device *netdev = urb->context;
+ struct f81604_port_priv *priv;
+ int ret;
+
+ priv = netdev_priv(netdev);
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__,
+ ERR_PTR(urb->status));
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+
+ case -ENOENT:
+ case -EPIPE:
+ case -EPROTO:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ goto resubmit_urb;
+ }
+
+ /* handle Errors */
+ if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI |
+ F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI |
+ F81604_SJA1000_IRQ_ALI))
+ f81604_handle_can_bus_errors(priv, data);
+
+ /* handle TX */
+ if (priv->can.state != CAN_STATE_BUS_OFF &&
+ (data->isrc & F81604_SJA1000_IRQ_TI))
+ f81604_handle_tx(priv, data);
+
+resubmit_urb:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else if (ret)
+ netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n",
+ __func__, ERR_PTR(ret));
+}
+
+static void f81604_unregister_urbs(struct f81604_port_priv *priv)
+{
+ usb_kill_anchored_urbs(&priv->urbs_anchor);
+}
+
+static int f81604_register_urbs(struct f81604_port_priv *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ struct f81604_int_data *int_data;
+ int id = netdev->dev_port;
+ struct urb *int_urb;
+ int rx_urb_cnt;
+ int ret;
+
+ for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) {
+ struct f81604_can_frame *frame;
+ struct urb *rx_urb;
+
+ rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rx_urb) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ frame = kmalloc(sizeof(*frame), GFP_KERNEL);
+ if (!frame) {
+ usb_free_urb(rx_urb);
+ ret = -ENOMEM;
+ break;
+ }
+
+ usb_fill_bulk_urb(rx_urb, priv->dev,
+ usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]),
+ frame, sizeof(*frame),
+ f81604_read_bulk_callback, netdev);
+
+ rx_urb->transfer_flags |= URB_FREE_BUFFER;
+ usb_anchor_urb(rx_urb, &priv->urbs_anchor);
+
+ ret = usb_submit_urb(rx_urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(rx_urb);
+ usb_free_urb(rx_urb);
+ break;
+ }
+
+ /* Drop reference, USB core will take care of freeing it */
+ usb_free_urb(rx_urb);
+ }
+
+ if (rx_urb_cnt == 0) {
+ netdev_warn(netdev, "%s: submit rx urb failed: %pe\n",
+ __func__, ERR_PTR(ret));
+
+ goto error;
+ }
+
+ int_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!int_urb) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ int_data = kmalloc(sizeof(*int_data), GFP_KERNEL);
+ if (!int_data) {
+ usb_free_urb(int_urb);
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ usb_fill_int_urb(int_urb, priv->dev,
+ usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data,
+ sizeof(*int_data), f81604_read_int_callback, netdev,
+ 1);
+
+ int_urb->transfer_flags |= URB_FREE_BUFFER;
+ usb_anchor_urb(int_urb, &priv->urbs_anchor);
+
+ ret = usb_submit_urb(int_urb, GFP_KERNEL);
+ if (ret) {
+ usb_unanchor_urb(int_urb);
+ usb_free_urb(int_urb);
+
+ netdev_warn(netdev, "%s: submit int urb failed: %pe\n",
+ __func__, ERR_PTR(ret));
+ goto error;
+ }
+
+ /* Drop reference, USB core will take care of freeing it */
+ usb_free_urb(int_urb);
+
+ return 0;
+
+error:
+ f81604_unregister_urbs(priv);
+ return ret;
+}
+
+static int f81604_start(struct net_device *netdev)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ int ret;
+ u8 mode;
+ u8 tmp;
+
+ mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE;
+
+ /* Set TR/AT mode */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ mode |= F81604_TX_ONESHOT;
+ else
+ mode |= F81604_TX_NORMAL;
+
+ ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode);
+ if (ret)
+ return ret;
+
+ /* set reset mode */
+ ret = f81604_set_reset_mode(priv);
+ if (ret)
+ return ret;
+
+ ret = f81604_chipset_init(priv);
+ if (ret)
+ return ret;
+
+ /* Clear error counters and error code capture */
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0);
+ if (ret)
+ return ret;
+
+ /* Read clear for ECC/ALC/IR register */
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp);
+ if (ret)
+ return ret;
+
+ ret = f81604_register_urbs(priv);
+ if (ret)
+ return ret;
+
+ ret = f81604_set_normal_mode(priv);
+ if (ret) {
+ f81604_unregister_urbs(priv);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int f81604_set_bittiming(struct net_device *dev)
+{
+ struct f81604_port_priv *priv = netdev_priv(dev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ u8 btr0, btr1;
+ int ret;
+
+ btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) |
+ FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1);
+
+ btr1 = FIELD_PREP(F81604_SEG1_MASK,
+ bt->prop_seg + bt->phase_seg1 - 1) |
+ FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1);
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE;
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0);
+ if (ret) {
+ netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__,
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1);
+ if (ret) {
+ netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__,
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int f81604_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+ int ret;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ ret = f81604_start(netdev);
+ if (!ret && netif_queue_stopped(netdev))
+ netif_wake_queue(netdev);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static void f81604_write_bulk_callback(struct urb *urb)
+{
+ struct net_device *netdev = urb->context;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__,
+ ERR_PTR(urb->status));
+}
+
+static void f81604_clear_reg_work(struct work_struct *work)
+{
+ struct f81604_port_priv *priv;
+ u8 tmp;
+
+ priv = container_of(work, struct f81604_port_priv, clear_reg_work);
+
+ /* dummy read for clear Arbitration lost capture(ALC) register. */
+ if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags))
+ f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp);
+
+ /* dummy read for clear Error code capture(ECC) register. */
+ if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags))
+ f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp);
+
+ /* dummy write for clear data overrun flag. */
+ if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags))
+ f81604_sja1000_write(priv, F81604_SJA1000_CMR,
+ F81604_SJA1000_CMD_CDO);
+}
+
+static netdev_tx_t f81604_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ struct net_device_stats *stats = &netdev->stats;
+ struct f81604_can_frame *frame;
+ struct urb *write_urb;
+ int ret;
+
+ if (can_dev_dropped_skb(netdev, skb))
+ return NETDEV_TX_OK;
+
+ netif_stop_queue(netdev);
+
+ write_urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!write_urb)
+ goto nomem_urb;
+
+ frame = kzalloc(sizeof(*frame), GFP_ATOMIC);
+ if (!frame)
+ goto nomem_buf;
+
+ usb_fill_bulk_urb(write_urb, priv->dev,
+ usb_sndbulkpipe(priv->dev,
+ bulk_out_addr[netdev->dev_port]),
+ frame, sizeof(*frame), f81604_write_bulk_callback,
+ priv->netdev);
+
+ write_urb->transfer_flags |= URB_FREE_BUFFER;
+
+ frame->cmd = F81604_CMD_DATA;
+ frame->dlc = cf->len;
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ frame->dlc |= F81604_DLC_RTR_BIT;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT;
+
+ put_unaligned_be32(id, &frame->eff.id);
+
+ frame->dlc |= F81604_DLC_EFF_BIT;
+
+ if (!(cf->can_id & CAN_RTR_FLAG))
+ memcpy(&frame->eff.data, cf->data, cf->len);
+ } else {
+ u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT;
+
+ put_unaligned_be16(id, &frame->sff.id);
+
+ if (!(cf->can_id & CAN_RTR_FLAG))
+ memcpy(&frame->sff.data, cf->data, cf->len);
+ }
+
+ can_put_echo_skb(skb, netdev, 0, 0);
+
+ ret = usb_submit_urb(write_urb, GFP_ATOMIC);
+ if (ret) {
+ netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n",
+ __func__, ERR_PTR(ret));
+
+ can_free_echo_skb(netdev, 0, NULL);
+ stats->tx_dropped++;
+ stats->tx_errors++;
+
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else
+ netif_wake_queue(netdev);
+ }
+
+ /* let usb core take care of this urb */
+ usb_free_urb(write_urb);
+
+ return NETDEV_TX_OK;
+
+nomem_buf:
+ usb_free_urb(write_urb);
+
+nomem_urb:
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ stats->tx_errors++;
+ netif_wake_queue(netdev);
+
+ return NETDEV_TX_OK;
+}
+
+static int f81604_get_berr_counter(const struct net_device *netdev,
+ struct can_berr_counter *bec)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+ u8 txerr, rxerr;
+ int ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr);
+ if (ret)
+ return ret;
+
+ ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr);
+ if (ret)
+ return ret;
+
+ bec->txerr = txerr;
+ bec->rxerr = rxerr;
+
+ return 0;
+}
+
+/* Open USB device */
+static int f81604_open(struct net_device *netdev)
+{
+ int ret;
+
+ ret = open_candev(netdev);
+ if (ret)
+ return ret;
+
+ ret = f81604_start(netdev);
+ if (ret) {
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+
+ close_candev(netdev);
+ return ret;
+ }
+
+ netif_start_queue(netdev);
+ return 0;
+}
+
+/* Close USB device */
+static int f81604_close(struct net_device *netdev)
+{
+ struct f81604_port_priv *priv = netdev_priv(netdev);
+
+ f81604_set_reset_mode(priv);
+
+ netif_stop_queue(netdev);
+ cancel_work_sync(&priv->clear_reg_work);
+ close_candev(netdev);
+
+ f81604_unregister_urbs(priv);
+
+ return 0;
+}
+
+static const struct net_device_ops f81604_netdev_ops = {
+ .ndo_open = f81604_open,
+ .ndo_stop = f81604_close,
+ .ndo_start_xmit = f81604_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
+};
+
+static const struct can_bittiming_const f81604_bittiming_const = {
+ .name = KBUILD_MODNAME,
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 64,
+ .brp_inc = 1,
+};
+
+/* Called by the usb core when driver is unloaded or device is removed */
+static void f81604_disconnect(struct usb_interface *intf)
+{
+ struct f81604_priv *priv = usb_get_intfdata(intf);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ if (!priv->netdev[i])
+ continue;
+
+ unregister_netdev(priv->netdev[i]);
+ free_candev(priv->netdev[i]);
+ }
+}
+
+static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term)
+{
+ u8 mask, data = 0;
+
+ if (idx == 0)
+ mask = F81604_CAN0_TERM;
+ else
+ mask = F81604_CAN1_TERM;
+
+ if (term)
+ data = mask;
+
+ return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data);
+}
+
+static int f81604_set_termination(struct net_device *netdev, u16 term)
+{
+ struct f81604_port_priv *port_priv = netdev_priv(netdev);
+
+ ASSERT_RTNL();
+
+ return __f81604_set_termination(port_priv->dev, netdev->dev_port,
+ term);
+}
+
+static int f81604_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct net_device *netdev;
+ struct f81604_priv *priv;
+ int i, ret;
+
+ priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ usb_set_intfdata(intf, priv);
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ ret = __f81604_set_termination(dev, i, 0);
+ if (ret) {
+ dev_err(&intf->dev,
+ "Setting termination of CH#%d failed: %pe\n",
+ i, ERR_PTR(ret));
+ return ret;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) {
+ struct f81604_port_priv *port_priv;
+
+ netdev = alloc_candev(sizeof(*port_priv), 1);
+ if (!netdev) {
+ dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i);
+ ret = -ENOMEM;
+
+ goto failure_cleanup;
+ }
+
+ port_priv = netdev_priv(netdev);
+
+ INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work);
+ init_usb_anchor(&port_priv->urbs_anchor);
+
+ port_priv->intf = intf;
+ port_priv->dev = dev;
+ port_priv->netdev = netdev;
+ port_priv->can.clock.freq = F81604_CAN_CLOCK;
+
+ port_priv->can.termination_const = f81604_termination;
+ port_priv->can.termination_const_cnt =
+ ARRAY_SIZE(f81604_termination);
+ port_priv->can.bittiming_const = &f81604_bittiming_const;
+ port_priv->can.do_set_bittiming = f81604_set_bittiming;
+ port_priv->can.do_set_mode = f81604_set_mode;
+ port_priv->can.do_set_termination = f81604_set_termination;
+ port_priv->can.do_get_berr_counter = f81604_get_berr_counter;
+ port_priv->can.ctrlmode_supported =
+ CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
+ CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_PRESUME_ACK;
+
+ netdev->ethtool_ops = &f81604_ethtool_ops;
+ netdev->netdev_ops = &f81604_netdev_ops;
+ netdev->flags |= IFF_ECHO;
+ netdev->dev_port = i;
+
+ SET_NETDEV_DEV(netdev, &intf->dev);
+
+ ret = register_candev(netdev);
+ if (ret) {
+ netdev_err(netdev, "register CAN device failed: %pe\n",
+ ERR_PTR(ret));
+ free_candev(netdev);
+
+ goto failure_cleanup;
+ }
+
+ priv->netdev[i] = netdev;
+ }
+
+ return 0;
+
+failure_cleanup:
+ f81604_disconnect(intf);
+ return ret;
+}
+
+static struct usb_driver f81604_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = f81604_probe,
+ .disconnect = f81604_disconnect,
+ .id_table = f81604_table,
+};
+
+module_usb_driver(f81604_driver);
+
+MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>");
+MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index d476c2884008..129ef60a577c 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -303,12 +303,6 @@ struct gs_can {
struct can_bittiming_const bt_const, data_bt_const;
unsigned int channel; /* channel number */
- /* time counter for hardware timestamps */
- struct cyclecounter cc;
- struct timecounter tc;
- spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
- struct delayed_work timestamp;
-
u32 feature;
unsigned int hf_size_tx;
@@ -325,6 +319,13 @@ struct gs_usb {
struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted;
struct usb_device *udev;
+
+ /* time counter for hardware timestamps */
+ struct cyclecounter cc;
+ struct timecounter tc;
+ spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
+ struct delayed_work timestamp;
+
unsigned int hf_size_rx;
u8 active_channels;
};
@@ -388,15 +389,15 @@ static int gs_cmd_reset(struct gs_can *dev)
GFP_KERNEL);
}
-static inline int gs_usb_get_timestamp(const struct gs_can *dev,
+static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
u32 *timestamp_p)
{
__le32 timestamp;
int rc;
- rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_TIMESTAMP,
+ rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
- dev->channel, 0,
+ 0, 0,
&timestamp, sizeof(timestamp),
USB_CTRL_GET_TIMEOUT,
GFP_KERNEL);
@@ -410,20 +411,20 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
{
- struct gs_can *dev = container_of(cc, struct gs_can, cc);
+ struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
u32 timestamp = 0;
int err;
- lockdep_assert_held(&dev->tc_lock);
+ lockdep_assert_held(&parent->tc_lock);
/* drop lock for synchronous USB transfer */
- spin_unlock_bh(&dev->tc_lock);
- err = gs_usb_get_timestamp(dev, &timestamp);
- spin_lock_bh(&dev->tc_lock);
+ spin_unlock_bh(&parent->tc_lock);
+ err = gs_usb_get_timestamp(parent, &timestamp);
+ spin_lock_bh(&parent->tc_lock);
if (err)
- netdev_err(dev->netdev,
- "Error %d while reading timestamp. HW timestamps may be inaccurate.",
- err);
+ dev_err(&parent->udev->dev,
+ "Error %d while reading timestamp. HW timestamps may be inaccurate.",
+ err);
return timestamp;
}
@@ -431,14 +432,14 @@ static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev
static void gs_usb_timestamp_work(struct work_struct *work)
{
struct delayed_work *delayed_work = to_delayed_work(work);
- struct gs_can *dev;
+ struct gs_usb *parent;
- dev = container_of(delayed_work, struct gs_can, timestamp);
- spin_lock_bh(&dev->tc_lock);
- timecounter_read(&dev->tc);
- spin_unlock_bh(&dev->tc_lock);
+ parent = container_of(delayed_work, struct gs_usb, timestamp);
+ spin_lock_bh(&parent->tc_lock);
+ timecounter_read(&parent->tc);
+ spin_unlock_bh(&parent->tc_lock);
- schedule_delayed_work(&dev->timestamp,
+ schedule_delayed_work(&parent->timestamp,
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
@@ -446,37 +447,38 @@ static void gs_usb_skb_set_timestamp(struct gs_can *dev,
struct sk_buff *skb, u32 timestamp)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
+ struct gs_usb *parent = dev->parent;
u64 ns;
- spin_lock_bh(&dev->tc_lock);
- ns = timecounter_cyc2time(&dev->tc, timestamp);
- spin_unlock_bh(&dev->tc_lock);
+ spin_lock_bh(&parent->tc_lock);
+ ns = timecounter_cyc2time(&parent->tc, timestamp);
+ spin_unlock_bh(&parent->tc_lock);
hwtstamps->hwtstamp = ns_to_ktime(ns);
}
-static void gs_usb_timestamp_init(struct gs_can *dev)
+static void gs_usb_timestamp_init(struct gs_usb *parent)
{
- struct cyclecounter *cc = &dev->cc;
+ struct cyclecounter *cc = &parent->cc;
cc->read = gs_usb_timestamp_read;
cc->mask = CYCLECOUNTER_MASK(32);
cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
- spin_lock_init(&dev->tc_lock);
- spin_lock_bh(&dev->tc_lock);
- timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
- spin_unlock_bh(&dev->tc_lock);
+ spin_lock_init(&parent->tc_lock);
+ spin_lock_bh(&parent->tc_lock);
+ timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
+ spin_unlock_bh(&parent->tc_lock);
- INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
- schedule_delayed_work(&dev->timestamp,
+ INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
+ schedule_delayed_work(&parent->timestamp,
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
}
-static void gs_usb_timestamp_stop(struct gs_can *dev)
+static void gs_usb_timestamp_stop(struct gs_usb *parent)
{
- cancel_delayed_work_sync(&dev->timestamp);
+ cancel_delayed_work_sync(&parent->timestamp);
}
static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
@@ -560,6 +562,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
if (!netif_device_present(netdev))
return;
+ if (!netif_running(netdev))
+ goto resubmit_urb;
+
if (hf->echo_id == -1) { /* normal rx */
if (hf->flags & GS_CAN_FLAG_FD) {
skb = alloc_canfd_skb(dev->netdev, &cfd);
@@ -628,6 +633,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
}
if (hf->flags & GS_CAN_FLAG_OVERFLOW) {
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+
skb = alloc_can_err_skb(netdev, &cf);
if (!skb)
goto resubmit_urb;
@@ -635,8 +643,6 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
cf->can_id |= CAN_ERR_CRTL;
cf->len = CAN_ERR_DLC;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- stats->rx_over_errors++;
- stats->rx_errors++;
netif_rx(skb);
}
@@ -833,6 +839,7 @@ static int gs_can_open(struct net_device *netdev)
.mode = cpu_to_le32(GS_CAN_MODE_START),
};
struct gs_host_frame *hf;
+ struct urb *urb = NULL;
u32 ctrlmode;
u32 flags = 0;
int rc, i;
@@ -855,14 +862,18 @@ static int gs_can_open(struct net_device *netdev)
}
if (!parent->active_channels) {
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_init(parent);
+
for (i = 0; i < GS_MAX_RX_URBS; i++) {
- struct urb *urb;
u8 *buf;
/* alloc rx urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
+ if (!urb) {
+ rc = -ENOMEM;
+ goto out_usb_kill_anchored_urbs;
+ }
/* alloc rx buffer */
buf = kmalloc(dev->parent->hf_size_rx,
@@ -870,8 +881,8 @@ static int gs_can_open(struct net_device *netdev)
if (!buf) {
netdev_err(netdev,
"No memory left for USB buffer\n");
- usb_free_urb(urb);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out_usb_free_urb;
}
/* fill, anchor, and submit rx urb */
@@ -894,9 +905,7 @@ static int gs_can_open(struct net_device *netdev)
netdev_err(netdev,
"usb_submit failed (err=%d)\n", rc);
- usb_unanchor_urb(urb);
- usb_free_urb(urb);
- break;
+ goto out_usb_unanchor_urb;
}
/* Drop reference,
@@ -926,13 +935,9 @@ static int gs_can_open(struct net_device *netdev)
flags |= GS_CAN_MODE_FD;
/* if hardware supports timestamps, enable it */
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
flags |= GS_CAN_MODE_HW_TIMESTAMP;
- /* start polling timestamp */
- gs_usb_timestamp_init(dev);
- }
-
/* finally start device */
dev->can.state = CAN_STATE_ERROR_ACTIVE;
dm.flags = cpu_to_le32(flags);
@@ -942,10 +947,9 @@ static int gs_can_open(struct net_device *netdev)
GFP_KERNEL);
if (rc) {
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- gs_usb_timestamp_stop(dev);
dev->can.state = CAN_STATE_STOPPED;
- return rc;
+
+ goto out_usb_kill_anchored_urbs;
}
parent->active_channels++;
@@ -953,6 +957,22 @@ static int gs_can_open(struct net_device *netdev)
netif_start_queue(netdev);
return 0;
+
+out_usb_unanchor_urb:
+ usb_unanchor_urb(urb);
+out_usb_free_urb:
+ usb_free_urb(urb);
+out_usb_kill_anchored_urbs:
+ if (!parent->active_channels) {
+ usb_kill_anchored_urbs(&dev->tx_submitted);
+
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_stop(parent);
+ }
+
+ close_candev(netdev);
+
+ return rc;
}
static int gs_usb_get_state(const struct net_device *netdev,
@@ -998,20 +1018,21 @@ static int gs_can_close(struct net_device *netdev)
netif_stop_queue(netdev);
- /* stop polling timestamp */
- if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
- gs_usb_timestamp_stop(dev);
-
/* Stop polling */
parent->active_channels--;
if (!parent->active_channels) {
usb_kill_anchored_urbs(&parent->rx_submitted);
+
+ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ gs_usb_timestamp_stop(parent);
}
/* Stop sending URBs */
usb_kill_anchored_urbs(&dev->tx_submitted);
atomic_set(&dev->active_tx_urbs, 0);
+ dev->can.state = CAN_STATE_STOPPED;
+
/* reset the device */
rc = gs_cmd_reset(dev);
if (rc < 0)
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index 7135ec851341..71ef4db5c09f 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -816,7 +816,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
init_completion(&priv->stop_comp);
init_completion(&priv->flush_comp);
init_completion(&priv->get_busparams_comp);
- priv->can.ctrlmode_supported = 0;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
priv->dev = dev;
priv->netdev = netdev;
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index ef341c4254fc..c7ba768dfe17 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -1263,7 +1263,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev,
if (flags & KVASER_USB_HYDRA_CF_FLAG_OVERRUN)
kvaser_usb_can_rx_over_error(priv->netdev);
- cf->len = can_cc_dlc2len(cmd->rx_can.dlc);
+ can_frame_set_cc_len((struct can_frame *)cf, cmd->rx_can.dlc, priv->can.ctrlmode);
if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) {
cf->can_id |= CAN_RTR_FLAG;
@@ -1342,7 +1342,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev,
if (flags & KVASER_USB_HYDRA_CF_FLAG_ESI)
cf->flags |= CANFD_ESI;
} else {
- cf->len = can_cc_dlc2len(dlc);
+ can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->can.ctrlmode);
}
if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) {
@@ -1442,7 +1442,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
struct kvaser_usb *dev = priv->dev;
struct kvaser_cmd_ext *cmd;
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
- u8 dlc = can_fd_len2dlc(cf->len);
+ u8 dlc;
u8 nbr_of_bytes = cf->len;
u32 flags;
u32 id;
@@ -1467,6 +1467,11 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv,
cmd->len = cpu_to_le16(*cmd_len);
+ if (can_is_canfd_skb(skb))
+ dlc = can_fd_len2dlc(cf->len);
+ else
+ dlc = can_get_cc_dlc((struct can_frame *)cf, priv->can.ctrlmode);
+
cmd->tx_can.databytes = nbr_of_bytes;
cmd->tx_can.dlc = dlc;
@@ -1542,7 +1547,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv,
id = cf->can_id & CAN_SFF_MASK;
}
- cmd->tx_can.dlc = cf->len;
+ cmd->tx_can.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
flags = (cf->can_id & CAN_EFF_FLAG ?
KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID : 0);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index 1c2f99ce4c6c..23bd7574b1c7 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -573,7 +573,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
cmd->u.tx_can.data[1] = cf->can_id & 0x3f;
}
- cmd->u.tx_can.data[5] = cf->len;
+ cmd->u.tx_can.data[5] = can_get_cc_dlc(cf, priv->can.ctrlmode);
memcpy(&cmd->u.tx_can.data[6], cf->data, cf->len);
if (cf->can_id & CAN_RTR_FLAG)
@@ -1349,7 +1349,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
else
cf->can_id &= CAN_SFF_MASK;
- cf->len = can_cc_dlc2len(cmd->u.leaf.log_message.dlc);
+ can_frame_set_cc_len(cf, cmd->u.leaf.log_message.dlc & 0xF, priv->can.ctrlmode);
if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG;
@@ -1367,7 +1367,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev,
cf->can_id |= CAN_EFF_FLAG;
}
- cf->len = can_cc_dlc2len(rx_data[5]);
+ can_frame_set_cc_len(cf, rx_data[5] & 0xF, priv->can.ctrlmode);
if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG;
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index 4068d962203d..98c669ad5141 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -192,12 +192,7 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
nla_peer = data[VXCAN_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifla(peer_tb,
- nla_data(nla_peer) +
- sizeof(struct ifinfomsg),
- nla_len(nla_peer) -
- sizeof(struct ifinfomsg),
- NULL);
+ err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
if (err < 0)
return err;
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 43c812ea1de0..4d3283db3a13 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
+#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#define DRIVER_NAME "xilinx_can"
@@ -198,6 +199,7 @@ struct xcan_devtype_data {
* @bus_clk: Pointer to struct clk
* @can_clk: Pointer to struct clk
* @devtype: Device type specific constants
+ * @transceiver: Optional pointer to associated CAN transceiver
*/
struct xcan_priv {
struct can_priv can;
@@ -215,6 +217,7 @@ struct xcan_priv {
struct clk *bus_clk;
struct clk *can_clk;
struct xcan_devtype_data devtype;
+ struct phy *transceiver;
};
/* CAN Bittiming constants as per Xilinx CAN specs */
@@ -1419,6 +1422,10 @@ static int xcan_open(struct net_device *ndev)
struct xcan_priv *priv = netdev_priv(ndev);
int ret;
+ ret = phy_power_on(priv->transceiver);
+ if (ret)
+ return ret;
+
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
@@ -1462,6 +1469,7 @@ err_irq:
free_irq(ndev->irq, ndev);
err:
pm_runtime_put(priv->dev);
+ phy_power_off(priv->transceiver);
return ret;
}
@@ -1483,6 +1491,7 @@ static int xcan_close(struct net_device *ndev)
close_candev(ndev);
pm_runtime_put(priv->dev);
+ phy_power_off(priv->transceiver);
return 0;
}
@@ -1713,6 +1722,7 @@ static int xcan_probe(struct platform_device *pdev)
{
struct net_device *ndev;
struct xcan_priv *priv;
+ struct phy *transceiver;
const struct of_device_id *of_id;
const struct xcan_devtype_data *devtype = &xcan_axi_data;
void __iomem *addr;
@@ -1843,6 +1853,14 @@ static int xcan_probe(struct platform_device *pdev)
goto err_free;
}
+ transceiver = devm_phy_optional_get(&pdev->dev, NULL);
+ if (IS_ERR(transceiver)) {
+ ret = PTR_ERR(transceiver);
+ dev_err_probe(&pdev->dev, ret, "failed to get phy\n");
+ goto err_free;
+ }
+ priv->transceiver = transceiver;
+
priv->write_reg = xcan_write_reg_le;
priv->read_reg = xcan_read_reg_le;
@@ -1869,6 +1887,7 @@ static int xcan_probe(struct platform_device *pdev)
goto err_disableclks;
}
+ of_can_transceiver(ndev);
pm_runtime_put(&pdev->dev);
if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
@@ -1898,20 +1917,18 @@ err:
* This function frees all the resources allocated to the device.
* Return: 0 always
*/
-static int xcan_remove(struct platform_device *pdev)
+static void xcan_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
unregister_candev(ndev);
pm_runtime_disable(&pdev->dev);
free_candev(ndev);
-
- return 0;
}
static struct platform_driver xcan_driver = {
.probe = xcan_probe,
- .remove = xcan_remove,
+ .remove_new = xcan_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &xcan_dev_pm_ops,
diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c
index 0690210770ff..b0ccebcd3ffa 100644
--- a/drivers/net/dsa/b53/b53_serdes.c
+++ b/drivers/net/dsa/b53/b53_serdes.c
@@ -65,7 +65,7 @@ static u16 b53_serdes_read(struct b53_device *dev, u8 lane,
return b53_serdes_read_blk(dev, offset, block);
}
-static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int mode,
+static int b53_serdes_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -239,6 +239,7 @@ int b53_serdes_init(struct b53_device *dev, int port)
pcs->dev = dev;
pcs->lane = lane;
pcs->pcs.ops = &b53_pcs_ops;
+ pcs->pcs.neg_mode = true;
return 0;
}
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index cde253d27bd0..72374b066f64 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1436,7 +1436,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv");
if (IS_ERR(priv->clk_mdiv)) {
@@ -1444,7 +1446,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
goto out_clk;
}
- clk_prepare_enable(priv->clk_mdiv);
+ ret = clk_prepare_enable(priv->clk_mdiv);
+ if (ret)
+ goto out_clk;
ret = bcm_sf2_sw_rst(priv);
if (ret) {
diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
index 595a548bb0a8..af50001ccdd4 100644
--- a/drivers/net/dsa/hirschmann/hellcreek.c
+++ b/drivers/net/dsa/hirschmann/hellcreek.c
@@ -1885,13 +1885,17 @@ static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO: {
struct tc_taprio_qopt_offload *taprio = type_data;
- if (!hellcreek_validate_schedule(hellcreek, taprio))
- return -EOPNOTSUPP;
+ switch (taprio->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ if (!hellcreek_validate_schedule(hellcreek, taprio))
+ return -EOPNOTSUPP;
- if (taprio->enable)
return hellcreek_port_set_schedule(ds, port, taprio);
-
- return hellcreek_port_del_schedule(ds, port);
+ case TAPRIO_CMD_DESTROY:
+ return hellcreek_port_del_schedule(ds, port);
+ default:
+ return -EOPNOTSUPP;
+ }
}
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index c0215a8770f4..ff76444057d2 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1458,7 +1458,6 @@ int lan9303_remove(struct lan9303 *chip)
/* assert reset to the whole device to prevent it from doing anything */
gpiod_set_value_cansleep(chip->reset_gpio, 1);
- gpiod_unexport(chip->reset_gpio);
return 0;
}
diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c
index e8844820c3a9..bbbec322bc4f 100644
--- a/drivers/net/dsa/lan9303_i2c.c
+++ b/drivers/net/dsa/lan9303_i2c.c
@@ -105,7 +105,7 @@ static struct i2c_driver lan9303_i2c_driver = {
.name = "LAN9303_I2C",
.of_match_table = lan9303_i2c_of_match,
},
- .probe_new = lan9303_i2c_probe,
+ .probe = lan9303_i2c_probe,
.remove = lan9303_i2c_remove,
.shutdown = lan9303_i2c_shutdown,
.id_table = lan9303_i2c_id,
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index f56fca1b1a22..91aba470fb2f 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -28,13 +28,13 @@
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
- regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -506,7 +506,13 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
shifts[STATIC_MAC_FWD_PORTS];
alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
- data_hi >>= 1;
+
+ /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
+ * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
+ * static MAC table compared to doing write.
+ */
+ if (ksz_is_ksz87xx(dev))
+ data_hi >>= 1;
alu->is_static = true;
alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
@@ -941,7 +947,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
{
u8 learn[DSA_MAX_PORTS];
int first, index, cnt;
- struct ksz_port *p;
const u16 *regs;
regs = dev->info->regs;
@@ -955,9 +960,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
cnt = dev->info->port_cnt;
}
for (index = first; index < cnt; index++) {
- p = &dev->ports[index];
- if (!p->on)
- continue;
ksz_pread8(dev, index, regs[P_STP_CTRL], &learn[index]);
if (!(learn[index] & PORT_LEARN_DISABLE))
ksz_pwrite8(dev, index, regs[P_STP_CTRL],
@@ -965,9 +967,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
}
ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true);
for (index = first; index < cnt; index++) {
- p = &dev->ports[index];
- if (!p->on)
- continue;
if (!(learn[index] & PORT_LEARN_DISABLE))
ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]);
}
@@ -1338,25 +1337,14 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true);
- p = &dev->ports[dev->cpu_port];
- p->on = 1;
-
ksz8_port_setup(dev, dev->cpu_port, true);
for (i = 0; i < dev->phy_port_cnt; i++) {
- p = &dev->ports[i];
-
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
-
- /* Last port may be disabled. */
- if (i == dev->phy_port_cnt)
- break;
- p->on = 1;
}
for (i = 0; i < dev->phy_port_cnt; i++) {
p = &dev->ports[i];
- if (!p->on)
- continue;
+
if (!ksz_is_ksz88x3(dev)) {
ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
if (remote & KSZ8_PORT_FIBER_MODE)
@@ -1425,14 +1413,14 @@ int ksz8_setup(struct dsa_switch *ds)
ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true);
/* Enable aggressive back off algorithm in half duplex mode. */
- regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_1,
SW_AGGR_BACKOFF, SW_AGGR_BACKOFF);
/*
* Make sure unicast VLAN boundary is set as default and
* enable no excessive collision drop.
*/
- regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_2,
UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP,
UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP);
diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
index 3698112138b7..fd6e2e69a42a 100644
--- a/drivers/net/dsa/microchip/ksz8863_smi.c
+++ b/drivers/net/dsa/microchip/ksz8863_smi.c
@@ -104,6 +104,7 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
},
{
.name = "#16",
@@ -113,6 +114,7 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
},
{
.name = "#32",
@@ -122,11 +124,14 @@ static const struct regmap_config ksz8863_regmap_config[] = {
.cache_type = REGCACHE_NONE,
.lock = ksz_regmap_lock,
.unlock = ksz_regmap_unlock,
+ .max_register = U8_MAX,
}
};
static int ksz8863_smi_probe(struct mdio_device *mdiodev)
{
+ struct device *ddev = &mdiodev->dev;
+ const struct ksz_chip_data *chip;
struct regmap_config rc;
struct ksz_device *dev;
int ret;
@@ -136,9 +141,15 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev)
if (!dev)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
+ chip = device_get_match_data(ddev);
+ if (!chip)
+ return -EINVAL;
+
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz8863_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
+ rc.wr_table = chip->wr_table;
+ rc.rd_table = chip->rd_table;
dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
&regmap_smi[i], dev,
&rc);
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index bf13d47c26cf..83b7f2d5c1ea 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -21,25 +21,25 @@
static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bool set)
{
- regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
{
- regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
+ regmap_update_bits(ksz_regmap_32(dev), addr, bits, set ? bits : 0);
}
static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
u32 bits, bool set)
{
- regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
+ regmap_update_bits(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -52,7 +52,7 @@ int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
- return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2,
+ return regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2,
REG_SW_MTU_MASK, frame_size);
}
@@ -60,7 +60,7 @@ static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL,
+ return regmap_read_poll_timeout(ksz_regmap_8(dev), REG_SW_VLAN_CTRL,
val, !(val & VLAN_START), 10, 1000);
}
@@ -147,7 +147,7 @@ static int ksz9477_wait_alu_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4,
+ return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_CTRL__4,
val, !(val & ALU_START), 10, 1000);
}
@@ -155,7 +155,7 @@ static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev)
{
unsigned int val;
- return regmap_read_poll_timeout(dev->regmap[2],
+ return regmap_read_poll_timeout(ksz_regmap_32(dev),
REG_SW_ALU_STAT_CTRL__4,
val, !(val & ALU_STAT_START),
10, 1000);
@@ -170,7 +170,7 @@ int ksz9477_reset_switch(struct ksz_device *dev)
ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
/* turn off SPI DO Edge select */
- regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_GLOBAL_SERIAL_CTRL_0,
SPI_AUTO_EDGE_DETECTION, 0);
/* default configuration */
@@ -213,7 +213,7 @@ void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
data |= (addr << MIB_COUNTER_INDEX_S);
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
- ret = regmap_read_poll_timeout(dev->regmap[2],
+ ret = regmap_read_poll_timeout(ksz_regmap_32(dev),
PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4),
val, !(val & MIB_COUNTER_READ), 10, 1000);
/* failed to read MIB. get out of loop */
@@ -329,11 +329,27 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{
+ u32 mask, val32;
+
/* No real PHY after this. */
if (!dev->info->internal_phy[addr])
return 0;
- return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
+ if (reg < 0x10)
+ return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
+
+ /* Errata: When using SPI, I2C, or in-band register access,
+ * writes to certain PHY registers should be performed as
+ * 32-bit writes instead of 16-bit writes.
+ */
+ val32 = val;
+ mask = 0xffff;
+ if ((reg & 1) == 0) {
+ val32 <<= 16;
+ mask <<= 16;
+ }
+ reg &= ~1;
+ return ksz_prmw32(dev, addr, 0x100 + (reg << 1), mask, val32);
}
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member)
@@ -346,7 +362,7 @@ void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
const u16 *regs = dev->info->regs;
u8 data;
- regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2,
+ regmap_update_bits(ksz_regmap_8(dev), REG_SW_LUE_CTRL_2,
SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
@@ -889,62 +905,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
return interface;
}
-static void ksz9477_port_mmd_write(struct ksz_device *dev, int port,
- u8 dev_addr, u16 reg_addr, u16 val)
-{
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
- MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr));
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr);
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
- MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr));
- ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
-}
-
-static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
-{
- /* Apply PHY settings to address errata listed in
- * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
- * Silicon Errata and Data Sheet Clarification documents:
- *
- * Register settings are needed to improve PHY receive performance
- */
- ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
- ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
- ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
-
- /* Transmit waveform amplitude can be improved
- * (1000BASE-T, 100BASE-TX, 10BASE-Te)
- */
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
-
- /* Energy Efficient Ethernet (EEE) feature select must
- * be manually disabled (except on KSZ8565 which is 100Mbit)
- */
- if (dev->info->gbit_capable[port])
- ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
-
- /* Register settings are required to meet data sheet
- * supply current specifications
- */
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
- ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
-}
-
void ksz9477_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config)
{
@@ -1029,20 +989,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable 802.1p priority */
ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
- if (dev->info->internal_phy[port]) {
- /* do not force flow control */
- ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
- PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
- false);
-
- if (dev->info->phy_errata_9477)
- ksz9477_phy_errata_setup(dev, port);
- } else {
- /* force flow control */
- ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
- PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
- true);
- }
+ /* force flow control for non-PHY ports only */
+ ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
+ PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
+ !dev->info->internal_phy[port]);
if (cpu_port)
member = dsa_user_ports(ds);
@@ -1165,7 +1115,7 @@ int ksz9477_setup(struct dsa_switch *ds)
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true);
/* Now we can configure default MTU value */
- ret = regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, REG_SW_MTU_MASK,
+ ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK,
VLAN_ETH_FRAME_LEN + ETH_FCS_LEN);
if (ret)
return ret;
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index 97a317263a2f..2710afad4f3a 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -24,7 +24,7 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c)
if (!dev)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) {
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = ksz9477_regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
dev->regmap[i] = devm_regmap_init_i2c(i2c, &rc);
@@ -119,7 +119,7 @@ static struct i2c_driver ksz9477_i2c_driver = {
.name = "ksz9477-switch",
.of_match_table = ksz9477_dt_ids,
},
- .probe_new = ksz9477_i2c_probe,
+ .probe = ksz9477_i2c_probe,
.remove = ksz9477_i2c_remove,
.shutdown = ksz9477_i2c_shutdown,
.id_table = ksz9477_i2c_id,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index a4428be5f483..d9d843efd111 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -331,13 +331,13 @@ static const u32 ksz8795_masks[] = {
[STATIC_MAC_TABLE_VALID] = BIT(21),
[STATIC_MAC_TABLE_USE_FID] = BIT(23),
[STATIC_MAC_TABLE_FID] = GENMASK(30, 24),
- [STATIC_MAC_TABLE_OVERRIDE] = BIT(26),
- [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20),
+ [STATIC_MAC_TABLE_OVERRIDE] = BIT(22),
+ [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16),
[DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0),
- [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8),
+ [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7),
[DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
[DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29),
- [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20),
+ [DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16),
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
[P_MII_TX_FLOW_CTRL] = BIT(5),
@@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x1030, 0x1030),
regmap_reg_range(0x1100, 0x1115),
regmap_reg_range(0x111a, 0x111f),
- regmap_reg_range(0x1122, 0x1127),
- regmap_reg_range(0x112a, 0x112b),
- regmap_reg_range(0x1136, 0x1139),
- regmap_reg_range(0x113e, 0x113f),
+ regmap_reg_range(0x1120, 0x112b),
+ regmap_reg_range(0x1134, 0x113b),
+ regmap_reg_range(0x113c, 0x113f),
regmap_reg_range(0x1400, 0x1401),
regmap_reg_range(0x1403, 0x1403),
regmap_reg_range(0x1410, 0x1417),
@@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x2030, 0x2030),
regmap_reg_range(0x2100, 0x2115),
regmap_reg_range(0x211a, 0x211f),
- regmap_reg_range(0x2122, 0x2127),
- regmap_reg_range(0x212a, 0x212b),
- regmap_reg_range(0x2136, 0x2139),
- regmap_reg_range(0x213e, 0x213f),
+ regmap_reg_range(0x2120, 0x212b),
+ regmap_reg_range(0x2134, 0x213b),
+ regmap_reg_range(0x213c, 0x213f),
regmap_reg_range(0x2400, 0x2401),
regmap_reg_range(0x2403, 0x2403),
regmap_reg_range(0x2410, 0x2417),
@@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x3030, 0x3030),
regmap_reg_range(0x3100, 0x3115),
regmap_reg_range(0x311a, 0x311f),
- regmap_reg_range(0x3122, 0x3127),
- regmap_reg_range(0x312a, 0x312b),
- regmap_reg_range(0x3136, 0x3139),
- regmap_reg_range(0x313e, 0x313f),
+ regmap_reg_range(0x3120, 0x312b),
+ regmap_reg_range(0x3134, 0x313b),
+ regmap_reg_range(0x313c, 0x313f),
regmap_reg_range(0x3400, 0x3401),
regmap_reg_range(0x3403, 0x3403),
regmap_reg_range(0x3410, 0x3417),
@@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x4030, 0x4030),
regmap_reg_range(0x4100, 0x4115),
regmap_reg_range(0x411a, 0x411f),
- regmap_reg_range(0x4122, 0x4127),
- regmap_reg_range(0x412a, 0x412b),
- regmap_reg_range(0x4136, 0x4139),
- regmap_reg_range(0x413e, 0x413f),
+ regmap_reg_range(0x4120, 0x412b),
+ regmap_reg_range(0x4134, 0x413b),
+ regmap_reg_range(0x413c, 0x413f),
regmap_reg_range(0x4400, 0x4401),
regmap_reg_range(0x4403, 0x4403),
regmap_reg_range(0x4410, 0x4417),
@@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x5030, 0x5030),
regmap_reg_range(0x5100, 0x5115),
regmap_reg_range(0x511a, 0x511f),
- regmap_reg_range(0x5122, 0x5127),
- regmap_reg_range(0x512a, 0x512b),
- regmap_reg_range(0x5136, 0x5139),
- regmap_reg_range(0x513e, 0x513f),
+ regmap_reg_range(0x5120, 0x512b),
+ regmap_reg_range(0x5134, 0x513b),
+ regmap_reg_range(0x513c, 0x513f),
regmap_reg_range(0x5400, 0x5401),
regmap_reg_range(0x5403, 0x5403),
regmap_reg_range(0x5410, 0x5417),
@@ -1075,6 +1070,45 @@ static const struct regmap_access_table ksz9896_register_set = {
.n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs),
};
+static const struct regmap_range ksz8873_valid_regs[] = {
+ regmap_reg_range(0x00, 0x01),
+ /* global control register */
+ regmap_reg_range(0x02, 0x0f),
+
+ /* port registers */
+ regmap_reg_range(0x10, 0x1d),
+ regmap_reg_range(0x1e, 0x1f),
+ regmap_reg_range(0x20, 0x2d),
+ regmap_reg_range(0x2e, 0x2f),
+ regmap_reg_range(0x30, 0x39),
+ regmap_reg_range(0x3f, 0x3f),
+
+ /* advanced control registers */
+ regmap_reg_range(0x60, 0x6f),
+ regmap_reg_range(0x70, 0x75),
+ regmap_reg_range(0x76, 0x78),
+ regmap_reg_range(0x79, 0x7a),
+ regmap_reg_range(0x7b, 0x83),
+ regmap_reg_range(0x8e, 0x99),
+ regmap_reg_range(0x9a, 0xa5),
+ regmap_reg_range(0xa6, 0xa6),
+ regmap_reg_range(0xa7, 0xaa),
+ regmap_reg_range(0xab, 0xae),
+ regmap_reg_range(0xaf, 0xba),
+ regmap_reg_range(0xbb, 0xbc),
+ regmap_reg_range(0xbd, 0xbd),
+ regmap_reg_range(0xc0, 0xc0),
+ regmap_reg_range(0xc2, 0xc2),
+ regmap_reg_range(0xc3, 0xc3),
+ regmap_reg_range(0xc4, 0xc4),
+ regmap_reg_range(0xc6, 0xc6),
+};
+
+static const struct regmap_access_table ksz8873_register_set = {
+ .yes_ranges = ksz8873_valid_regs,
+ .n_yes_ranges = ARRAY_SIZE(ksz8873_valid_regs),
+};
+
const struct ksz_chip_data ksz_switch_chips[] = {
[KSZ8563] = {
.chip_id = KSZ8563_CHIP_ID,
@@ -1214,6 +1248,8 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_mii = {false, false, true},
.supports_rmii = {false, false, true},
.internal_phy = {true, true, false},
+ .wr_table = &ksz8873_register_set,
+ .rd_table = &ksz8873_register_set,
},
[KSZ9477] = {
@@ -1229,7 +1265,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.tc_ets_supported = true,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1262,7 +1297,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1295,7 +1329,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2,
.num_tx_queues = 4,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -1382,7 +1415,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true,
.tc_ets_supported = true,
.ops = &ksz9477_dev_ops,
- .phy_errata_9477 = true,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
@@ -2095,7 +2127,7 @@ static int ksz_setup(struct dsa_switch *ds)
}
/* set broadcast storm protection 10% rate */
- regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL],
+ regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL],
BROADCAST_STORM_RATE,
(BROADCAST_STORM_VALUE *
BROADCAST_STORM_PROT_RATE) / 100);
@@ -2106,7 +2138,7 @@ static int ksz_setup(struct dsa_switch *ds)
ds->num_tx_queues = dev->info->num_tx_queues;
- regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL],
+ regmap_update_bits(ksz_regmap_8(dev), regs[S_MULTICAST_CTRL],
MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE);
ksz_init_mib_timer(dev);
@@ -2156,7 +2188,7 @@ static int ksz_setup(struct dsa_switch *ds)
}
/* start switch */
- regmap_update_bits(dev->regmap[0], regs[S_START_CTRL],
+ regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL],
SW_START, SW_START);
return 0;
@@ -2305,13 +2337,27 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
- if (dev->chip_id == KSZ8830_CHIP_ID) {
+ switch (dev->chip_id) {
+ case KSZ8830_CHIP_ID:
/* Silicon Errata Sheet (DS80000830A):
* Port 1 does not work with LinkMD Cable-Testing.
* Port 1 does not respond to received PAUSE control frames.
*/
if (!port)
return MICREL_KSZ8_P1_ERRATA;
+ break;
+ case KSZ9477_CHIP_ID:
+ /* KSZ9477 Errata DS80000754C
+ *
+ * Module 4: Energy Efficient Ethernet (EEE) feature select must
+ * be manually disabled
+ * The EEE feature is enabled by default, but it is not fully
+ * operational. It must be manually disabled through register
+ * controls. If not disabled, the PHY ports can auto-negotiate
+ * to enable EEE, and this feature can cause link drops when
+ * linked to another device supporting EEE.
+ */
+ return MICREL_NO_EEE;
}
return 0;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 8abecaf6089e..a4de58847dea 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -22,6 +22,13 @@
struct ksz_device;
struct ksz_port;
+enum ksz_regmap_width {
+ KSZ_REGMAP_8,
+ KSZ_REGMAP_16,
+ KSZ_REGMAP_32,
+ __KSZ_NUM_REGMAPS,
+};
+
struct vlan_table {
u32 table[3];
};
@@ -53,7 +60,6 @@ struct ksz_chip_data {
bool tc_cbs_supported;
bool tc_ets_supported;
const struct ksz_dev_ops *ops;
- bool phy_errata_9477;
bool ksz87xx_eee_link_erratum;
const struct ksz_mib_names *mib_names;
int mib_cnt;
@@ -101,7 +107,6 @@ struct ksz_port {
int stp_state;
struct phy_device phydev;
- u32 on:1; /* port is not disabled by hardware */
u32 fiber:1; /* port is fiber */
u32 force:1;
u32 read:1; /* read MIB counters in background */
@@ -137,7 +142,7 @@ struct ksz_device {
const struct ksz_dev_ops *dev_ops;
struct device *dev;
- struct regmap *regmap[3];
+ struct regmap *regmap[__KSZ_NUM_REGMAPS];
void *priv;
int irq;
@@ -377,11 +382,25 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit);
extern const struct ksz_chip_data ksz_switch_chips[];
/* Common register access functions */
+static inline struct regmap *ksz_regmap_8(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_8];
+}
+
+static inline struct regmap *ksz_regmap_16(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_16];
+}
+
+static inline struct regmap *ksz_regmap_32(struct ksz_device *dev)
+{
+ return dev->regmap[KSZ_REGMAP_32];
+}
static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[0], reg, &value);
+ int ret = regmap_read(ksz_regmap_8(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg,
@@ -394,7 +413,7 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[1], reg, &value);
+ int ret = regmap_read(ksz_regmap_16(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg,
@@ -407,7 +426,7 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
{
unsigned int value;
- int ret = regmap_read(dev->regmap[2], reg, &value);
+ int ret = regmap_read(ksz_regmap_32(dev), reg, &value);
if (ret)
dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg,
@@ -422,7 +441,7 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
u32 value[2];
int ret;
- ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
+ ret = regmap_bulk_read(ksz_regmap_32(dev), reg, value, 2);
if (ret)
dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -436,7 +455,7 @@ static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{
int ret;
- ret = regmap_write(dev->regmap[0], reg, value);
+ ret = regmap_write(ksz_regmap_8(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -448,7 +467,7 @@ static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{
int ret;
- ret = regmap_write(dev->regmap[1], reg, value);
+ ret = regmap_write(ksz_regmap_16(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -460,7 +479,7 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{
int ret;
- ret = regmap_write(dev->regmap[2], reg, value);
+ ret = regmap_write(ksz_regmap_32(dev), reg, value);
if (ret)
dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
@@ -473,7 +492,7 @@ static inline int ksz_rmw16(struct ksz_device *dev, u32 reg, u16 mask,
{
int ret;
- ret = regmap_update_bits(dev->regmap[1], reg, mask, value);
+ ret = regmap_update_bits(ksz_regmap_16(dev), reg, mask, value);
if (ret)
dev_err(dev->dev, "can't rmw 16bit reg 0x%x: %pe\n", reg,
ERR_PTR(ret));
@@ -486,7 +505,7 @@ static inline int ksz_rmw32(struct ksz_device *dev, u32 reg, u32 mask,
{
int ret;
- ret = regmap_update_bits(dev->regmap[2], reg, mask, value);
+ ret = regmap_update_bits(ksz_regmap_32(dev), reg, mask, value);
if (ret)
dev_err(dev->dev, "can't rmw 32bit reg 0x%x: %pe\n", reg,
ERR_PTR(ret));
@@ -503,12 +522,19 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
val[0] = swab32(value & 0xffffffffULL);
val[1] = swab32(value >> 32ULL);
- return regmap_bulk_write(dev->regmap[2], reg, val, 2);
+ return regmap_bulk_write(ksz_regmap_32(dev), reg, val, 2);
}
static inline int ksz_rmw8(struct ksz_device *dev, int offset, u8 mask, u8 val)
{
- return regmap_update_bits(dev->regmap[0], offset, mask, val);
+ int ret;
+
+ ret = regmap_update_bits(ksz_regmap_8(dev), offset, mask, val);
+ if (ret)
+ dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n", offset,
+ ERR_PTR(ret));
+
+ return ret;
}
static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
@@ -549,12 +575,18 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
data);
}
-static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
- u8 mask, u8 val)
+static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset,
+ u8 mask, u8 val)
{
- regmap_update_bits(dev->regmap[0],
- dev->dev_ops->get_port_addr(port, offset),
- mask, val);
+ return ksz_rmw8(dev, dev->dev_ops->get_port_addr(port, offset),
+ mask, val);
+}
+
+static inline int ksz_prmw32(struct ksz_device *dev, int port, int offset,
+ u32 mask, u32 val)
+{
+ return ksz_rmw32(dev, dev->dev_ops->get_port_addr(port, offset),
+ mask, val);
}
static inline void ksz_regmap_lock(void *__mtx)
@@ -569,6 +601,13 @@ static inline void ksz_regmap_unlock(void *__mtx)
mutex_unlock(mtx);
}
+static inline bool ksz_is_ksz87xx(struct ksz_device *dev)
+{
+ return dev->chip_id == KSZ8795_CHIP_ID ||
+ dev->chip_id == KSZ8794_CHIP_ID ||
+ dev->chip_id == KSZ8765_CHIP_ID;
+}
+
static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
{
return dev->chip_id == KSZ8830_CHIP_ID;
@@ -709,9 +748,9 @@ static inline int is_lan937x(struct ksz_device *dev)
#define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \
static const struct regmap_config ksz##_regmap_config[] = { \
- KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
- KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
- KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_8] = KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_16] = KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
+ [KSZ_REGMAP_32] = KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
}
#endif
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c
index 96c52e8fb51b..279338451621 100644
--- a/drivers/net/dsa/microchip/ksz_spi.c
+++ b/drivers/net/dsa/microchip/ksz_spi.c
@@ -63,7 +63,7 @@ static int ksz_spi_probe(struct spi_device *spi)
else
regmap_config = ksz9477_regmap_config;
- for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
+ for (i = 0; i < __KSZ_NUM_REGMAPS; i++) {
rc = regmap_config[i];
rc.lock_arg = &dev->regmap_mutex;
rc.wr_table = chip->wr_table;
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 399a3905e6ca..b479a628b1ae 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -20,13 +20,13 @@
static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{
- return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
+ return regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0);
}
static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset,
u8 bits, bool set)
{
- return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+ return regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
bits, set ? bits : 0);
}
@@ -86,7 +86,7 @@ static int lan937x_internal_phy_write(struct ksz_device *dev, int addr, int reg,
if (ret < 0)
return ret;
- ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
+ ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2,
value, !(value & VPHY_IND_BUSY), 10,
1000);
if (ret < 0) {
@@ -116,7 +116,7 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
if (ret < 0)
return ret;
- ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2,
+ ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2,
value, !(value & VPHY_IND_BUSY), 10,
1000);
if (ret < 0) {
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 7e773c4ba046..b8bb9f3b3609 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1006,6 +1006,10 @@ mt753x_trap_frames(struct mt7530_priv *priv)
mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
MT753X_BPDU_CPU_ONLY);
+ /* Trap 802.1X PAE frames to the CPU port(s) */
+ mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_PORT_FW_MASK,
+ MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY));
+
/* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
@@ -3005,7 +3009,7 @@ static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -3033,6 +3037,7 @@ mt753x_setup(struct dsa_switch *ds)
/* Initialise the PCS devices */
for (i = 0; i < priv->ds->num_ports; i++) {
priv->pcs[i].pcs.ops = priv->info->pcs_ops;
+ priv->pcs[i].pcs.neg_mode = true;
priv->pcs[i].priv = priv;
priv->pcs[i].port = i;
}
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 08045b035e6a..17e42d30fff4 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -66,6 +66,8 @@ enum mt753x_id {
/* Registers for BPDU and PAE frame control*/
#define MT753X_BPC 0x24
#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
+#define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16)
+#define MT753X_PAE_PORT_FW(x) FIELD_PREP(MT753X_PAE_PORT_FW_MASK, x)
/* Register for :03 and :0E MAC DA frame control */
#define MT753X_RGAC2 0x2c
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 08a46ffd53af..7af2f08a62f1 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -109,6 +109,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
usleep_range(1000, 2000);
}
+ err = mv88e6xxx_read(chip, addr, reg, &data);
+ if (err)
+ return err;
+
+ if ((data & mask) == val)
+ return 0;
+
dev_err(chip->dev, "Timeout while waiting for switch\n");
return -ETIMEDOUT;
}
@@ -463,11 +470,11 @@ restore_link:
return err;
}
-static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
+static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)
{
- struct mv88e6xxx_chip *chip = ds->priv;
-
- return port < chip->info->num_internal_phys;
+ return port >= chip->info->internal_phys_offset &&
+ port < chip->info->num_internal_phys +
+ chip->info->internal_phys_offset;
}
static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
@@ -479,7 +486,7 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
* report whether the port is internal.
*/
if (chip->info->family == MV88E6XXX_FAMILY_6250)
- return port < chip->info->num_internal_phys;
+ return mv88e6xxx_phy_is_internal(chip, port);
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
if (err) {
@@ -584,7 +591,7 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
- if (mv88e6xxx_phy_is_internal(chip->ds, port)) {
+ if (mv88e6xxx_phy_is_internal(chip, port)) {
__set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
} else {
if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) &&
@@ -790,6 +797,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
unsigned long *supported = config->supported_interfaces;
bool is_6191x =
chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X;
+ bool is_6361 =
+ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361;
mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
@@ -804,13 +813,16 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
/* 6191X supports >1G modes only on port 10 */
if (!is_6191x || port == 10) {
__set_bit(PHY_INTERFACE_MODE_2500BASEX, supported);
- __set_bit(PHY_INTERFACE_MODE_5GBASER, supported);
- __set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
- /* FIXME: USXGMII is not supported yet */
- /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */
-
- config->mac_capabilities |= MAC_2500FD | MAC_5000FD |
- MAC_10000FD;
+ config->mac_capabilities |= MAC_2500FD;
+
+ /* 6361 only supports up to 2500BaseX */
+ if (!is_6361) {
+ __set_bit(PHY_INTERFACE_MODE_5GBASER, supported);
+ __set_bit(PHY_INTERFACE_MODE_10GBASER, supported);
+ __set_bit(PHY_INTERFACE_MODE_USXGMII, supported);
+ config->mac_capabilities |= MAC_5000FD |
+ MAC_10000FD;
+ }
}
}
@@ -832,7 +844,7 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
chip->info->ops->phylink_get_caps(chip, port, config);
mv88e6xxx_reg_unlock(chip);
- if (mv88e6xxx_phy_is_internal(ds, port)) {
+ if (mv88e6xxx_phy_is_internal(chip, port)) {
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
config->supported_interfaces);
/* Internal ports with no phy-mode need GMII for PHYLIB */
@@ -841,29 +853,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
}
}
+static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = 0;
+
+ /* In inband mode, the link may come up at any time while the link
+ * is not forced down. Force the link down while we reconfigure the
+ * interface mode.
+ */
+ if (mode == MLO_AN_INBAND &&
+ chip->ports[port].interface != interface &&
+ chip->info->ops->port_set_link) {
+ mv88e6xxx_reg_lock(chip);
+ err = chip->info->ops->port_set_link(chip, port,
+ LINK_FORCED_DOWN);
+ mv88e6xxx_reg_unlock(chip);
+ }
+
+ return err;
+}
+
static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
unsigned int mode,
const struct phylink_link_state *state)
{
struct mv88e6xxx_chip *chip = ds->priv;
- struct mv88e6xxx_port *p;
int err = 0;
- p = &chip->ports[port];
-
mv88e6xxx_reg_lock(chip);
- if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) {
- /* In inband mode, the link may come up at any time while the
- * link is not forced down. Force the link down while we
- * reconfigure the interface mode.
- */
- if (mode == MLO_AN_INBAND &&
- p->interface != state->interface &&
- chip->info->ops->port_set_link)
- chip->info->ops->port_set_link(chip, port,
- LINK_FORCED_DOWN);
-
+ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {
err = mv88e6xxx_port_config_interface(chip, port,
state->interface);
if (err && err != -EOPNOTSUPP)
@@ -880,24 +901,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
err = 0;
}
+err_unlock:
+ mv88e6xxx_reg_unlock(chip);
+
+ if (err && err != -EOPNOTSUPP)
+ dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
+}
+
+static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = 0;
+
/* Undo the forced down state above after completing configuration
* irrespective of its state on entry, which allows the link to come
* up in the in-band case where there is no separate SERDES. Also
* ensure that the link can come up if the PPU is in use and we are
* in PHY mode (we treat the PPU as an effective in-band mechanism.)
*/
+ mv88e6xxx_reg_lock(chip);
+
if (chip->info->ops->port_set_link &&
- ((mode == MLO_AN_INBAND && p->interface != state->interface) ||
+ ((mode == MLO_AN_INBAND &&
+ chip->ports[port].interface != interface) ||
(mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port))))
- chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
-
- p->interface = state->interface;
+ err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
-err_unlock:
mv88e6xxx_reg_unlock(chip);
- if (err && err != -EOPNOTSUPP)
- dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
+ chip->ports[port].interface = interface;
+
+ return err;
}
static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
@@ -2999,6 +3034,14 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
/* If there is a GPIO connected to the reset pin, toggle it */
if (gpiod) {
+ /* If the switch has just been reset and not yet completed
+ * loading EEPROM, the reset may interrupt the I2C transaction
+ * mid-byte, causing the first EEPROM read after the reset
+ * from the wrong location resulting in the switch booting
+ * to wrong mode and inoperable.
+ */
+ mv88e6xxx_g1_wait_eeprom_done(chip);
+
gpiod_set_value_cansleep(gpiod, 1);
usleep_range(10000, 20000);
gpiod_set_value_cansleep(gpiod, 0);
@@ -3311,7 +3354,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
caps = pl_config.mac_capabilities;
if (chip->info->ops->port_max_speed_mode)
- mode = chip->info->ops->port_max_speed_mode(port);
+ mode = chip->info->ops->port_max_speed_mode(chip, port);
else
mode = PHY_INTERFACE_MODE_NA;
@@ -5043,6 +5086,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6250_ptp_ops,
.phylink_get_caps = mv88e6250_phylink_get_caps,
+ .set_max_frame_size = mv88e6185_g1_set_max_frame_size,
};
static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -5642,6 +5686,46 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
};
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ [MV88E6020] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6020,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6020",
+ .num_databases = 64,
+ .num_ports = 4,
+ .num_internal_phys = 2,
+ .max_vid = 4095,
+ .port_base_addr = 0x8,
+ .phy_base_addr = 0x0,
+ .global1_addr = 0xf,
+ .global2_addr = 0x7,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .g2_irqs = 5,
+ .atu_move_port_mask = 0xf,
+ .dual_chip = true,
+ .ops = &mv88e6250_ops,
+ },
+
+ [MV88E6071] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6071,
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6071",
+ .num_databases = 64,
+ .num_ports = 7,
+ .num_internal_phys = 5,
+ .max_vid = 4095,
+ .port_base_addr = 0x08,
+ .phy_base_addr = 0x00,
+ .global1_addr = 0x0f,
+ .global2_addr = 0x07,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .g2_irqs = 5,
+ .atu_move_port_mask = 0xf,
+ .dual_chip = true,
+ .ops = &mv88e6250_ops,
+ },
+
[MV88E6085] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085,
.family = MV88E6XXX_FAMILY_6097,
@@ -6024,7 +6108,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6191X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6047,7 +6132,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6193X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6309,6 +6395,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ptp_support = true,
.ops = &mv88e6352_ops,
},
+ [MV88E6361] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361,
+ .family = MV88E6XXX_FAMILY_6393,
+ .name = "Marvell 88E6361",
+ .num_databases = 4096,
+ .num_macs = 16384,
+ .num_ports = 11,
+ /* Ports 1, 2 and 8 are not routed */
+ .invalid_port_mask = BIT(1) | BIT(2) | BIT(8),
+ .num_internal_phys = 5,
+ .internal_phys_offset = 3,
+ .max_vid = 4095,
+ .max_sid = 63,
+ .port_base_addr = 0x0,
+ .phy_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .global2_addr = 0x1c,
+ .age_time_coeff = 3750,
+ .g1_irqs = 10,
+ .g2_irqs = 14,
+ .atu_move_port_mask = 0x1f,
+ .pvt = true,
+ .multi_chip = true,
+ .ptp_support = true,
+ .ops = &mv88e6393x_ops,
+ },
[MV88E6390] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
.family = MV88E6XXX_FAMILY_6390,
@@ -6366,7 +6478,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.name = "Marvell 88E6393X",
.num_databases = 4096,
.num_ports = 11, /* 10 + Z80 */
- .num_internal_phys = 9,
+ .num_internal_phys = 8,
+ .internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -7002,7 +7115,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.port_teardown = mv88e6xxx_port_teardown,
.phylink_get_caps = mv88e6xxx_get_caps,
.phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
+ .phylink_mac_prepare = mv88e6xxx_mac_prepare,
.phylink_mac_config = mv88e6xxx_mac_config,
+ .phylink_mac_finish = mv88e6xxx_mac_finish,
.phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart,
.phylink_mac_link_down = mv88e6xxx_mac_link_down,
.phylink_mac_link_up = mv88e6xxx_mac_link_up,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index da6e1339f809..0ad34b2d8913 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -54,6 +54,8 @@ enum mv88e6xxx_frame_mode {
/* List of supported models */
enum mv88e6xxx_model {
+ MV88E6020,
+ MV88E6071,
MV88E6085,
MV88E6095,
MV88E6097,
@@ -82,6 +84,7 @@ enum mv88e6xxx_model {
MV88E6350,
MV88E6351,
MV88E6352,
+ MV88E6361,
MV88E6390,
MV88E6390X,
MV88E6393X,
@@ -94,13 +97,13 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
- MV88E6XXX_FAMILY_6250, /* 6220 6250 */
+ MV88E6XXX_FAMILY_6250, /* 6220 6250 6020 6071 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
- MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */
+ MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */
};
/**
@@ -167,6 +170,11 @@ struct mv88e6xxx_info {
/* Supports PTP */
bool ptp_support;
+
+ /* Internal PHY start index. 0 means that internal PHYs range starts at
+ * port 0, 1 means internal PHYs range starts at port 1, etc
+ */
+ unsigned int internal_phys_offset;
};
struct mv88e6xxx_atu_entry {
@@ -513,7 +521,8 @@ struct mv88e6xxx_ops {
int speed, int duplex);
/* What interface mode should be used for maximum speed? */
- phy_interface_t (*port_max_speed_mode)(int port);
+ phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip,
+ int port);
int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 615896893076..937a01f2ba75 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1196,9 +1196,12 @@ out:
int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
struct mii_bus *bus)
{
+ int phy_start = chip->info->internal_phys_offset;
+ int phy_end = chip->info->internal_phys_offset +
+ chip->info->num_internal_phys;
int phy, irq;
- for (phy = 0; phy < chip->info->num_internal_phys; phy++) {
+ for (phy = phy_start; phy < phy_end; phy++) {
irq = irq_find_mapping(chip->g2_irq.domain, phy);
if (irq < 0)
return irq;
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index f79cf716c541..dd66ec902d4c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6341_port_max_speed_mode(int port)
+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 5)
return PHY_INTERFACE_MODE_2500BASEX;
@@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6390_port_max_speed_mode(int port)
+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 9 || port == 10)
return PHY_INTERFACE_MODE_2500BASEX;
@@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
duplex);
}
-phy_interface_t mv88e6390x_port_max_speed_mode(int port)
+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
if (port == 9 || port == 10)
return PHY_INTERFACE_MODE_XAUI;
@@ -421,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
u16 reg, ctrl;
int err;
+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 &&
+ speed > 2500)
+ return -EOPNOTSUPP;
+
if (speed == 200 && port != 0)
return -EOPNOTSUPP;
@@ -500,12 +507,17 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
return 0;
}
-phy_interface_t mv88e6393x_port_max_speed_mode(int port)
+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port)
{
- if (port == 0 || port == 9 || port == 10)
- return PHY_INTERFACE_MODE_10GBASER;
- return PHY_INTERFACE_MODE_NA;
+ if (port != 0 && port != 9 && port != 10)
+ return PHY_INTERFACE_MODE_NA;
+
+ if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361)
+ return PHY_INTERFACE_MODE_2500BASEX;
+
+ return PHY_INTERFACE_MODE_10GBASER;
}
static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
@@ -554,6 +566,9 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
case PHY_INTERFACE_MODE_10GBASER:
cmode = MV88E6393X_PORT_STS_CMODE_10GBASER;
break;
+ case PHY_INTERFACE_MODE_USXGMII:
+ cmode = MV88E6393X_PORT_STS_CMODE_USXGMII;
+ break;
default:
cmode = 0;
}
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index d19b6303b91f..86deeb347cbc 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -111,6 +111,8 @@
/* Offset 0x03: Switch Identifier Register */
#define MV88E6XXX_PORT_SWITCH_ID 0x03
#define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK 0xfff0
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6020 0x0200
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6071 0x0710
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6085 0x04a0
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6095 0x0950
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6097 0x0990
@@ -133,6 +135,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
+#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
@@ -359,10 +362,14 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port,
int speed, int duplex);
-phy_interface_t mv88e6341_port_max_speed_mode(int port);
-phy_interface_t mv88e6390_port_max_speed_mode(int port);
-phy_interface_t mv88e6390x_port_max_speed_mode(int port);
-phy_interface_t mv88e6393x_port_max_speed_mode(int port);
+phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
+phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip,
+ int port);
int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state);
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
index 72faec8f44dc..80167d53212f 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.c
+++ b/drivers/net/dsa/mv88e6xxx/serdes.c
@@ -683,7 +683,8 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
- cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
+ cmode == MV88E6393X_PORT_STS_CMODE_10GBASER ||
+ cmode == MV88E6393X_PORT_STS_CMODE_USXGMII)
lane = port;
return lane;
@@ -984,7 +985,42 @@ static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
state->speed = SPEED_10000;
state->duplex = DUPLEX_FULL;
}
+ return 0;
+}
+
+/* USXGMII registers for Marvell switch 88e639x are undocumented and this function is based
+ * on some educated guesses. It appears that there are no status bits related to
+ * autonegotiation complete or flow control.
+ */
+static int mv88e639x_serdes_pcs_get_state_usxgmii(struct mv88e6xxx_chip *chip,
+ int port, int lane,
+ struct phylink_link_state *state)
+{
+ u16 status, lp_status;
+ int err;
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
+ MV88E6390_USXGMII_PHY_STATUS, &status);
+ if (err) {
+ dev_err(chip->dev, "can't read Serdes USXGMII PHY status: %d\n", err);
+ return err;
+ }
+ dev_dbg(chip->dev, "USXGMII PHY status: 0x%x\n", status);
+
+ state->link = !!(status & MDIO_USXGMII_LINK);
+ state->an_complete = state->link;
+
+ if (state->link) {
+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
+ MV88E6390_USXGMII_LP_STATUS, &lp_status);
+ if (err) {
+ dev_err(chip->dev, "can't read Serdes USXGMII LP status: %d\n", err);
+ return err;
+ }
+ dev_dbg(chip->dev, "USXGMII LP status: 0x%x\n", lp_status);
+ /* lp_status appears to include the "link" bit as per USXGMII spec. */
+ phylink_decode_usxgmii_word(state, lp_status);
+ }
return 0;
}
@@ -1020,6 +1056,9 @@ int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
case PHY_INTERFACE_MODE_10GBASER:
return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
state);
+ case PHY_INTERFACE_MODE_USXGMII:
+ return mv88e639x_serdes_pcs_get_state_usxgmii(chip, port, lane,
+ state);
default:
return -EOPNOTSUPP;
@@ -1173,6 +1212,7 @@ int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
}
@@ -1213,6 +1253,7 @@ irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
break;
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
if (err)
return err;
@@ -1477,7 +1518,8 @@ static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane,
* to SERDES operating in 10G mode. These registers only apply to 10G
* operation and have no effect on other speeds.
*/
- if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER)
+ if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER &&
+ cmode != MV88E6393X_PORT_STS_CMODE_USXGMII)
return 0;
for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
@@ -1582,6 +1624,7 @@ int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
break;
case MV88E6393X_PORT_STS_CMODE_5GBASER:
case MV88E6393X_PORT_STS_CMODE_10GBASER:
+ case MV88E6393X_PORT_STS_CMODE_USXGMII:
err = mv88e6390_serdes_power_10g(chip, lane, on);
break;
default:
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
index 29bb4e91e2f6..e245687ddb1d 100644
--- a/drivers/net/dsa/mv88e6xxx/serdes.h
+++ b/drivers/net/dsa/mv88e6xxx/serdes.h
@@ -48,6 +48,10 @@
#define MV88E6393X_10G_INT_LINK_CHANGE BIT(2)
#define MV88E6393X_10G_INT_STATUS 0x9001
+/* USXGMII */
+#define MV88E6390_USXGMII_LP_STATUS 0xf0a2
+#define MV88E6390_USXGMII_PHY_STATUS 0xf0a6
+
/* 1000BASE-X and SGMII */
#define MV88E6390_SGMII_BMCR (0x2000 + MII_BMCR)
#define MV88E6390_SGMII_BMSR (0x2000 + MII_BMSR)
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index 80861ac090ae..bef879c6d500 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -1286,7 +1286,6 @@ static int felix_parse_ports_node(struct felix *felix,
if (err < 0) {
dev_info(dev, "Unsupported PHY mode %s on port %d\n",
phy_modes(phy_mode), port);
- of_node_put(child);
/* Leave port_phy_modes[port] = 0, which is also
* PHY_INTERFACE_MODE_NA. This will perform a
@@ -1626,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds)
struct felix *felix = ocelot_to_felix(ocelot);
struct dsa_port *dp;
+ rtnl_lock();
if (felix->tag_proto_ops)
felix->tag_proto_ops->teardown(ds);
+ rtnl_unlock();
dsa_switch_for_each_available_port(dp, ds)
ocelot_deinit_port(ocelot, dp->index);
@@ -1725,6 +1726,18 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port,
u32 tstamp_hi;
u64 tstamp;
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_L2:
+ if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L2))
+ return false;
+ break;
+ case PTP_CLASS_IPV4:
+ case PTP_CLASS_IPV6:
+ if (!(ocelot->ports[port]->trap_proto & OCELOT_PROTO_PTP_L4))
+ return false;
+ break;
+ }
+
/* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb
* for RX timestamping. Then free it, and poll for its copy through
* MMIO in the CPU port module, and inject that into the stack from
@@ -1774,16 +1787,15 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
struct ocelot *ocelot = ds->priv;
struct ocelot_port *ocelot_port = ocelot->ports[port];
- struct felix *felix = ocelot_to_felix(ocelot);
ocelot_port_set_maxlen(ocelot, port, new_mtu);
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
- if (ocelot_port->taprio && felix->info->tas_guard_bands_update)
- felix->info->tas_guard_bands_update(ocelot, port);
+ if (ocelot_port->taprio && ocelot->ops->tas_guard_bands_update)
+ ocelot->ops->tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
}
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index 96008c046da5..1d4befe7cfe8 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -57,7 +57,6 @@ struct felix_info {
void (*mdio_bus_free)(struct ocelot *ocelot);
int (*port_setup_tc)(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data);
- void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
void (*port_sched_speed_set)(struct ocelot *ocelot, int port,
u32 speed);
void (*phylink_mac_config)(struct ocelot *ocelot, int port,
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index d172a3e9736c..f16daa9b1765 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -1021,7 +1021,6 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
for (port = 0; port < felix->info->num_ports; port++) {
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
if (dsa_is_unused_port(felix->ds, port))
continue;
@@ -1029,16 +1028,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- mdio_device = mdio_device_create(felix->imdio, port);
- if (IS_ERR(mdio_device))
+ phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port);
+ if (IS_ERR(phylink_pcs))
continue;
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- continue;
- }
-
felix->pcs[port] = phylink_pcs;
dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
@@ -1054,14 +1047,9 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
for (port = 0; port < ocelot->num_phys_ports; port++) {
struct phylink_pcs *phylink_pcs = felix->pcs[port];
- struct mdio_device *mdio_device;
-
- if (!phylink_pcs)
- continue;
- mdio_device = lynx_get_mdio_device(phylink_pcs);
- mdio_device_free(mdio_device);
- lynx_pcs_destroy(phylink_pcs);
+ if (phylink_pcs)
+ lynx_pcs_destroy(phylink_pcs);
}
mdiobus_unregister(felix->imdio);
mdiobus_free(felix->imdio);
@@ -1081,6 +1069,9 @@ static u64 vsc9959_tas_remaining_gate_len_ps(u64 gate_len_ns)
if (gate_len_ns == U64_MAX)
return U64_MAX;
+ if (gate_len_ns < VSC9959_TAS_MIN_GATE_LEN_NS)
+ return 0;
+
return (gate_len_ns - VSC9959_TAS_MIN_GATE_LEN_NS) * PSEC_PER_NSEC;
}
@@ -1221,15 +1212,17 @@ static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc)
static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct ocelot_mm_state *mm = &ocelot->mm[port];
struct tc_taprio_qopt_offload *taprio;
u64 min_gate_len[OCELOT_NUM_TC];
+ u32 val, maxlen, add_frag_size;
+ u64 needed_min_frag_time_ps;
int speed, picos_per_byte;
u64 needed_bit_time_ps;
- u32 val, maxlen;
u8 tas_speed;
int tc;
- lockdep_assert_held(&ocelot->tas_lock);
+ lockdep_assert_held(&ocelot->fwd_domain_lock);
taprio = ocelot_port->taprio;
@@ -1265,14 +1258,21 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
*/
needed_bit_time_ps = (u64)(maxlen + 24) * picos_per_byte;
+ /* Preemptible TCs don't need to pass a full MTU, the port will
+ * automatically emit a HOLD request when a preemptible TC gate closes
+ */
+ val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port);
+ add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val);
+ needed_min_frag_time_ps = picos_per_byte *
+ (u64)(24 + 2 * ethtool_mm_frag_size_add_to_min(add_frag_size));
+
dev_dbg(ocelot->dev,
- "port %d: max frame size %d needs %llu ps at speed %d\n",
- port, maxlen, needed_bit_time_ps, speed);
+ "port %d: max frame size %d needs %llu ps, %llu ps for mPackets at speed %d\n",
+ port, maxlen, needed_bit_time_ps, needed_min_frag_time_ps,
+ speed);
vsc9959_tas_min_gate_lengths(taprio, min_gate_len);
- mutex_lock(&ocelot->fwd_domain_lock);
-
for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);
u64 remaining_gate_len_ps;
@@ -1281,7 +1281,9 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
remaining_gate_len_ps =
vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]);
- if (remaining_gate_len_ps > needed_bit_time_ps) {
+ if ((mm->active_preemptible_tcs & BIT(tc)) ?
+ remaining_gate_len_ps > needed_min_frag_time_ps :
+ remaining_gate_len_ps > needed_bit_time_ps) {
/* Setting QMAXSDU_CFG to 0 disables oversized frame
* dropping.
*/
@@ -1335,8 +1337,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);
ocelot->ops->cut_through_fwd(ocelot);
-
- mutex_unlock(&ocelot->fwd_domain_lock);
}
static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
@@ -1363,7 +1363,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
break;
}
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
ocelot_rmw_rix(ocelot,
QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
@@ -1373,7 +1373,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
if (ocelot_port->taprio)
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
}
static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
@@ -1421,9 +1421,9 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
int ret, i;
u32 val;
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
- if (!taprio->enable) {
+ if (taprio->cmd == TAPRIO_CMD_DESTROY) {
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port);
@@ -1433,8 +1433,11 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
+ } else if (taprio->cmd != TAPRIO_CMD_REPLACE) {
+ ret = -EOPNOTSUPP;
+ goto err_unlock;
}
ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
@@ -1513,7 +1516,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
ocelot_port->taprio = taprio_offload_get(taprio);
vsc9959_tas_guard_bands_update(ocelot, port);
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return 0;
@@ -1521,7 +1524,7 @@ err_reset_tc:
taprio->mqprio.qopt.num_tc = 0;
ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
err_unlock:
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
return ret;
}
@@ -1534,7 +1537,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
int port;
u32 val;
- mutex_lock(&ocelot->tas_lock);
+ mutex_lock(&ocelot->fwd_domain_lock);
for (port = 0; port < ocelot->num_phys_ports; port++) {
ocelot_port = ocelot->ports[port];
@@ -1572,7 +1575,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port);
}
- mutex_unlock(&ocelot->tas_lock);
+ mutex_unlock(&ocelot->fwd_domain_lock);
}
static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
@@ -1643,6 +1646,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
}
}
+static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port,
+ struct tc_mqprio_qopt_offload *mqprio)
+{
+ int ret;
+
+ mutex_lock(&ocelot->fwd_domain_lock);
+ ret = ocelot_port_mqprio(ocelot, port, mqprio);
+ mutex_unlock(&ocelot->fwd_domain_lock);
+
+ return ret;
+}
+
static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type,
void *type_data)
@@ -1655,7 +1670,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data);
case TC_SETUP_QDISC_MQPRIO:
- return ocelot_port_mqprio(ocelot, port, type_data);
+ return vsc9959_qos_port_mqprio(ocelot, port, type_data);
case TC_SETUP_QDISC_CBS:
return vsc9959_qos_port_cbs_set(ds, port, type_data);
default:
@@ -2600,6 +2615,7 @@ static const struct ocelot_ops vsc9959_ops = {
.cut_through_fwd = vsc9959_cut_through_fwd,
.tas_clock_adjust = vsc9959_tas_clock_adjust,
.update_stats = vsc9959_update_stats,
+ .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
};
static const struct felix_info felix_info_vsc9959 = {
@@ -2625,7 +2641,6 @@ static const struct felix_info felix_info_vsc9959 = {
.port_modes = vsc9959_port_modes,
.port_setup_tc = vsc9959_port_setup_tc,
.port_sched_speed_set = vsc9959_sched_speed_set,
- .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
};
/* The INTB interrupt is shared between for PTP TX timestamp availability
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
index 96d4972a62f0..15003b2af264 100644
--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
+++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
@@ -912,7 +912,6 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
for (port = 0; port < felix->info->num_ports; port++) {
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
int addr = port + 4;
if (dsa_is_unused_port(felix->ds, port))
@@ -921,16 +920,10 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL)
continue;
- mdio_device = mdio_device_create(felix->imdio, addr);
- if (IS_ERR(mdio_device))
+ phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, addr);
+ if (IS_ERR(phylink_pcs))
continue;
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- continue;
- }
-
felix->pcs[port] = phylink_pcs;
dev_info(dev, "Found PCS at internal MDIO address %d\n", addr);
@@ -946,14 +939,9 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
for (port = 0; port < ocelot->num_phys_ports; port++) {
struct phylink_pcs *phylink_pcs = felix->pcs[port];
- struct mdio_device *mdio_device;
-
- if (!phylink_pcs)
- continue;
- mdio_device = lynx_get_mdio_device(phylink_pcs);
- mdio_device_free(mdio_device);
- lynx_pcs_destroy(phylink_pcs);
+ if (phylink_pcs)
+ lynx_pcs_destroy(phylink_pcs);
}
/* mdiobus_unregister and mdiobus_free handled by devres */
diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index e7b98b864fa1..3b0937031499 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -391,7 +391,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
u32 port_mask, port_ctrl, val;
int ret;
@@ -439,7 +439,7 @@ error:
static int ar9331_sw_setup(struct dsa_switch *ds)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret, i;
@@ -484,7 +484,7 @@ error:
static void ar9331_sw_port_disable(struct dsa_switch *ds, int port)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret;
@@ -527,7 +527,7 @@ static void ar9331_sw_phylink_mac_config(struct dsa_switch *ds, int port,
unsigned int mode,
const struct phylink_link_state *state)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct regmap *regmap = priv->regmap;
int ret;
@@ -542,7 +542,7 @@ static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port,
unsigned int mode,
phy_interface_t interface)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
struct regmap *regmap = priv->regmap;
int ret;
@@ -562,7 +562,7 @@ static void ar9331_sw_phylink_mac_link_up(struct dsa_switch *ds, int port,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
struct regmap *regmap = priv->regmap;
u32 val;
@@ -665,7 +665,7 @@ static void ar9331_do_stats_poll(struct work_struct *work)
static void ar9331_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *s)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
spin_lock(&p->stats_lock);
@@ -676,7 +676,7 @@ static void ar9331_get_stats64(struct dsa_switch *ds, int port,
static void ar9331_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
- struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+ struct ar9331_sw_priv *priv = ds->priv;
struct ar9331_sw_port *p = &priv->port[port];
spin_lock(&p->stats_lock);
@@ -1002,6 +1002,8 @@ static const struct regmap_config ar9331_mdio_regmap_config = {
.val_bits = 32,
.reg_stride = 4,
.max_register = AR9331_SW_REG_PAGE,
+ .use_single_read = true,
+ .use_single_write = true,
.ranges = ar9331_regmap_range,
.num_ranges = ARRAY_SIZE(ar9331_regmap_range),
@@ -1018,8 +1020,6 @@ static struct regmap_bus ar9331_sw_bus = {
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
.read = ar9331_mdio_read,
.write = ar9331_sw_bus_write,
- .max_raw_read = 4,
- .max_raw_write = 4,
};
static int ar9331_sw_probe(struct mdio_device *mdiodev)
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index 6d5ac7588a69..efe9380d4a15 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -576,8 +576,11 @@ static struct regmap_config qca8k_regmap_config = {
.rd_table = &qca8k_readable_table,
.disable_locking = true, /* Locking is handled by qca8k read/write */
.cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
- .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
- .max_raw_write = 32,
+ .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */
+ /* ATU regs suffer from a bug where some data are not correctly
+ * written. Disable bulk write to correctly write ATU entry.
+ */
+ .use_single_write = true,
};
static int
@@ -588,6 +591,9 @@ qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data,
bool ack;
int ret;
+ if (!skb)
+ return -ENOMEM;
+
reinit_completion(&mgmt_eth_data->rw_done);
/* Increment seq_num and set it in the copy pkt */
@@ -1493,7 +1499,7 @@ static void qca8k_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -1520,14 +1526,12 @@ static int qca8k_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
}
/* Enable/disable SerDes auto-negotiation as necessary */
- ret = qca8k_read(priv, QCA8K_REG_PWS, &val);
+ val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ?
+ 0 : QCA8K_PWS_SERDES_AEN_DIS;
+
+ ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8K_PWS_SERDES_AEN_DIS, val);
if (ret)
return ret;
- if (phylink_autoneg_inband(mode))
- val &= ~QCA8K_PWS_SERDES_AEN_DIS;
- else
- val |= QCA8K_PWS_SERDES_AEN_DIS;
- qca8k_write(priv, QCA8K_REG_PWS, val);
/* Configure the SGMII parameters */
ret = qca8k_read(priv, QCA8K_REG_SGMII_CTRL, &val);
@@ -1598,6 +1602,7 @@ static void qca8k_setup_pcs(struct qca8k_priv *priv, struct qca8k_pcs *qpcs,
int port)
{
qpcs->pcs.ops = &qca8k_pcs_ops;
+ qpcs->pcs.neg_mode = true;
/* We don't have interrupts for link changes, so we need to poll */
qpcs->pcs.poll = true;
@@ -1756,7 +1761,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds,
static int
qca8k_setup(struct dsa_switch *ds)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
int cpu_port, ret, i;
u32 mask;
diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c
index 96773e432558..13b8452ce5b2 100644
--- a/drivers/net/dsa/qca/qca8k-common.c
+++ b/drivers/net/dsa/qca/qca8k-common.c
@@ -244,7 +244,7 @@ void qca8k_fdb_flush(struct qca8k_priv *priv)
}
static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
- const u8 *mac, u16 vid)
+ const u8 *mac, u16 vid, u8 aging)
{
struct qca8k_fdb fdb = { 0 };
int ret;
@@ -261,10 +261,12 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
goto exit;
/* Rule exist. Delete first */
- if (!fdb.aging) {
+ if (fdb.aging) {
ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
if (ret)
goto exit;
+ } else {
+ fdb.aging = aging;
}
/* Add port to fdb portmask */
@@ -291,6 +293,10 @@ static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
if (ret < 0)
goto exit;
+ ret = qca8k_fdb_read(priv, &fdb);
+ if (ret < 0)
+ goto exit;
+
/* Rule doesn't exist. Why delete? */
if (!fdb.aging) {
ret = -EINVAL;
@@ -760,7 +766,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
u16 port_mask = BIT(port);
return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
@@ -770,7 +776,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
struct dsa_db db)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
u16 port_mask = BIT(port);
if (!vid)
@@ -782,7 +788,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port,
int qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{
- struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+ struct qca8k_priv *priv = ds->priv;
struct qca8k_fdb _fdb = { 0 };
int cnt = QCA8K_NUM_FDB_RECORDS;
bool is_static;
@@ -810,7 +816,11 @@ int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
const u8 *addr = mdb->addr;
u16 vid = mdb->vid;
- return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
+ if (!vid)
+ vid = QCA8K_PORT_VID_DEF;
+
+ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
+ QCA8K_ATU_STATUS_STATIC);
}
int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
@@ -821,6 +831,9 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
const u8 *addr = mdb->addr;
u16 vid = mdb->vid;
+ if (!vid)
+ vid = QCA8K_PORT_VID_DEF;
+
return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
}
diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
index b883692b7d86..1261e0bb21ef 100644
--- a/drivers/net/dsa/qca/qca8k-leds.c
+++ b/drivers/net/dsa/qca/qca8k-leds.c
@@ -5,6 +5,18 @@
#include "qca8k.h"
#include "qca8k_leds.h"
+static u32 qca8k_phy_to_port(int phy)
+{
+ /* Internal PHY 0 has port at index 1.
+ * Internal PHY 1 has port at index 2.
+ * Internal PHY 2 has port at index 3.
+ * Internal PHY 3 has port at index 4.
+ * Internal PHY 4 has port at index 5.
+ */
+
+ return phy + 1;
+}
+
static int
qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
{
@@ -32,6 +44,53 @@ qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en
}
static int
+qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
+{
+ reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
+
+ /* 6 total control rule:
+ * 3 control rules for phy0-3 that applies to all their leds
+ * 3 control rules for phy4
+ */
+ if (port_num == 4)
+ reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
+ else
+ reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
+
+ return 0;
+}
+
+static int
+qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
+{
+ /* Parsing specific to netdev trigger */
+ if (test_bit(TRIGGER_NETDEV_TX, &rules))
+ *offload_trigger |= QCA8K_LED_TX_BLINK_MASK;
+ if (test_bit(TRIGGER_NETDEV_RX, &rules))
+ *offload_trigger |= QCA8K_LED_RX_BLINK_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_10M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_100M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules))
+ *offload_trigger |= QCA8K_LED_LINK_1000M_EN_MASK;
+ if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules))
+ *offload_trigger |= QCA8K_LED_HALF_DUPLEX_MASK;
+ if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules))
+ *offload_trigger |= QCA8K_LED_FULL_DUPLEX_MASK;
+
+ if (rules && !*offload_trigger)
+ return -EOPNOTSUPP;
+
+ /* Enable some default rule by default to the requested mode:
+ * - Blink at 4Hz by default
+ */
+ *offload_trigger |= QCA8K_LED_BLINK_4HZ;
+
+ return 0;
+}
+
+static int
qca8k_led_brightness_set(struct qca8k_led *led,
enum led_brightness brightness)
{
@@ -165,6 +224,143 @@ qca8k_cled_blink_set(struct led_classdev *ldev,
}
static int
+qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 mask, val = QCA8K_LED_ALWAYS_OFF;
+
+ qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+
+ if (enable)
+ val = QCA8K_LED_RULE_CONTROLLED;
+
+ if (led->port_num == 0 || led->port_num == 4) {
+ mask = QCA8K_LED_PATTERN_EN_MASK;
+ val <<= QCA8K_LED_PATTERN_EN_SHIFT;
+ } else {
+ mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
+ }
+
+ return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
+ val << reg_info.shift);
+}
+
+static bool
+qca8k_cled_hw_control_status(struct led_classdev *ldev)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 val;
+
+ qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+
+ regmap_read(priv->regmap, reg_info.reg, &val);
+
+ val >>= reg_info.shift;
+
+ if (led->port_num == 0 || led->port_num == 4) {
+ val &= QCA8K_LED_PATTERN_EN_MASK;
+ val >>= QCA8K_LED_PATTERN_EN_SHIFT;
+ } else {
+ val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
+ }
+
+ return val == QCA8K_LED_RULE_CONTROLLED;
+}
+
+static int
+qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
+{
+ u32 offload_trigger = 0;
+
+ return qca8k_parse_netdev(rules, &offload_trigger);
+}
+
+static int
+qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 offload_trigger = 0;
+ int ret;
+
+ ret = qca8k_parse_netdev(rules, &offload_trigger);
+ if (ret)
+ return ret;
+
+ ret = qca8k_cled_trigger_offload(ldev, true);
+ if (ret)
+ return ret;
+
+ qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+
+ return regmap_update_bits(priv->regmap, reg_info.reg,
+ QCA8K_LED_RULE_MASK << reg_info.shift,
+ offload_trigger << reg_info.shift);
+}
+
+static int
+qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_led_pattern_en reg_info;
+ struct qca8k_priv *priv = led->priv;
+ u32 val;
+ int ret;
+
+ /* With hw control not active return err */
+ if (!qca8k_cled_hw_control_status(ldev))
+ return -EINVAL;
+
+ qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
+
+ ret = regmap_read(priv->regmap, reg_info.reg, &val);
+ if (ret)
+ return ret;
+
+ val >>= reg_info.shift;
+ val &= QCA8K_LED_RULE_MASK;
+
+ /* Parsing specific to netdev trigger */
+ if (val & QCA8K_LED_TX_BLINK_MASK)
+ set_bit(TRIGGER_NETDEV_TX, rules);
+ if (val & QCA8K_LED_RX_BLINK_MASK)
+ set_bit(TRIGGER_NETDEV_RX, rules);
+ if (val & QCA8K_LED_LINK_10M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_10, rules);
+ if (val & QCA8K_LED_LINK_100M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_100, rules);
+ if (val & QCA8K_LED_LINK_1000M_EN_MASK)
+ set_bit(TRIGGER_NETDEV_LINK_1000, rules);
+ if (val & QCA8K_LED_HALF_DUPLEX_MASK)
+ set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules);
+ if (val & QCA8K_LED_FULL_DUPLEX_MASK)
+ set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules);
+
+ return 0;
+}
+
+static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev)
+{
+ struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+ struct qca8k_priv *priv = led->priv;
+ struct dsa_port *dp;
+
+ dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num));
+ if (!dp)
+ return NULL;
+ if (dp->slave)
+ return &dp->slave->dev;
+ return NULL;
+}
+
+static int
qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
{
struct fwnode_handle *led = NULL, *leds = NULL;
@@ -224,6 +420,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p
port_led->cdev.max_brightness = 1;
port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
port_led->cdev.blink_set = qca8k_cled_blink_set;
+ port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported;
+ port_led->cdev.hw_control_set = qca8k_cled_hw_control_set;
+ port_led->cdev.hw_control_get = qca8k_cled_hw_control_get;
+ port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device;
+ port_led->cdev.hw_control_trigger = "netdev";
init_data.default_label = ":port";
init_data.fwnode = led;
init_data.devname_mandatory = true;
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index fb1549a5fe32..8c66d3bf61f0 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -132,6 +132,8 @@ struct sja1105_info {
int max_frame_mem;
int num_ports;
bool multiple_cascade_ports;
+ /* Every {port, TXQ} has its own CBS shaper */
+ bool fixed_cbs_mapping;
enum dsa_tag_protocol tag_proto;
const struct sja1105_dynamic_table_ops *dyn_ops;
const struct sja1105_table_ops *static_ops;
@@ -252,6 +254,7 @@ struct sja1105_private {
unsigned long ucast_egress_floods;
unsigned long bcast_egress_floods;
unsigned long hwts_tx_en;
+ unsigned long hwts_rx_en;
const struct sja1105_info *info;
size_t max_xfer_len;
struct spi_device *spidev;
@@ -263,6 +266,8 @@ struct sja1105_private {
* the switch doesn't confuse them with one another.
*/
struct mutex mgmt_lock;
+ /* Serializes accesses to the FDB */
+ struct mutex fdb_lock;
/* PTP two-step TX timestamp ID, and its serialization lock */
spinlock_t ts_id_lock;
u8 ts_id;
@@ -289,7 +294,6 @@ struct sja1105_spi_message {
/* From sja1105_main.c */
enum sja1105_reset_reason {
SJA1105_VLAN_FILTERING = 0,
- SJA1105_RX_HWTSTAMPING,
SJA1105_AGEING_TIME,
SJA1105_SCHEDULING,
SJA1105_BEST_EFFORT_POLICING,
diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
index 7729d3f8b7f5..984c0e604e8d 100644
--- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
+++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c
@@ -1175,18 +1175,15 @@ const struct sja1105_dynamic_table_ops sja1110_dyn_ops[BLK_IDX_MAX_DYN] = {
static int
sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
- struct sja1105_dyn_cmd *cmd,
- const struct sja1105_dynamic_table_ops *ops)
+ const struct sja1105_dynamic_table_ops *ops,
+ void *entry, bool check_valident,
+ bool check_errors)
{
u8 packed_buf[SJA1105_MAX_DYN_CMD_SIZE] = {};
+ struct sja1105_dyn_cmd cmd = {};
int rc;
- /* We don't _need_ to read the full entry, just the command area which
- * is a fixed SJA1105_SIZE_DYN_CMD. But our cmd_packing() API expects a
- * buffer that contains the full entry too. Additionally, our API
- * doesn't really know how many bytes into the buffer does the command
- * area really begin. So just read back the whole entry.
- */
+ /* Read back the whole entry + command structure. */
rc = sja1105_xfer_buf(priv, SPI_READ, ops->addr, packed_buf,
ops->packed_size);
if (rc)
@@ -1195,11 +1192,25 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
/* Unpack the command structure, and return it to the caller in case it
* needs to perform further checks on it (VALIDENT).
*/
- memset(cmd, 0, sizeof(*cmd));
- ops->cmd_packing(packed_buf, cmd, UNPACK);
+ ops->cmd_packing(packed_buf, &cmd, UNPACK);
/* Hardware hasn't cleared VALID => still working on it */
- return cmd->valid ? -EAGAIN : 0;
+ if (cmd.valid)
+ return -EAGAIN;
+
+ if (check_valident && !cmd.valident && !(ops->access & OP_VALID_ANYWAY))
+ return -ENOENT;
+
+ if (check_errors && cmd.errors)
+ return -EINVAL;
+
+ /* Don't dereference possibly NULL pointer - maybe caller
+ * only wanted to see whether the entry existed or not.
+ */
+ if (entry)
+ ops->entry_packing(packed_buf, entry, UNPACK);
+
+ return 0;
}
/* Poll the dynamic config entry's control area until the hardware has
@@ -1208,16 +1219,19 @@ sja1105_dynamic_config_poll_valid(struct sja1105_private *priv,
*/
static int
sja1105_dynamic_config_wait_complete(struct sja1105_private *priv,
- struct sja1105_dyn_cmd *cmd,
- const struct sja1105_dynamic_table_ops *ops)
+ const struct sja1105_dynamic_table_ops *ops,
+ void *entry, bool check_valident,
+ bool check_errors)
{
- int rc;
-
- return read_poll_timeout(sja1105_dynamic_config_poll_valid,
- rc, rc != -EAGAIN,
- SJA1105_DYNAMIC_CONFIG_SLEEP_US,
- SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
- false, priv, cmd, ops);
+ int err, rc;
+
+ err = read_poll_timeout(sja1105_dynamic_config_poll_valid,
+ rc, rc != -EAGAIN,
+ SJA1105_DYNAMIC_CONFIG_SLEEP_US,
+ SJA1105_DYNAMIC_CONFIG_TIMEOUT_US,
+ false, priv, ops, entry, check_valident,
+ check_errors);
+ return err < 0 ? err : rc;
}
/* Provides read access to the settings through the dynamic interface
@@ -1286,25 +1300,14 @@ int sja1105_dynamic_config_read(struct sja1105_private *priv,
mutex_lock(&priv->dynamic_config_lock);
rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
ops->packed_size);
- if (rc < 0) {
- mutex_unlock(&priv->dynamic_config_lock);
- return rc;
- }
-
- rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
- mutex_unlock(&priv->dynamic_config_lock);
if (rc < 0)
- return rc;
+ goto out;
- if (!cmd.valident && !(ops->access & OP_VALID_ANYWAY))
- return -ENOENT;
+ rc = sja1105_dynamic_config_wait_complete(priv, ops, entry, true, false);
+out:
+ mutex_unlock(&priv->dynamic_config_lock);
- /* Don't dereference possibly NULL pointer - maybe caller
- * only wanted to see whether the entry existed or not.
- */
- if (entry)
- ops->entry_packing(packed_buf, entry, UNPACK);
- return 0;
+ return rc;
}
int sja1105_dynamic_config_write(struct sja1105_private *priv,
@@ -1356,22 +1359,14 @@ int sja1105_dynamic_config_write(struct sja1105_private *priv,
mutex_lock(&priv->dynamic_config_lock);
rc = sja1105_xfer_buf(priv, SPI_WRITE, ops->addr, packed_buf,
ops->packed_size);
- if (rc < 0) {
- mutex_unlock(&priv->dynamic_config_lock);
- return rc;
- }
-
- rc = sja1105_dynamic_config_wait_complete(priv, &cmd, ops);
- mutex_unlock(&priv->dynamic_config_lock);
if (rc < 0)
- return rc;
+ goto out;
- cmd = (struct sja1105_dyn_cmd) {0};
- ops->cmd_packing(packed_buf, &cmd, UNPACK);
- if (cmd.errors)
- return -EINVAL;
+ rc = sja1105_dynamic_config_wait_complete(priv, ops, NULL, false, true);
+out:
+ mutex_unlock(&priv->dynamic_config_lock);
- return 0;
+ return rc;
}
static u8 sja1105_crc8_add(u8 crc, u8 byte, u8 poly)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 2b3671d34ea5..3cd51285b508 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -866,12 +866,12 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
.hostprio = 7,
.mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A,
.mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK,
- .incl_srcpt1 = false,
- .send_meta1 = false,
+ .incl_srcpt1 = true,
+ .send_meta1 = true,
.mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B,
.mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK,
- .incl_srcpt0 = false,
- .send_meta0 = false,
+ .incl_srcpt0 = true,
+ .send_meta0 = true,
/* Default to an invalid value */
.mirr_port = priv->ds->num_ports,
/* No TTEthernet */
@@ -1805,6 +1805,7 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
struct dsa_db db)
{
struct sja1105_private *priv = ds->priv;
+ int rc;
if (!vid) {
switch (db.type) {
@@ -1819,12 +1820,16 @@ static int sja1105_fdb_add(struct dsa_switch *ds, int port,
}
}
- return priv->info->fdb_add_cmd(ds, port, addr, vid);
+ mutex_lock(&priv->fdb_lock);
+ rc = priv->info->fdb_add_cmd(ds, port, addr, vid);
+ mutex_unlock(&priv->fdb_lock);
+
+ return rc;
}
-static int sja1105_fdb_del(struct dsa_switch *ds, int port,
- const unsigned char *addr, u16 vid,
- struct dsa_db db)
+static int __sja1105_fdb_del(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid,
+ struct dsa_db db)
{
struct sja1105_private *priv = ds->priv;
@@ -1844,6 +1849,20 @@ static int sja1105_fdb_del(struct dsa_switch *ds, int port,
return priv->info->fdb_del_cmd(ds, port, addr, vid);
}
+static int sja1105_fdb_del(struct dsa_switch *ds, int port,
+ const unsigned char *addr, u16 vid,
+ struct dsa_db db)
+{
+ struct sja1105_private *priv = ds->priv;
+ int rc;
+
+ mutex_lock(&priv->fdb_lock);
+ rc = __sja1105_fdb_del(ds, port, addr, vid, db);
+ mutex_unlock(&priv->fdb_lock);
+
+ return rc;
+}
+
static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{
@@ -1875,13 +1894,14 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
if (!(l2_lookup.destports & BIT(port)))
continue;
- /* We need to hide the FDB entry for unknown multicast */
- if (l2_lookup.macaddr == SJA1105_UNKNOWN_MULTICAST &&
- l2_lookup.mask_macaddr == SJA1105_UNKNOWN_MULTICAST)
- continue;
-
u64_to_ether_addr(l2_lookup.macaddr, macaddr);
+ /* Hardware FDB is shared for fdb and mdb, "bridge fdb show"
+ * only wants to see unicast
+ */
+ if (is_multicast_ether_addr(macaddr))
+ continue;
+
/* We need to hide the dsa_8021q VLANs from the user. */
if (vid_is_dsa_8021q(l2_lookup.vlanid))
l2_lookup.vlanid = 0;
@@ -1905,6 +1925,8 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
};
int i;
+ mutex_lock(&priv->fdb_lock);
+
for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
struct sja1105_l2_lookup_entry l2_lookup = {0};
u8 macaddr[ETH_ALEN];
@@ -1918,7 +1940,7 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
if (rc) {
dev_err(ds->dev, "Failed to read FDB: %pe\n",
ERR_PTR(rc));
- return;
+ break;
}
if (!(l2_lookup.destports & BIT(port)))
@@ -1930,14 +1952,16 @@ static void sja1105_fast_age(struct dsa_switch *ds, int port)
u64_to_ether_addr(l2_lookup.macaddr, macaddr);
- rc = sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
+ rc = __sja1105_fdb_del(ds, port, macaddr, l2_lookup.vlanid, db);
if (rc) {
dev_err(ds->dev,
"Failed to delete FDB entry %pM vid %lld: %pe\n",
macaddr, l2_lookup.vlanid, ERR_PTR(rc));
- return;
+ break;
}
}
+
+ mutex_unlock(&priv->fdb_lock);
}
static int sja1105_mdb_add(struct dsa_switch *ds, int port,
@@ -2122,11 +2146,36 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
}
#define BYTES_PER_KBIT (1000LL / 8)
+/* Port 0 (the uC port) does not have CBS shapers */
+#define SJA1110_FIXED_CBS(port, prio) ((((port) - 1) * SJA1105_NUM_TC) + (prio))
+
+static int sja1105_find_cbs_shaper(struct sja1105_private *priv,
+ int port, int prio)
+{
+ int i;
+
+ if (priv->info->fixed_cbs_mapping) {
+ i = SJA1110_FIXED_CBS(port, prio);
+ if (i >= 0 && i < priv->info->num_cbs_shapers)
+ return i;
+
+ return -1;
+ }
+
+ for (i = 0; i < priv->info->num_cbs_shapers; i++)
+ if (priv->cbs[i].port == port && priv->cbs[i].prio == prio)
+ return i;
+
+ return -1;
+}
static int sja1105_find_unused_cbs_shaper(struct sja1105_private *priv)
{
int i;
+ if (priv->info->fixed_cbs_mapping)
+ return -1;
+
for (i = 0; i < priv->info->num_cbs_shapers; i++)
if (!priv->cbs[i].idle_slope && !priv->cbs[i].send_slope)
return i;
@@ -2157,14 +2206,20 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
{
struct sja1105_private *priv = ds->priv;
struct sja1105_cbs_entry *cbs;
+ s64 port_transmit_rate_kbps;
int index;
if (!offload->enable)
return sja1105_delete_cbs_shaper(priv, port, offload->queue);
- index = sja1105_find_unused_cbs_shaper(priv);
- if (index < 0)
- return -ENOSPC;
+ /* The user may be replacing an existing shaper */
+ index = sja1105_find_cbs_shaper(priv, port, offload->queue);
+ if (index < 0) {
+ /* That isn't the case - see if we can allocate a new one */
+ index = sja1105_find_unused_cbs_shaper(priv);
+ if (index < 0)
+ return -ENOSPC;
+ }
cbs = &priv->cbs[index];
cbs->port = port;
@@ -2174,9 +2229,17 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
*/
cbs->credit_hi = offload->hicredit;
cbs->credit_lo = abs(offload->locredit);
- /* User space is in kbits/sec, hardware in bytes/sec */
- cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT;
- cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT);
+ /* User space is in kbits/sec, while the hardware in bytes/sec times
+ * link speed. Since the given offload->sendslope is good only for the
+ * current link speed anyway, and user space is likely to reprogram it
+ * when that changes, don't even bother to track the port's link speed,
+ * but deduce the port transmit rate from idleslope - sendslope.
+ */
+ port_transmit_rate_kbps = offload->idleslope - offload->sendslope;
+ cbs->idle_slope = div_s64(offload->idleslope * BYTES_PER_KBIT,
+ port_transmit_rate_kbps);
+ cbs->send_slope = div_s64(abs(offload->sendslope * BYTES_PER_KBIT),
+ port_transmit_rate_kbps);
/* Convert the negative values from 64-bit 2's complement
* to 32-bit 2's complement (for the case of 0x80000000 whose
* negative is still negative).
@@ -2215,7 +2278,6 @@ static int sja1105_reload_cbs(struct sja1105_private *priv)
static const char * const sja1105_reset_reasons[] = {
[SJA1105_VLAN_FILTERING] = "VLAN filtering",
- [SJA1105_RX_HWTSTAMPING] = "RX timestamping",
[SJA1105_AGEING_TIME] = "Ageing time",
[SJA1105_SCHEDULING] = "Time-aware scheduling",
[SJA1105_BEST_EFFORT_POLICING] = "Best-effort policing",
@@ -2242,6 +2304,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
int rc, i;
s64 now;
+ mutex_lock(&priv->fdb_lock);
mutex_lock(&priv->mgmt_lock);
mutex_lock(&priv->mgmt_lock);
@@ -2316,7 +2379,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
for (i = 0; i < ds->num_ports; i++) {
struct dw_xpcs *xpcs = priv->xpcs[i];
- unsigned int mode;
+ unsigned int neg_mode;
rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]);
if (rc < 0)
@@ -2326,17 +2389,15 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
continue;
if (bmcr[i] & BMCR_ANENABLE)
- mode = MLO_AN_INBAND;
- else if (priv->fixed_link[i])
- mode = MLO_AN_FIXED;
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
else
- mode = MLO_AN_PHY;
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
- rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode, NULL);
+ rc = xpcs_do_config(xpcs, priv->phy_mode[i], NULL, neg_mode);
if (rc < 0)
goto out;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_OUTBAND) {
int speed = SPEED_UNKNOWN;
if (priv->phy_mode[i] == PHY_INTERFACE_MODE_2500BASEX)
@@ -2348,7 +2409,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
else
speed = SPEED_10;
- xpcs_link_up(&xpcs->pcs, mode, priv->phy_mode[i],
+ xpcs_link_up(&xpcs->pcs, neg_mode, priv->phy_mode[i],
speed, DUPLEX_FULL);
}
}
@@ -2358,6 +2419,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
goto out;
out:
mutex_unlock(&priv->mgmt_lock);
+ mutex_unlock(&priv->fdb_lock);
return rc;
}
@@ -2409,11 +2471,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
general_params->tpid = tpid;
/* EtherType used to identify outer tagged (S-tag) VLAN traffic */
general_params->tpid2 = tpid2;
- /* When VLAN filtering is on, we need to at least be able to
- * decode management traffic through the "backup plan".
- */
- general_params->incl_srcpt1 = enabled;
- general_params->incl_srcpt0 = enabled;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_is_unused_port(ds, port))
@@ -2932,7 +2989,9 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
{
struct sja1105_l2_lookup_entry *l2_lookup;
struct sja1105_table *table;
- int match;
+ int match, rc;
+
+ mutex_lock(&priv->fdb_lock);
table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP];
l2_lookup = table->entries;
@@ -2945,7 +3004,8 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
if (match == table->entry_count) {
NL_SET_ERR_MSG_MOD(extack,
"Could not find FDB entry for unknown multicast");
- return -ENOSPC;
+ rc = -ENOSPC;
+ goto out;
}
if (flags.val & BR_MCAST_FLOOD)
@@ -2953,10 +3013,13 @@ static int sja1105_port_mcast_flood(struct sja1105_private *priv, int to,
else
l2_lookup[match].destports &= ~BIT(to);
- return sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
- l2_lookup[match].index,
- &l2_lookup[match],
- true);
+ rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
+ l2_lookup[match].index,
+ &l2_lookup[match], true);
+out:
+ mutex_unlock(&priv->fdb_lock);
+
+ return rc;
}
static int sja1105_port_pre_bridge_flags(struct dsa_switch *ds, int port,
@@ -3326,6 +3389,7 @@ static int sja1105_probe(struct spi_device *spi)
mutex_init(&priv->ptp_data.lock);
mutex_init(&priv->dynamic_config_lock);
mutex_init(&priv->mgmt_lock);
+ mutex_init(&priv->fdb_lock);
spin_lock_init(&priv->ts_id_lock);
rc = sja1105_parse_dt(priv);
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
index 01f1cb719042..833e55e4b961 100644
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
@@ -400,7 +400,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
}
for (port = 0; port < ds->num_ports; port++) {
- struct mdio_device *mdiodev;
struct dw_xpcs *xpcs;
if (dsa_is_unused_port(ds, port))
@@ -410,13 +409,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
continue;
- mdiodev = mdio_device_create(bus, port);
- if (IS_ERR(mdiodev)) {
- rc = PTR_ERR(mdiodev);
- goto out_pcs_free;
- }
-
- xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
+ xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]);
if (IS_ERR(xpcs)) {
rc = PTR_ERR(xpcs);
goto out_pcs_free;
@@ -434,7 +427,6 @@ out_pcs_free:
if (!priv->xpcs[port])
continue;
- mdio_device_free(priv->xpcs[port]->mdiodev);
xpcs_destroy(priv->xpcs[port]);
priv->xpcs[port] = NULL;
}
@@ -457,7 +449,6 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
if (!priv->xpcs[port])
continue;
- mdio_device_free(priv->xpcs[port]->mdiodev);
xpcs_destroy(priv->xpcs[port]);
priv->xpcs[port] = NULL;
}
diff --git a/drivers/net/dsa/sja1105/sja1105_ptp.c b/drivers/net/dsa/sja1105/sja1105_ptp.c
index 30fb2cc40164..a7d41e781398 100644
--- a/drivers/net/dsa/sja1105/sja1105_ptp.c
+++ b/drivers/net/dsa/sja1105/sja1105_ptp.c
@@ -58,35 +58,10 @@ enum sja1105_ptp_clk_mode {
#define ptp_data_to_sja1105(d) \
container_of((d), struct sja1105_private, ptp_data)
-/* Must be called only while the RX timestamping state of the tagger
- * is turned off
- */
-static int sja1105_change_rxtstamping(struct sja1105_private *priv,
- bool on)
-{
- struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
- struct sja1105_general_params_entry *general_params;
- struct sja1105_table *table;
-
- table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
- general_params = table->entries;
- general_params->send_meta1 = on;
- general_params->send_meta0 = on;
-
- ptp_cancel_worker_sync(ptp_data->clock);
- skb_queue_purge(&ptp_data->skb_txtstamp_queue);
- skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
-
- return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
-}
-
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct hwtstamp_config config;
- bool rx_on;
- int rc;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
@@ -104,26 +79,13 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
- rx_on = false;
+ priv->hwts_rx_en &= ~BIT(port);
break;
default:
- rx_on = true;
+ priv->hwts_rx_en |= BIT(port);
break;
}
- if (rx_on != tagger_data->rxtstamp_get_state(ds)) {
- tagger_data->rxtstamp_set_state(ds, false);
-
- rc = sja1105_change_rxtstamping(priv, rx_on);
- if (rc < 0) {
- dev_err(ds->dev,
- "Failed to change RX timestamping: %d\n", rc);
- return rc;
- }
- if (rx_on)
- tagger_data->rxtstamp_set_state(ds, true);
- }
-
if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
return -EFAULT;
return 0;
@@ -131,7 +93,6 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct hwtstamp_config config;
@@ -140,7 +101,7 @@ int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
config.tx_type = HWTSTAMP_TX_ON;
else
config.tx_type = HWTSTAMP_TX_OFF;
- if (tagger_data->rxtstamp_get_state(ds))
+ if (priv->hwts_rx_en & BIT(port))
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
else
config.rx_filter = HWTSTAMP_FILTER_NONE;
@@ -413,11 +374,10 @@ static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)
bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
- struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
struct sja1105_private *priv = ds->priv;
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
- if (!tagger_data->rxtstamp_get_state(ds))
+ if (!(priv->hwts_rx_en & BIT(port)))
return false;
/* We need to read the full PTP clock to reconstruct the Rx
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 5ce29c8057a4..834b5c1b4db0 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -781,6 +781,7 @@ const struct sja1105_info sja1110a_info = {
.tag_proto = DSA_TAG_PROTO_SJA1110,
.can_limit_mcast_flood = true,
.multiple_cascade_ports = true,
+ .fixed_cbs_mapping = true,
.ptp_ts_bits = 32,
.ptpegr_ts_bytes = 8,
.max_frame_mem = SJA1110_MAX_FRAME_MEMORY,
@@ -831,6 +832,7 @@ const struct sja1105_info sja1110b_info = {
.tag_proto = DSA_TAG_PROTO_SJA1110,
.can_limit_mcast_flood = true,
.multiple_cascade_ports = true,
+ .fixed_cbs_mapping = true,
.ptp_ts_bits = 32,
.ptpegr_ts_bytes = 8,
.max_frame_mem = SJA1110_MAX_FRAME_MEMORY,
@@ -881,6 +883,7 @@ const struct sja1105_info sja1110c_info = {
.tag_proto = DSA_TAG_PROTO_SJA1110,
.can_limit_mcast_flood = true,
.multiple_cascade_ports = true,
+ .fixed_cbs_mapping = true,
.ptp_ts_bits = 32,
.ptpegr_ts_bytes = 8,
.max_frame_mem = SJA1110_MAX_FRAME_MEMORY,
@@ -931,6 +934,7 @@ const struct sja1105_info sja1110d_info = {
.tag_proto = DSA_TAG_PROTO_SJA1110,
.can_limit_mcast_flood = true,
.multiple_cascade_ports = true,
+ .fixed_cbs_mapping = true,
.ptp_ts_bits = 32,
.ptpegr_ts_bytes = 8,
.max_frame_mem = SJA1110_MAX_FRAME_MEMORY,
diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c
index e6153848a950..d7818710bc02 100644
--- a/drivers/net/dsa/sja1105/sja1105_tas.c
+++ b/drivers/net/dsa/sja1105/sja1105_tas.c
@@ -516,10 +516,11 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
/* Can't change an already configured port (must delete qdisc first).
* Can't delete the qdisc from an unconfigured port.
*/
- if (!!tas_data->offload[port] == admin->enable)
+ if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) ||
+ (!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY))
return -EINVAL;
- if (!admin->enable) {
+ if (admin->cmd == TAPRIO_CMD_DESTROY) {
taprio_offload_free(tas_data->offload[port]);
tas_data->offload[port] = NULL;
@@ -528,6 +529,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
return rc;
return sja1105_static_config_reload(priv, SJA1105_SCHEDULING);
+ } else if (admin->cmd != TAPRIO_CMD_REPLACE) {
+ return -EOPNOTSUPP;
}
/* The cycle time extension is the amount of time the last cycle from
diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c
index ae55167ce0a6..ef1a4a7c47b2 100644
--- a/drivers/net/dsa/vitesse-vsc73xx-core.c
+++ b/drivers/net/dsa/vitesse-vsc73xx-core.c
@@ -1025,17 +1025,17 @@ static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
struct vsc73xx *vsc = ds->priv;
return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port,
- VSC73XX_MAXLEN, new_mtu);
+ VSC73XX_MAXLEN, new_mtu + ETH_HLEN + ETH_FCS_LEN);
}
/* According to application not "VSC7398 Jumbo Frames" setting
- * up the MTU to 9.6 KB does not affect the performance on standard
+ * up the frame size to 9.6 KB does not affect the performance on standard
* frames. It is clear from the application note that
* "9.6 kilobytes" == 9600 bytes.
*/
static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port)
{
- return 9600;
+ return 9600 - ETH_HLEN - ETH_FCS_LEN;
}
static const struct dsa_switch_ops vsc73xx_ds_ops = {
diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
index 14ff6887a225..c1179d7311f7 100644
--- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c
+++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
@@ -147,7 +147,7 @@ static struct i2c_driver xrs700x_i2c_driver = {
.name = "xrs700x-i2c",
.of_match_table = of_match_ptr(xrs700x_i2c_dt_ids),
},
- .probe_new = xrs700x_i2c_probe,
+ .probe = xrs700x_i2c_probe,
.remove = xrs700x_i2c_remove,
.shutdown = xrs700x_i2c_shutdown,
.id_table = xrs700x_i2c_id,
diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h
index e52264465998..f784a6e2ab0e 100644
--- a/drivers/net/ethernet/8390/8390.h
+++ b/drivers/net/ethernet/8390/8390.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-1.0+ */
+
/* Generic NS8390 register definitions. */
/* This file is part of Donald Becker's 8390 drivers, and is distributed
diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c
index 991ad953aa79..a09f383dd249 100644
--- a/drivers/net/ethernet/8390/apne.c
+++ b/drivers/net/ethernet/8390/apne.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
*
@@ -19,12 +20,6 @@
*
* ----------------------------------------------------------------------------
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ----------------------------------------------------------------------------
- *
*/
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 78f985885547..fea489af72fb 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-1.0+
+
/*======================================================================
A PCMCIA ethernet driver for Asix AX88190-based cards
@@ -17,9 +19,7 @@
Written 1992,1993 by Donald Becker.
Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may be used and
- distributed according to the terms of the GNU General Public License,
- incorporated herein by reference.
+ Director, National Security Agency.
Donald Becker may be reached at becker@scyld.com
======================================================================*/
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
index 1df7601af86a..24f49a8ff903 100644
--- a/drivers/net/ethernet/8390/hydra.c
+++ b/drivers/net/ethernet/8390/hydra.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/* New Hydra driver using generic 8390 core */
/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
-/* This file is subject to the terms and conditions of the GNU General */
-/* Public License. See the file COPYING in the main directory of the */
-/* Linux distribution for more details. */
-
/* Peter De Schrijver (p2@mind.be) */
/* Oldenburg 2000 */
diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
index e84021282edf..84aeb8054304 100644
--- a/drivers/net/ethernet/8390/lib8390.c
+++ b/drivers/net/ethernet/8390/lib8390.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-1.0+
+
/* 8390.c: A general NS8390 ethernet driver core for linux. */
/*
Written 1992-94 by Donald Becker.
@@ -5,9 +7,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 7fb819b9b89a..4a0a095a1a8a 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -1,11 +1,9 @@
+// SPDX-License-Identifier: GPL-1.0+
/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
Ethernet cards on Linux */
/* Based on the former daynaport.c driver, by Alan Cox. Some code
taken from or inspired by skeleton.c by Donald Becker, acenic.c by
- Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
-
- This software may be used and distributed according to the terms of
- the GNU Public License, incorporated herein by reference. */
+ Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker. */
/* 2000-02-28: support added for Dayna and Kinetics cards by
A.G.deWijn@phys.uu.nl */
diff --git a/drivers/net/ethernet/8390/mcf8390.c b/drivers/net/ethernet/8390/mcf8390.c
index 8a7918d33419..217838b28220 100644
--- a/drivers/net/ethernet/8390/mcf8390.c
+++ b/drivers/net/ethernet/8390/mcf8390.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Support for ColdFire CPU based boards using a NS8390 Ethernet device.
*
@@ -5,9 +6,6 @@
*
* (C) Copyright 2012, Greg Ungerer <gerg@uclinux.org>
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
*/
#include <linux/module.h>
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index bc9c81dc00fd..7d89ec1cf273 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
/*
Written 1992-94 by Donald Becker.
@@ -5,9 +6,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index 6a0a2039600a..2c6bd36d2f31 100644
--- a/drivers/net/ethernet/8390/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* A Linux device driver for PCI NE2000 clones.
*
* Authors and other copyright holders:
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index 0f07fe03da98..9bd5e991f1e5 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/*======================================================================
A PCMCIA ethernet driver for NS8390-based cards
@@ -17,9 +18,7 @@
Written 1992,1993 by Donald Becker.
Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may be used and
- distributed according to the terms of the GNU General Public License,
- incorporated herein by reference.
+ Director, National Security Agency.
Donald Becker may be reached at becker@scyld.com
Based also on Keith Moore's changes to Don Becker's code, for IBM
diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c
index 7465650c8078..22ca804b2e95 100644
--- a/drivers/net/ethernet/8390/smc-ultra.c
+++ b/drivers/net/ethernet/8390/smc-ultra.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
/*
This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
@@ -7,9 +8,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c
index bd89ca8a92df..265976e3b64a 100644
--- a/drivers/net/ethernet/8390/stnic.c
+++ b/drivers/net/ethernet/8390/stnic.c
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
* Copyright (C) 1999 kaz Kojima
*/
diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c
index 119021d41451..ffd639477dfc 100644
--- a/drivers/net/ethernet/8390/wd.c
+++ b/drivers/net/ethernet/8390/wd.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* wd.c: A WD80x3 ethernet driver for linux. */
/*
Written 1993-94 by Donald Becker.
@@ -5,9 +6,6 @@
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
index e8b4fe813a08..d70390e9d03d 100644
--- a/drivers/net/ethernet/8390/zorro8390.c
+++ b/drivers/net/ethernet/8390/zorro8390.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
*
@@ -9,12 +10,6 @@
*
* ---------------------------------------------------------------------------
*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ---------------------------------------------------------------------------
- *
* The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
* Ethernet Controllers.
*/
diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c
index f5c2d7a9abc1..ca66b747b7c5 100644
--- a/drivers/net/ethernet/adi/adin1110.c
+++ b/drivers/net/ethernet/adi/adin1110.c
@@ -739,7 +739,7 @@ static int adin1110_broadcasts_filter(struct adin1110_port_priv *port_priv,
u32 port_rules = 0;
u8 mask[ETH_ALEN];
- memset(mask, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(mask);
if (accept_broadcast && port_priv->state == BR_STATE_FORWARDING)
port_rules = adin1110_port_rules(port_priv, true, true);
@@ -760,7 +760,7 @@ static int adin1110_set_mac_address(struct net_device *netdev,
return -EADDRNOTAVAIL;
eth_hw_addr_set(netdev, dev_addr);
- memset(mask, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(mask);
mac_slot = (!port_priv->nr) ? ADIN_MAC_P1_ADDR_SLOT : ADIN_MAC_P2_ADDR_SLOT;
port_rules = adin1110_port_rules(port_priv, true, false);
@@ -1271,7 +1271,7 @@ static int adin1110_port_set_blocking_state(struct adin1110_port_priv *port_priv
goto out;
/* Allow only BPDUs to be passed to the CPU */
- memset(mask, 0xFF, ETH_ALEN);
+ eth_broadcast_addr(mask);
port_rules = adin1110_port_rules(port_priv, true, false);
ret = adin1110_write_mac_address(port_priv, mac_slot, mac,
mask, port_rules);
@@ -1385,8 +1385,8 @@ static int adin1110_fdb_add(struct adin1110_port_priv *port_priv,
return -ENOMEM;
other_port = priv->ports[!port_priv->nr];
- port_rules = adin1110_port_rules(port_priv, false, true);
- memset(mask, 0xFF, ETH_ALEN);
+ port_rules = adin1110_port_rules(other_port, false, true);
+ eth_broadcast_addr(mask);
return adin1110_write_mac_address(other_port, mac_nr, (u8 *)fdb->addr,
mask, port_rules);
diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig
index dd7fd41ccde5..17985319088c 100644
--- a/drivers/net/ethernet/altera/Kconfig
+++ b/drivers/net/ethernet/altera/Kconfig
@@ -4,7 +4,9 @@ config ALTERA_TSE
depends on HAS_DMA
select PHYLIB
select PHYLINK
- select PCS_ALTERA_TSE
+ select PCS_LYNX
+ select MDIO_REGMAP
+ select REGMAP_MMIO
help
This driver supports the Altera Triple-Speed (TSE) Ethernet MAC.
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index 66e3af73ec41..2e15800e5310 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -27,14 +27,16 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mii.h>
+#include <linux/mdio/mdio-regmap.h>
#include <linux/netdevice.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
-#include <linux/pcs-altera-tse.h>
+#include <linux/pcs-lynx.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/skbuff.h>
#include <asm/cacheflush.h>
@@ -1036,10 +1038,6 @@ static struct net_device_ops altera_tse_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
};
-static void alt_tse_mac_an_restart(struct phylink_config *config)
-{
-}
-
static void alt_tse_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -1096,7 +1094,6 @@ static struct phylink_pcs *alt_tse_select_pcs(struct phylink_config *config,
}
static const struct phylink_mac_ops alt_tse_phylink_ops = {
- .mac_an_restart = alt_tse_mac_an_restart,
.mac_config = alt_tse_mac_config,
.mac_link_down = alt_tse_mac_link_down,
.mac_link_up = alt_tse_mac_link_up,
@@ -1137,13 +1134,16 @@ static int request_and_map(struct platform_device *pdev, const char *name,
static int altera_tse_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id = NULL;
+ struct regmap_config pcs_regmap_cfg;
struct altera_tse_private *priv;
+ struct mdio_regmap_config mrc;
struct resource *control_port;
+ struct regmap *pcs_regmap;
struct resource *dma_res;
struct resource *pcs_res;
+ struct mii_bus *pcs_bus;
struct net_device *ndev;
void __iomem *descmap;
- int pcs_reg_width = 2;
int ret = -ENODEV;
ndev = alloc_etherdev(sizeof(struct altera_tse_private));
@@ -1255,18 +1255,41 @@ static int altera_tse_probe(struct platform_device *pdev)
if (ret)
goto err_free_netdev;
+ memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg));
+ memset(&mrc, 0, sizeof(mrc));
/* SGMII PCS address space. The location can vary depending on how the
* IP is integrated. We can have a resource dedicated to it at a specific
* address space, but if it's not the case, we fallback to the mdiophy0
* from the MAC's address space
*/
- ret = request_and_map(pdev, "pcs", &pcs_res,
- &priv->pcs_base);
+ ret = request_and_map(pdev, "pcs", &pcs_res, &priv->pcs_base);
if (ret) {
+ /* If we can't find a dedicated resource for the PCS, fallback
+ * to the internal PCS, that has a different address stride
+ */
priv->pcs_base = priv->mac_dev + tse_csroffs(mdio_phy0);
- pcs_reg_width = 4;
+ pcs_regmap_cfg.reg_bits = 32;
+ /* Values are MDIO-like values, on 16 bits */
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(2);
+ } else {
+ pcs_regmap_cfg.reg_bits = 16;
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1);
}
+ /* Create a regmap for the PCS so that it can be used by the PCS driver */
+ pcs_regmap = devm_regmap_init_mmio(&pdev->dev, priv->pcs_base,
+ &pcs_regmap_cfg);
+ if (IS_ERR(pcs_regmap)) {
+ ret = PTR_ERR(pcs_regmap);
+ goto err_free_netdev;
+ }
+ mrc.regmap = pcs_regmap;
+ mrc.parent = &pdev->dev;
+ mrc.valid_addr = 0x0;
+ mrc.autoscan = false;
+
/* Rx IRQ */
priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq");
if (priv->rx_irq == -ENXIO) {
@@ -1389,7 +1412,18 @@ static int altera_tse_probe(struct platform_device *pdev)
(unsigned long) control_port->start, priv->rx_irq,
priv->tx_irq);
- priv->pcs = alt_tse_pcs_create(ndev, priv->pcs_base, pcs_reg_width);
+ snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name);
+ pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc);
+ if (IS_ERR(pcs_bus)) {
+ ret = PTR_ERR(pcs_bus);
+ goto err_init_pcs;
+ }
+
+ priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ if (IS_ERR(priv->pcs)) {
+ ret = PTR_ERR(priv->pcs);
+ goto err_init_pcs;
+ }
priv->phylink_config.dev = &ndev->dev;
priv->phylink_config.type = PHYLINK_NETDEV;
@@ -1412,12 +1446,13 @@ static int altera_tse_probe(struct platform_device *pdev)
if (IS_ERR(priv->phylink)) {
dev_err(&pdev->dev, "failed to create phylink\n");
ret = PTR_ERR(priv->phylink);
- goto err_init_phy;
+ goto err_init_phylink;
}
return 0;
-
-err_init_phy:
+err_init_phylink:
+ lynx_pcs_destroy(priv->pcs);
+err_init_pcs:
unregister_netdev(ndev);
err_register_netdev:
netif_napi_del(&priv->napi);
@@ -1438,6 +1473,8 @@ static int altera_tse_remove(struct platform_device *pdev)
altera_tse_mdio_destroy(ndev);
unregister_netdev(ndev);
phylink_destroy(priv->phylink);
+ lynx_pcs_destroy(priv->pcs);
+
free_netdev(ndev);
return 0;
diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
index 466ad9470d1f..6de0d590be34 100644
--- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
+++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
@@ -869,7 +869,9 @@ struct ena_admin_host_info {
* 2 : interrupt_moderation
* 3 : rx_buf_mirroring
* 4 : rss_configurable_function_key
- * 31:5 : reserved
+ * 5 : reserved
+ * 6 : rx_page_reuse
+ * 31:7 : reserved
*/
u32 driver_supported_features;
};
@@ -1184,6 +1186,8 @@ struct ena_admin_ena_mmio_req_read_less_resp {
#define ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK BIT(3)
#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_SHIFT 4
#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK BIT(4)
+#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_SHIFT 6
+#define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK BIT(6)
/* aenq_common_desc */
#define ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK BIT(0)
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
index 451c3a1b6255..633b321d7fdd 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -35,6 +35,8 @@
#define ENA_REGS_ADMIN_INTR_MASK 1
+#define ENA_MAX_BACKOFF_DELAY_EXP 16U
+
#define ENA_MIN_ADMIN_POLL_US 100
#define ENA_MAX_ADMIN_POLL_US 5000
@@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue,
static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us)
{
+ exp = min_t(u32, exp, ENA_MAX_BACKOFF_DELAY_EXP);
delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us);
delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US);
usleep_range(delay_us, 2 * delay_us);
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index e6a6efaeb87c..d19593fae226 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -1023,7 +1023,7 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
int tailroom;
/* restore page offset value in case it has been changed by device */
- rx_info->page_offset = headroom;
+ rx_info->buf_offset = headroom;
/* if previous allocated page is not used */
if (unlikely(rx_info->page))
@@ -1040,6 +1040,8 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
rx_info->page = page;
+ rx_info->dma_addr = dma;
+ rx_info->page_offset = 0;
ena_buf = &rx_info->ena_buf;
ena_buf->paddr = dma + headroom;
ena_buf->len = ENA_PAGE_SIZE - headroom - tailroom;
@@ -1047,14 +1049,12 @@ static int ena_alloc_rx_buffer(struct ena_ring *rx_ring,
return 0;
}
-static void ena_unmap_rx_buff(struct ena_ring *rx_ring,
- struct ena_rx_buffer *rx_info)
+static void ena_unmap_rx_buff_attrs(struct ena_ring *rx_ring,
+ struct ena_rx_buffer *rx_info,
+ unsigned long attrs)
{
- struct ena_com_buf *ena_buf = &rx_info->ena_buf;
-
- dma_unmap_page(rx_ring->dev, ena_buf->paddr - rx_ring->rx_headroom,
- ENA_PAGE_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_unmap_page_attrs(rx_ring->dev, rx_info->dma_addr, ENA_PAGE_SIZE,
+ DMA_BIDIRECTIONAL, attrs);
}
static void ena_free_rx_page(struct ena_ring *rx_ring,
@@ -1068,7 +1068,7 @@ static void ena_free_rx_page(struct ena_ring *rx_ring,
return;
}
- ena_unmap_rx_buff(rx_ring, rx_info);
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info, 0);
__free_page(page);
rx_info->page = NULL;
@@ -1406,14 +1406,14 @@ static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget)
return tx_pkts;
}
-static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag)
+static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag, u16 len)
{
struct sk_buff *skb;
if (!first_frag)
- skb = napi_alloc_skb(rx_ring->napi, rx_ring->rx_copybreak);
+ skb = napi_alloc_skb(rx_ring->napi, len);
else
- skb = napi_build_skb(first_frag, ENA_PAGE_SIZE);
+ skb = napi_build_skb(first_frag, len);
if (unlikely(!skb)) {
ena_increase_stat(&rx_ring->rx_stats.skb_alloc_fail, 1,
@@ -1422,24 +1422,47 @@ static struct sk_buff *ena_alloc_skb(struct ena_ring *rx_ring, void *first_frag)
netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev,
"Failed to allocate skb. first_frag %s\n",
first_frag ? "provided" : "not provided");
- return NULL;
}
return skb;
}
+static bool ena_try_rx_buf_page_reuse(struct ena_rx_buffer *rx_info, u16 buf_len,
+ u16 len, int pkt_offset)
+{
+ struct ena_com_buf *ena_buf = &rx_info->ena_buf;
+
+ /* More than ENA_MIN_RX_BUF_SIZE left in the reused buffer
+ * for data + headroom + tailroom.
+ */
+ if (SKB_DATA_ALIGN(len + pkt_offset) + ENA_MIN_RX_BUF_SIZE <= ena_buf->len) {
+ page_ref_inc(rx_info->page);
+ rx_info->page_offset += buf_len;
+ ena_buf->paddr += buf_len;
+ ena_buf->len -= buf_len;
+ return true;
+ }
+
+ return false;
+}
+
static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
struct ena_com_rx_buf_info *ena_bufs,
u32 descs,
u16 *next_to_clean)
{
+ int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ bool is_xdp_loaded = ena_xdp_present_ring(rx_ring);
struct ena_rx_buffer *rx_info;
struct ena_adapter *adapter;
+ int page_offset, pkt_offset;
+ dma_addr_t pre_reuse_paddr;
u16 len, req_id, buf = 0;
+ bool reuse_rx_buf_page;
struct sk_buff *skb;
- void *page_addr;
- u32 page_offset;
- void *data_addr;
+ void *buf_addr;
+ int buf_offset;
+ u16 buf_len;
len = ena_bufs[buf].len;
req_id = ena_bufs[buf].req_id;
@@ -1459,34 +1482,30 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
"rx_info %p page %p\n",
rx_info, rx_info->page);
- /* save virt address of first buffer */
- page_addr = page_address(rx_info->page);
+ buf_offset = rx_info->buf_offset;
+ pkt_offset = buf_offset - rx_ring->rx_headroom;
page_offset = rx_info->page_offset;
- data_addr = page_addr + page_offset;
-
- prefetch(data_addr);
+ buf_addr = page_address(rx_info->page) + page_offset;
if (len <= rx_ring->rx_copybreak) {
- skb = ena_alloc_skb(rx_ring, NULL);
+ skb = ena_alloc_skb(rx_ring, NULL, len);
if (unlikely(!skb))
return NULL;
- netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
- "RX allocated small packet. len %d. data_len %d\n",
- skb->len, skb->data_len);
-
/* sync this buffer for CPU use */
dma_sync_single_for_cpu(rx_ring->dev,
- dma_unmap_addr(&rx_info->ena_buf, paddr),
+ dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
len,
DMA_FROM_DEVICE);
- skb_copy_to_linear_data(skb, data_addr, len);
+ skb_copy_to_linear_data(skb, buf_addr + buf_offset, len);
dma_sync_single_for_device(rx_ring->dev,
- dma_unmap_addr(&rx_info->ena_buf, paddr),
+ dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
len,
DMA_FROM_DEVICE);
skb_put(skb, len);
+ netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
+ "RX allocated small packet. len %d.\n", skb->len);
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
rx_ring->free_ids[*next_to_clean] = req_id;
*next_to_clean = ENA_RX_RING_IDX_ADD(*next_to_clean, descs,
@@ -1494,14 +1513,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
return skb;
}
- ena_unmap_rx_buff(rx_ring, rx_info);
+ buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom);
+
+ pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr);
+
+ /* If XDP isn't loaded try to reuse part of the RX buffer */
+ reuse_rx_buf_page = !is_xdp_loaded &&
+ ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset);
- skb = ena_alloc_skb(rx_ring, page_addr);
+ dma_sync_single_for_cpu(rx_ring->dev,
+ pre_reuse_paddr + pkt_offset,
+ len,
+ DMA_FROM_DEVICE);
+
+ if (!reuse_rx_buf_page)
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info, DMA_ATTR_SKIP_CPU_SYNC);
+
+ skb = ena_alloc_skb(rx_ring, buf_addr, buf_len);
if (unlikely(!skb))
return NULL;
/* Populate skb's linear part */
- skb_reserve(skb, page_offset);
+ skb_reserve(skb, buf_offset);
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
@@ -1510,7 +1543,8 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
"RX skb updated. len %d. data_len %d\n",
skb->len, skb->data_len);
- rx_info->page = NULL;
+ if (!reuse_rx_buf_page)
+ rx_info->page = NULL;
rx_ring->free_ids[*next_to_clean] = req_id;
*next_to_clean =
@@ -1525,10 +1559,28 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
rx_info = &rx_ring->rx_buffer_info[req_id];
- ena_unmap_rx_buff(rx_ring, rx_info);
+ /* rx_info->buf_offset includes rx_ring->rx_headroom */
+ buf_offset = rx_info->buf_offset;
+ pkt_offset = buf_offset - rx_ring->rx_headroom;
+ buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom);
+ page_offset = rx_info->page_offset;
+
+ pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr);
+
+ reuse_rx_buf_page = !is_xdp_loaded &&
+ ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset);
+
+ dma_sync_single_for_cpu(rx_ring->dev,
+ pre_reuse_paddr + pkt_offset,
+ len,
+ DMA_FROM_DEVICE);
+
+ if (!reuse_rx_buf_page)
+ ena_unmap_rx_buff_attrs(rx_ring, rx_info,
+ DMA_ATTR_SKIP_CPU_SYNC);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page,
- rx_info->page_offset, len, ENA_PAGE_SIZE);
+ page_offset + buf_offset, len, buf_len);
} while (1);
@@ -1626,7 +1678,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
xdp_prepare_buff(xdp, page_address(rx_info->page),
- rx_info->page_offset,
+ rx_info->buf_offset,
rx_ring->ena_bufs[0].len, false);
/* If for some reason we received a bigger packet than
* we expect, then we simply drop it
@@ -1638,7 +1690,7 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
/* The xdp program might expand the headers */
if (ret == ENA_XDP_PASS) {
- rx_info->page_offset = xdp->data - xdp->data_hard_start;
+ rx_info->buf_offset = xdp->data - xdp->data_hard_start;
rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data;
}
@@ -1693,7 +1745,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
/* First descriptor might have an offset set by the device */
rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
- rx_info->page_offset += ena_rx_ctx.pkt_offset;
+ rx_info->buf_offset += ena_rx_ctx.pkt_offset;
netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
"rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
@@ -1723,8 +1775,9 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
* from RX side.
*/
if (xdp_verdict & ENA_XDP_FORWARDED) {
- ena_unmap_rx_buff(rx_ring,
- &rx_ring->rx_buffer_info[req_id]);
+ ena_unmap_rx_buff_attrs(rx_ring,
+ &rx_ring->rx_buffer_info[req_id],
+ 0);
rx_ring->rx_buffer_info[req_id].page = NULL;
}
}
@@ -3233,7 +3286,8 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd
ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK |
ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK |
ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK |
- ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK;
+ ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK |
+ ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK;
rc = ena_com_set_host_attributes(ena_dev);
if (rc) {
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h
index 5a0d4ee76172..248b715b4d68 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.h
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h
@@ -51,6 +51,8 @@
#define ENA_DEFAULT_RING_SIZE (1024)
#define ENA_MIN_RING_SIZE (256)
+#define ENA_MIN_RX_BUF_SIZE (2048)
+
#define ENA_MIN_NUM_IO_QUEUES (1)
#define ENA_TX_WAKEUP_THRESH (MAX_SKB_FRAGS + 2)
@@ -175,7 +177,9 @@ struct ena_tx_buffer {
struct ena_rx_buffer {
struct sk_buff *skb;
struct page *page;
+ dma_addr_t dma_addr;
u32 page_offset;
+ u32 buf_offset;
struct ena_com_buf ena_buf;
} ____cacheline_aligned;
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index 483a070d96fa..36f9b932b9e2 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -196,7 +196,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
dma_addr_t q_base_pa;
int err;
- qcq->q.info = vzalloc(num_descs * sizeof(*qcq->q.info));
+ qcq->q.info = vcalloc(num_descs, sizeof(*qcq->q.info));
if (!qcq->q.info) {
err = -ENOMEM;
goto err_out;
@@ -219,7 +219,7 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
if (err)
goto err_out_free_q_info;
- qcq->cq.info = vzalloc(num_descs * sizeof(*qcq->cq.info));
+ qcq->cq.info = vcalloc(num_descs, sizeof(*qcq->cq.info));
if (!qcq->cq.info) {
err = -ENOMEM;
goto err_out_free_irq;
@@ -464,7 +464,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
{
int i;
- pdsc_devcmd_reset(pdsc);
+ if (!pdsc->pdev->is_virtfn)
+ pdsc_devcmd_reset(pdsc);
pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
pdsc_qcq_free(pdsc, &pdsc->adminqcq);
@@ -524,7 +525,8 @@ static void pdsc_fw_down(struct pdsc *pdsc)
}
/* Notify clients of fw_down */
- devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc);
+ if (pdsc->fw_reporter)
+ devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc);
pdsc_notify(PDS_EVENT_RESET, &reset_event);
pdsc_stop(pdsc);
@@ -554,8 +556,9 @@ static void pdsc_fw_up(struct pdsc *pdsc)
/* Notify clients of fw_up */
pdsc->fw_recoveries++;
- devlink_health_reporter_state_update(pdsc->fw_reporter,
- DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
+ if (pdsc->fw_reporter)
+ devlink_health_reporter_state_update(pdsc->fw_reporter,
+ DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
pdsc_notify(PDS_EVENT_RESET, &reset_event);
return;
diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c
index debe5216fe29..f77cd9f5a2fd 100644
--- a/drivers/net/ethernet/amd/pds_core/dev.c
+++ b/drivers/net/ethernet/amd/pds_core/dev.c
@@ -121,7 +121,7 @@ static const char *pdsc_devcmd_str(int opcode)
}
}
-static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds)
+static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds)
{
struct device *dev = pdsc->dev;
unsigned long start_time;
@@ -131,9 +131,6 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds)
int done = 0;
int err = 0;
int status;
- int opcode;
-
- opcode = ioread8(&pdsc->cmd_regs->cmd.opcode);
start_time = jiffies;
max_wait = start_time + (max_seconds * HZ);
@@ -180,10 +177,10 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
pdsc_devcmd_dbell(pdsc);
- err = pdsc_devcmd_wait(pdsc, max_seconds);
+ err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds);
memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
- if (err == -ENXIO || err == -ETIMEDOUT)
+ if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
queue_work(pdsc->wq, &pdsc->health_work);
return err;
diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c
index 9c6b3653c1c7..d9607033bbf2 100644
--- a/drivers/net/ethernet/amd/pds_core/devlink.c
+++ b/drivers/net/ethernet/amd/pds_core/devlink.c
@@ -10,6 +10,9 @@ pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc,
{
int vt;
+ if (!pdsc->viftype_status)
+ return NULL;
+
for (vt = 0; vt < PDS_DEV_TYPE_MAX; vt++) {
if (pdsc->viftype_status[vt].dl_id == dl_id)
return &pdsc->viftype_status[vt];
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 16e7fb2c0dae..6a716337f48b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2782,9 +2782,9 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_prv_data *pdata,
switch (speed) {
case SPEED_10:
- /* Supported in ver >= 30H */
+ /* Supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- return (ver >= 0x30) ? true : false;
+ return (ver == 0x21 || ver >= 0x30);
case SPEED_100:
case SPEED_1000:
return true;
@@ -2806,9 +2806,10 @@ static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_prv_data *pdata,
switch (speed) {
case SPEED_10:
- /* Supported in ver >= 30H */
+ /* Supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- return (ver >= 0x30) && (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
+ return ((ver == 0x21 || ver >= 0x30) &&
+ (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000));
case SPEED_100:
return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
case SPEED_1000:
@@ -3158,9 +3159,9 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
struct xgbe_phy_data *phy_data = pdata->phy_data;
unsigned int ver;
- /* 10 Mbps speed is not supported in ver < 30H */
+ /* 10 Mbps speed is supported in ver 21H and ver >= 30H */
ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
- if (ver < 0x30 && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10))
+ if ((ver < 0x30 && ver != 0x21) && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10))
return true;
switch (phy_data->port_mode) {
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
index 7eb5851eb95d..6afff8af5e86 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c
@@ -289,7 +289,7 @@ static int aq_get_txsc_stats(struct aq_hw_s *hw, const int sc_idx,
static int aq_mdo_dev_open(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int ret = 0;
if (netif_carrier_ok(nic->ndev))
@@ -300,7 +300,7 @@ static int aq_mdo_dev_open(struct macsec_context *ctx)
static int aq_mdo_dev_stop(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int i;
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
@@ -439,7 +439,7 @@ static enum aq_macsec_sc_sa sc_sa_from_num_an(const int num_an)
static int aq_mdo_add_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
enum aq_macsec_sc_sa sc_sa;
@@ -474,7 +474,7 @@ static int aq_mdo_add_secy(struct macsec_context *ctx)
static int aq_mdo_upd_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_secy *secy = ctx->secy;
int txsc_idx;
int ret = 0;
@@ -528,7 +528,7 @@ static int aq_clear_txsc(struct aq_nic_s *nic, const int txsc_idx,
static int aq_mdo_del_secy(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int ret = 0;
if (!nic->macsec_cfg)
@@ -576,7 +576,7 @@ static int aq_update_txsa(struct aq_nic_s *nic, const unsigned int sc_idx,
static int aq_mdo_add_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_txsc *aq_txsc;
@@ -603,7 +603,7 @@ static int aq_mdo_add_txsa(struct macsec_context *ctx)
static int aq_mdo_upd_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_txsc *aq_txsc;
@@ -652,7 +652,7 @@ static int aq_clear_txsa(struct aq_nic_s *nic, struct aq_macsec_txsc *aq_txsc,
static int aq_mdo_del_txsa(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int txsc_idx;
int ret = 0;
@@ -744,7 +744,7 @@ static int aq_set_rxsc(struct aq_nic_s *nic, const u32 rxsc_idx)
static int aq_mdo_add_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const u32 rxsc_idx_max = aq_sc_idx_max(cfg->sc_sa);
u32 rxsc_idx;
@@ -775,7 +775,7 @@ static int aq_mdo_add_rxsc(struct macsec_context *ctx)
static int aq_mdo_upd_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
int rxsc_idx;
int ret = 0;
@@ -838,7 +838,7 @@ static int aq_clear_rxsc(struct aq_nic_s *nic, const int rxsc_idx,
static int aq_mdo_del_rxsc(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
enum aq_clear_type clear_type = AQ_CLEAR_SW;
int rxsc_idx;
int ret = 0;
@@ -906,8 +906,8 @@ static int aq_update_rxsa(struct aq_nic_s *nic, const unsigned int sc_idx,
static int aq_mdo_add_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
const struct macsec_secy *secy = ctx->secy;
struct aq_macsec_rxsc *aq_rxsc;
int rxsc_idx;
@@ -933,8 +933,8 @@ static int aq_mdo_add_rxsa(struct macsec_context *ctx)
static int aq_mdo_upd_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
const struct macsec_secy *secy = ctx->secy;
int rxsc_idx;
@@ -982,8 +982,8 @@ static int aq_clear_rxsa(struct aq_nic_s *nic, struct aq_macsec_rxsc *aq_rxsc,
static int aq_mdo_del_rxsa(struct macsec_context *ctx)
{
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
const struct macsec_rx_sc *rx_sc = ctx->sa.rx_sa->sc;
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int rxsc_idx;
int ret = 0;
@@ -1000,7 +1000,7 @@ static int aq_mdo_del_rxsa(struct macsec_context *ctx)
static int aq_mdo_get_dev_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_common_stats *stats = &nic->macsec_cfg->stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1020,7 +1020,7 @@ static int aq_mdo_get_dev_stats(struct macsec_context *ctx)
static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_tx_sc_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_txsc *aq_txsc;
@@ -1044,7 +1044,7 @@ static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx)
static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_tx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1084,7 +1084,7 @@ static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx)
static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1129,7 +1129,7 @@ static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx)
static int aq_mdo_get_rx_sa_stats(struct macsec_context *ctx)
{
- struct aq_nic_s *nic = netdev_priv(ctx->netdev);
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
@@ -1399,7 +1399,7 @@ static void aq_check_txsa_expiration(struct aq_nic_s *nic)
#define AQ_LOCKED_MDO_DEF(mdo) \
static int aq_locked_mdo_##mdo(struct macsec_context *ctx) \
{ \
- struct aq_nic_s *nic = netdev_priv(ctx->netdev); \
+ struct aq_nic_s *nic = macsec_netdev_priv(ctx->netdev); \
int ret; \
mutex_lock(&nic->macsec_mutex); \
ret = aq_mdo_##mdo(ctx); \
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
index 7f933175cbda..4de22eed099a 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -532,10 +532,10 @@ static bool aq_add_rx_fragment(struct device *dev,
buff_->rxdata.pg_off,
buff_->len,
DMA_FROM_DEVICE);
- skb_frag_off_set(frag, buff_->rxdata.pg_off);
- skb_frag_size_set(frag, buff_->len);
sinfo->xdp_frags_size += buff_->len;
- __skb_frag_set_page(frag, buff_->rxdata.page);
+ skb_frag_fill_page_desc(frag, buff_->rxdata.page,
+ buff_->rxdata.pg_off,
+ buff_->len);
buff_->is_cleaned = 1;
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h
index d820ae03a966..0e244f0e25fd 100644
--- a/drivers/net/ethernet/arc/emac.h
+++ b/drivers/net/ethernet/arc/emac.h
@@ -220,6 +220,6 @@ static inline void arc_reg_clr(struct arc_emac_priv *priv, int reg, int mask)
int arc_mdio_probe(struct arc_emac_priv *priv);
int arc_mdio_remove(struct arc_emac_priv *priv);
int arc_emac_probe(struct net_device *ndev, int interface);
-int arc_emac_remove(struct net_device *ndev);
+void arc_emac_remove(struct net_device *ndev);
#endif /* ARC_EMAC_H */
diff --git a/drivers/net/ethernet/arc/emac_arc.c b/drivers/net/ethernet/arc/emac_arc.c
index 800620b8f10d..ce3147e886a1 100644
--- a/drivers/net/ethernet/arc/emac_arc.c
+++ b/drivers/net/ethernet/arc/emac_arc.c
@@ -61,11 +61,11 @@ out_netdev:
static int emac_arc_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
- int err;
- err = arc_emac_remove(ndev);
+ arc_emac_remove(ndev);
free_netdev(ndev);
- return err;
+
+ return 0;
}
static const struct of_device_id emac_arc_dt_ids[] = {
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index ba0646b3b122..2b427d8a1831 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -1008,7 +1008,7 @@ out_put_node:
}
EXPORT_SYMBOL_GPL(arc_emac_probe);
-int arc_emac_remove(struct net_device *ndev)
+void arc_emac_remove(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
@@ -1019,8 +1019,6 @@ int arc_emac_remove(struct net_device *ndev)
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
-
- return 0;
}
EXPORT_SYMBOL_GPL(arc_emac_remove);
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
index 1c9ca3bcb871..509101112279 100644
--- a/drivers/net/ethernet/arc/emac_rockchip.c
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
@@ -248,9 +248,8 @@ static int emac_rockchip_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct rockchip_priv_data *priv = netdev_priv(ndev);
- int err;
- err = arc_emac_remove(ndev);
+ arc_emac_remove(ndev);
clk_disable_unprepare(priv->refclk);
@@ -261,7 +260,7 @@ static int emac_rockchip_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->macclk);
free_netdev(ndev);
- return err;
+ return 0;
}
static struct platform_driver emac_rockchip_driver = {
diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c
index b716adacd815..7f6b69a52367 100644
--- a/drivers/net/ethernet/atheros/alx/ethtool.c
+++ b/drivers/net/ethernet/atheros/alx/ethtool.c
@@ -292,9 +292,8 @@ static void alx_get_ethtool_stats(struct net_device *netdev,
spin_lock(&alx->stats_lock);
alx_update_hw_stats(hw);
- BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
- ALX_NUM_STATS * sizeof(u64));
- memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
+ BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64));
+ memcpy(data, &hw->stats, sizeof(hw->stats));
spin_unlock(&alx->stats_lock);
}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 4a288799633f..940c5d1ff9cf 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2094,8 +2094,11 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,
real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (unlikely(skb->len == hdr_len)) {
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 5db0f3495a32..5935be190b9e 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1641,8 +1641,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter,
real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (unlikely(skb->len == hdr_len)) {
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index c8444bcdf527..02aa6fd8ebc2 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2113,8 +2113,11 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
real_len = (((unsigned char *)iph - skb->data) +
ntohs(iph->tot_len));
- if (real_len < skb->len)
- pskb_trim(skb, real_len);
+ if (real_len < skb->len) {
+ err = pskb_trim(skb, real_len);
+ if (err)
+ return err;
+ }
hdr_len = skb_tcp_all_headers(skb);
if (skb->len == hdr_len) {
iph->check = 0;
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 392ec09a1d8a..3e4fb3c3e834 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1793,11 +1793,9 @@ static int b44_nway_reset(struct net_device *dev)
b44_readphy(bp, MII_BMCR, &bmcr);
b44_readphy(bp, MII_BMCR, &bmcr);
r = -EINVAL;
- if (bmcr & BMCR_ANENABLE) {
- b44_writephy(bp, MII_BMCR,
- bmcr | BMCR_ANRESTART);
- r = 0;
- }
+ if (bmcr & BMCR_ANENABLE)
+ r = b44_writephy(bp, MII_BMCR,
+ bmcr | BMCR_ANRESTART);
spin_unlock_irq(&bp->lock);
return r;
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 1761df8fb7f9..52ee3751187a 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1448,7 +1448,7 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac)
int err;
phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
- if (!phy_dev || IS_ERR(phy_dev)) {
+ if (IS_ERR(phy_dev)) {
dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
return -ENODEV;
}
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
bgmac->in_init = true;
- bgmac_chip_intrs_off(bgmac);
-
net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);
dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
*/
bgmac_clk_enable(bgmac, 0);
+ bgmac_chip_intrs_off(bgmac);
+
/* This seems to be fixing IRQ by assigning OOB #6 to the core */
if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 466e1d62bcf6..0d917a9699c5 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -2955,7 +2955,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
shinfo = skb_shinfo(skb);
shinfo->nr_frags--;
page = skb_frag_page(&shinfo->frags[shinfo->nr_frags]);
- __skb_frag_set_page(&shinfo->frags[shinfo->nr_frags], NULL);
cons_rx_pg->page = page;
dev_kfree_skb(skb);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8bcde0a6e011..e2a4e1088b7f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1508,6 +1508,8 @@ struct bnx2x {
bool cnic_loaded;
struct cnic_eth_dev *(*cnic_probe)(struct net_device *);
+ bool nic_stopped;
+
/* Flag that indicates that we can start looking for FCoE L2 queue
* completions in the default status block.
*/
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 6ea5521074d3..e9c1e1bb5580 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2715,6 +2715,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_add_all_napi(bp);
DP(NETIF_MSG_IFUP, "napi added\n");
bnx2x_napi_enable(bp);
+ bp->nic_stopped = false;
if (IS_PF(bp)) {
/* set pf load just before approaching the MCP */
@@ -2960,6 +2961,7 @@ load_error2:
load_error1:
bnx2x_napi_disable(bp);
bnx2x_del_all_napi(bp);
+ bp->nic_stopped = true;
/* clear pf_load status, as it was already set */
if (IS_PF(bp))
@@ -3095,14 +3097,17 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
if (!CHIP_IS_E1x(bp))
bnx2x_pf_disable(bp);
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 1);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Report UNLOAD_DONE to MCP */
bnx2x_send_unload_done(bp, false);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 1e7a6f1d4223..0d8e61c63c7c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9474,15 +9474,18 @@ unload_error:
}
}
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 1);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 1);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Reset the chip, unless PCI function is offline. If we reach this
* point following a PCI error handling, it means device is really
@@ -14238,13 +14241,16 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev)
}
bnx2x_drain_tx_queues(bp);
bnx2x_send_unload_req(bp, UNLOAD_RECOVERY);
- bnx2x_netif_stop(bp, 1);
- bnx2x_del_all_napi(bp);
+ if (!bp->nic_stopped) {
+ bnx2x_netif_stop(bp, 1);
+ bnx2x_del_all_napi(bp);
- if (CNIC_LOADED(bp))
- bnx2x_del_all_napi_cnic(bp);
+ if (CNIC_LOADED(bp))
+ bnx2x_del_all_napi_cnic(bp);
- bnx2x_free_irq(bp);
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
/* Report UNLOAD_DONE to MCP */
bnx2x_send_unload_done(bp, true);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 0657a0f5170f..8946a931e87e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -529,13 +529,16 @@ void bnx2x_vfpf_close_vf(struct bnx2x *bp)
bnx2x_vfpf_finalize(bp, &req->first_tlv);
free_irq:
- /* Disable HW interrupts, NAPI */
- bnx2x_netif_stop(bp, 0);
- /* Delete all NAPI objects */
- bnx2x_del_all_napi(bp);
-
- /* Release IRQs */
- bnx2x_free_irq(bp);
+ if (!bp->nic_stopped) {
+ /* Disable HW interrupts, NAPI */
+ bnx2x_netif_stop(bp, 0);
+ /* Delete all NAPI objects */
+ bnx2x_del_all_napi(bp);
+
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+ bp->nic_stopped = true;
+ }
}
static void bnx2x_leading_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b499bc9c4e06..1eb490c48c52 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -633,12 +633,13 @@ tx_kick_pending:
return NETDEV_TX_OK;
}
-static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
u16 cons = txr->tx_cons;
struct pci_dev *pdev = bp->pdev;
+ int nr_pkts = bnapi->tx_pkts;
int i;
unsigned int tx_bytes = 0;
@@ -688,6 +689,7 @@ next_tx_int:
dev_kfree_skb_any(skb);
}
+ bnapi->tx_pkts = 0;
WRITE_ONCE(txr->tx_cons, cons);
__netif_txq_completed_wake(txq, nr_pkts, tx_bytes,
@@ -697,17 +699,24 @@ next_tx_int:
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
struct bnxt_rx_ring_info *rxr,
+ unsigned int *offset,
gfp_t gfp)
{
struct device *dev = &bp->pdev->dev;
struct page *page;
- page = page_pool_dev_alloc_pages(rxr->page_pool);
+ if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
+ page = page_pool_dev_alloc_frag(rxr->page_pool, offset,
+ BNXT_RX_PAGE_SIZE);
+ } else {
+ page = page_pool_dev_alloc_pages(rxr->page_pool);
+ *offset = 0;
+ }
if (!page)
return NULL;
- *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
+ *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
if (dma_mapping_error(dev, *mapping)) {
page_pool_recycle_direct(rxr->page_pool, page);
return NULL;
@@ -747,15 +756,16 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
dma_addr_t mapping;
if (BNXT_RX_PAGE_MODE(bp)) {
+ unsigned int offset;
struct page *page =
- __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+ __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
if (!page)
return -ENOMEM;
mapping += bp->rx_dma_offset;
rx_buf->data = page;
- rx_buf->data_ptr = page_address(page) + bp->rx_offset;
+ rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
} else {
u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
@@ -815,7 +825,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp,
unsigned int offset = 0;
if (BNXT_RX_PAGE_MODE(bp)) {
- page = __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+ page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
if (!page)
return -ENOMEM;
@@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
return NULL;
}
dma_addr -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
- skb = build_skb(page_address(page), PAGE_SIZE);
+ dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
+ skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE);
if (!skb) {
page_pool_recycle_direct(rxr->page_pool, page);
return NULL;
}
skb_mark_for_recycle(skb);
- skb_reserve(skb, bp->rx_dma_offset);
+ skb_reserve(skb, bp->rx_offset);
__skb_put(skb, len);
return skb;
@@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
return NULL;
}
dma_addr -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
- DMA_ATTR_WEAK_ORDERING);
+ dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+ bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
if (unlikely(!payload))
payload = eth_get_headlen(bp->dev, data_ptr, len);
@@ -1010,7 +1020,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
skb_mark_for_recycle(skb);
off = (void *)data_ptr - page_address(page);
- skb_add_rx_frag(skb, 0, page, off, len, PAGE_SIZE);
+ skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE);
memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN,
payload + NET_IP_ALIGN);
@@ -1085,9 +1095,8 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp,
RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT;
cons_rx_buf = &rxr->rx_agg_ring[cons];
- skb_frag_off_set(frag, cons_rx_buf->offset);
- skb_frag_size_set(frag, frag_len);
- __skb_frag_set_page(frag, cons_rx_buf->page);
+ skb_frag_fill_page_desc(frag, cons_rx_buf->page,
+ cons_rx_buf->offset, frag_len);
shinfo->nr_frags = i + 1;
__clear_bit(cons, rxr->rx_agg_bmap);
@@ -1103,10 +1112,7 @@ static u32 __bnxt_rx_agg_pages(struct bnxt *bp,
xdp_buff_set_frag_pfmemalloc(xdp);
if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_ATOMIC) != 0) {
- unsigned int nr_frags;
-
- nr_frags = --shinfo->nr_frags;
- __skb_frag_set_page(&shinfo->frags[nr_frags], NULL);
+ --shinfo->nr_frags;
cons_rx_buf->page = page;
/* Update prod since possibly some pages have been
@@ -1145,7 +1151,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp,
skb->data_len += total_frag_len;
skb->len += total_frag_len;
- skb->truesize += PAGE_SIZE * agg_bufs;
+ skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs;
return skb;
}
@@ -2573,12 +2579,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
return rx_pkts;
}
-static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
+static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
+ int budget)
{
- if (bnapi->tx_pkts) {
- bnapi->tx_int(bp, bnapi, bnapi->tx_pkts);
- bnapi->tx_pkts = 0;
- }
+ if (bnapi->tx_pkts)
+ bnapi->tx_int(bp, bnapi, budget);
if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -2607,7 +2612,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
*/
bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons);
- __bnxt_poll_work_done(bp, bnapi);
+ __bnxt_poll_work_done(bp, bnapi, budget);
return rx_pkts;
}
@@ -2738,7 +2743,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
}
static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
- u64 dbr_type)
+ u64 dbr_type, int budget)
{
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
int i;
@@ -2754,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
cpr2->had_work_done = 0;
}
}
- __bnxt_poll_work_done(bp, bnapi);
+ __bnxt_poll_work_done(bp, bnapi, budget);
}
static int bnxt_poll_p5(struct napi_struct *napi, int budget)
@@ -2784,7 +2789,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
if (cpr->has_more_work)
break;
- __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL);
+ __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL,
+ budget);
cpr->cp_raw_cons = raw_cons;
if (napi_complete_done(napi, work_done))
BNXT_DB_NQ_ARM_P5(&cpr->cp_db,
@@ -2814,7 +2820,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
}
raw_cons = NEXT_RAW_CMP(raw_cons);
}
- __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ);
+ __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget);
if (raw_cons != cpr->cp_raw_cons) {
cpr->cp_raw_cons = raw_cons;
BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
@@ -2947,8 +2953,8 @@ skip_rx_tpa_free:
rx_buf->data = NULL;
if (BNXT_RX_PAGE_MODE(bp)) {
mapping -= bp->rx_dma_offset;
- dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE,
- bp->rx_dir,
+ dma_unmap_page_attrs(&pdev->dev, mapping,
+ BNXT_RX_PAGE_SIZE, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING);
page_pool_recycle_direct(rxr->page_pool, data);
} else {
@@ -3217,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
pp.napi = &rxr->bnapi->napi;
pp.dev = &bp->pdev->dev;
pp.dma_dir = DMA_BIDIRECTIONAL;
+ if (PAGE_SIZE > BNXT_RX_PAGE_SIZE)
+ pp.flags |= PP_FLAG_PAGE_FRAG;
rxr->page_pool = page_pool_create(&pp);
if (IS_ERR(rxr->page_pool)) {
@@ -3993,26 +4001,29 @@ void bnxt_set_ring_params(struct bnxt *bp)
*/
int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
{
+ struct net_device *dev = bp->dev;
+
if (page_mode) {
bp->flags &= ~BNXT_FLAG_AGG_RINGS;
bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
- if (bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
+ if (bp->xdp_prog->aux->xdp_has_frags)
+ dev->max_mtu = min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
+ else
+ dev->max_mtu =
+ min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
+ if (dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
bp->flags |= BNXT_FLAG_JUMBO;
bp->rx_skb_func = bnxt_rx_multi_page_skb;
- bp->dev->max_mtu =
- min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
} else {
bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
bp->rx_skb_func = bnxt_rx_page_skb;
- bp->dev->max_mtu =
- min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
}
bp->rx_dir = DMA_BIDIRECTIONAL;
/* Disable LRO or GRO_HW */
- netdev_update_features(bp->dev);
+ netdev_update_features(dev);
} else {
- bp->dev->max_mtu = bp->max_mtu;
+ dev->max_mtu = bp->max_mtu;
bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
bp->rx_dir = DMA_FROM_DEVICE;
bp->rx_skb_func = bnxt_rx_skb;
@@ -9433,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp)
cpr->sw_stats.rx.rx_resets++;
bnapi->in_reset = false;
+ bnapi->tx_pkts = 0;
+
if (bnapi->rx_ring) {
INIT_WORK(&cpr->dim.work, bnxt_dim_work);
cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 080e73496066..bb95c3dc5270 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1005,7 +1005,7 @@ struct bnxt_napi {
struct bnxt_tx_ring_info *tx_ring;
void (*tx_int)(struct bnxt *, struct bnxt_napi *,
- int);
+ int budget);
int tx_pkts;
u8 events;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
index b31de4cf6534..a2d3a80236c4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
@@ -3721,6 +3721,60 @@ struct hwrm_func_backing_store_qcaps_v2_output {
u8 valid;
};
+/* hwrm_func_dbr_pacing_qcfg_input (size:128b/16B) */
+struct hwrm_func_dbr_pacing_qcfg_input {
+ __le16 req_type;
+ __le16 cmpl_ring;
+ __le16 seq_id;
+ __le16 target_id;
+ __le64 resp_addr;
+};
+
+/* hwrm_func_dbr_pacing_qcfg_output (size:512b/64B) */
+struct hwrm_func_dbr_pacing_qcfg_output {
+ __le16 error_code;
+ __le16 req_type;
+ __le16 seq_id;
+ __le16 resp_len;
+ u8 flags;
+#define FUNC_DBR_PACING_QCFG_RESP_FLAGS_DBR_NQ_EVENT_ENABLED 0x1UL
+ u8 unused_0[7];
+ __le32 dbr_stat_db_fifo_reg;
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_MASK 0x3UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_SFT 0
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_GRC 0x1UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_BAR0 0x2UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_BAR1 0x3UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_LAST \
+ FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SPACE_BAR1
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_MASK 0xfffffffcUL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_STAT_DB_FIFO_REG_ADDR_SFT 2
+ __le32 dbr_stat_db_fifo_reg_watermark_mask;
+ u8 dbr_stat_db_fifo_reg_watermark_shift;
+ u8 unused_1[3];
+ __le32 dbr_stat_db_fifo_reg_fifo_room_mask;
+ u8 dbr_stat_db_fifo_reg_fifo_room_shift;
+ u8 unused_2[3];
+ __le32 dbr_throttling_aeq_arm_reg;
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_MASK 0x3UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_SFT 0
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_PCIE_CFG 0x0UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_GRC 0x1UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_BAR0 0x2UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_BAR1 0x3UL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_LAST \
+ FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SPACE_BAR1
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_MASK 0xfffffffcUL
+#define FUNC_DBR_PACING_QCFG_RESP_DBR_THROTTLING_AEQ_ARM_REG_ADDR_SFT 2
+ u8 dbr_throttling_aeq_arm_reg_val;
+ u8 unused_3[7];
+ __le32 primary_nq_id;
+ __le32 pacing_threshold;
+ u8 unused_4[7];
+ u8 valid;
+};
+
/* hwrm_func_drv_if_change_input (size:192b/24B) */
struct hwrm_func_drv_if_change_input {
__le16 req_type;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
index 852eb449ccae..6ba2b9398633 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -345,7 +345,7 @@ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
edev->hw_ring_stats_size = bp->hw_ring_stats_size;
edev->pf_port_id = bp->pf.port_id;
edev->en_state = bp->state;
-
+ edev->bar0 = bp->bar0;
edev->ulp_tbl->msix_requested = bnxt_get_ulp_msix_num(bp);
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
index 80cbc4b6130a..6ff77f082e6c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
@@ -81,6 +81,7 @@ struct bnxt_en_dev {
* mode only. Will be
* updated in resume.
*/
+ void __iomem *bar0;
};
static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 2f1a1f2d2157..1467b94a6427 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -468,6 +468,7 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep,
struct net_device *pf_dev = bp->dev;
u16 max_mtu;
+ SET_NETDEV_DEV(dev, &bp->pdev->dev);
dev->netdev_ops = &bnxt_vf_rep_netdev_ops;
dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops;
/* Just inherit all the featues of the parent PF as the VF-R
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 4efa5fe6972b..fb43232310b2 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
dma_unmap_len_set(tx_buf, len, 0);
}
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
bool rx_doorbell_needed = false;
+ int nr_pkts = bnapi->tx_pkts;
struct bnxt_sw_tx_bd *tx_buf;
u16 tx_cons = txr->tx_cons;
u16 last_tx_cons = tx_cons;
int i, j, frags;
+ if (!budget)
+ return;
+
for (i = 0; i < nr_pkts; i++) {
tx_buf = &txr->tx_buf_ring[tx_cons];
@@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
}
tx_cons = NEXT_TX(tx_cons);
}
+
+ bnapi->tx_pkts = 0;
WRITE_ONCE(txr->tx_cons, tx_cons);
if (rx_doorbell_needed) {
tx_buf = &txr->tx_buf_ring[last_tx_cons];
@@ -180,8 +186,8 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
u16 cons, u8 *data_ptr, unsigned int len,
struct xdp_buff *xdp)
{
+ u32 buflen = BNXT_RX_PAGE_SIZE;
struct bnxt_sw_rx_bd *rx_buf;
- u32 buflen = PAGE_SIZE;
struct pci_dev *pdev;
dma_addr_t mapping;
u32 offset;
@@ -297,7 +303,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
rx_buf = &rxr->rx_buf_ring[cons];
mapping = rx_buf->mapping - bp->rx_dma_offset;
dma_unmap_page_attrs(&pdev->dev, mapping,
- PAGE_SIZE, bp->rx_dir,
+ BNXT_RX_PAGE_SIZE, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING);
/* if we are unable to allocate a new buffer, abort and reuse */
@@ -480,7 +486,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
}
xdp_update_skb_shared_info(skb, num_frags,
sinfo->xdp_frags_size,
- PAGE_SIZE * sinfo->nr_frags,
+ BNXT_RX_PAGE_SIZE * sinfo->nr_frags,
xdp_buff_is_frag_pfmemalloc(xdp));
return skb;
}
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
index ea430d6961df..5e412c5655ba 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
@@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
struct bnxt_tx_ring_info *txr,
dma_addr_t mapping, u32 len,
struct xdp_buff *xdp);
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget);
bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
struct xdp_buff xdp, struct page *page, u8 **data_ptr,
unsigned int *len, u8 *event);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
index 3a4b6cb7b7b9..7a41cad5788f 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -42,6 +42,12 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
+ if (dev->phydev) {
+ phy_ethtool_get_wol(dev->phydev, wol);
+ if (wol->supported)
+ return;
+ }
+
if (!device_can_wakeup(kdev)) {
wol->supported = 0;
wol->wolopts = 0;
@@ -63,6 +69,14 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
+ int ret;
+
+ /* Try Wake-on-LAN from the PHY first */
+ if (dev->phydev) {
+ ret = phy_ethtool_set_wol(dev->phydev, wol);
+ if (ret != -EOPNOTSUPP)
+ return ret;
+ }
if (!device_can_wakeup(kdev))
return -ENOTSUPP;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index c15ed0acdb77..cc3afb605b1e 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -617,7 +617,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
};
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
- if (!phydev || IS_ERR(phydev)) {
+ if (IS_ERR(phydev)) {
dev_err(kdev, "failed to register fixed PHY device\n");
return -ENODEV;
}
@@ -673,5 +673,7 @@ void bcmgenet_mii_exit(struct net_device *dev)
if (of_phy_is_fixed_link(dn))
of_phy_deregister_fixed_link(dn);
of_node_put(priv->phy_dn);
+ clk_prepare_enable(priv->clk);
platform_device_unregister(priv->mii_pdev);
+ clk_disable_unprepare(priv->clk);
}
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 58747292521d..cb2810f175cc 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -57,6 +57,7 @@
#include <linux/crc32poly.h>
#include <net/checksum.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <linux/io.h>
@@ -224,6 +225,7 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox
MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG357766);
MODULE_FIRMWARE(FIRMWARE_TG3TSO);
MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
@@ -6879,7 +6881,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
ri->data = NULL;
- skb = build_skb(data, frag_size);
+ if (frag_size)
+ skb = build_skb(data, frag_size);
+ else
+ skb = slab_build_skb(data);
if (!skb) {
tg3_frag_free(frag_size != 0, data);
goto drop_it_no_recycle;
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
index 04ad0f2b9677..7246e13dd559 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
@@ -512,11 +512,6 @@ bnad_debugfs_init(struct bnad *bnad)
if (!bnad->port_debugfs_root) {
bnad->port_debugfs_root =
debugfs_create_dir(name, bna_debugfs_root);
- if (!bnad->port_debugfs_root) {
- netdev_warn(bnad->netdev,
- "debugfs root dir creation failed\n");
- return;
- }
atomic_inc(&bna_debugfs_port_count);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index cfbdd0022764..78c972bb1d96 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -82,6 +82,7 @@
#define GEM_NCFGR 0x0004 /* Network Config */
#define GEM_USRIO 0x000c /* User IO */
#define GEM_DMACFG 0x0010 /* DMA Configuration */
+#define GEM_PBUFRXCUT 0x0044 /* RX Partial Store and Forward */
#define GEM_JML 0x0048 /* Jumbo Max Length */
#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */
#define GEM_HRB 0x0080 /* Hash Bottom */
@@ -347,6 +348,10 @@
#define GEM_ADDR64_SIZE 1
+/* Bitfields in PBUFRXCUT */
+#define GEM_ENCUTTHRU_OFFSET 31 /* Enable RX partial store and forward */
+#define GEM_ENCUTTHRU_SIZE 1
+
/* Bitfields in NSR */
#define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */
#define MACB_NSR_LINK_SIZE 1
@@ -513,6 +518,8 @@
#define GEM_TX_PKT_BUFF_OFFSET 21
#define GEM_TX_PKT_BUFF_SIZE 1
+#define GEM_RX_PBUF_ADDR_OFFSET 22
+#define GEM_RX_PBUF_ADDR_SIZE 4
/* Bitfields in DCFG5. */
#define GEM_TSU_OFFSET 8
@@ -521,6 +528,8 @@
/* Bitfields in DCFG6. */
#define GEM_PBUF_LSO_OFFSET 27
#define GEM_PBUF_LSO_SIZE 1
+#define GEM_PBUF_CUTTHRU_OFFSET 25
+#define GEM_PBUF_CUTTHRU_SIZE 1
#define GEM_DAW64_OFFSET 23
#define GEM_DAW64_SIZE 1
@@ -1181,6 +1190,7 @@ struct macb_config {
struct clk **hclk, struct clk **tx_clk,
struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev);
+ unsigned int max_tx_length;
int jumbo_max_len;
const struct macb_usrio_config *usrio;
};
@@ -1289,6 +1299,9 @@ struct macb {
u32 wol;
+ /* holds value of rx watermark value for pbuf_rxcutthru register */
+ u32 rx_watermark;
+
struct macb_ptp_info *ptp_info; /* macb-ptp interface */
struct phy *sgmii_phy; /* for ZynqMP SGMII mode */
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 29a1199dad14..2d18acf3d5ea 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -563,7 +563,7 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}
-static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed,
int duplex)
{
@@ -596,7 +596,7 @@ static void macb_usx_pcs_get_state(struct phylink_pcs *pcs,
}
static int macb_usx_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -621,7 +621,7 @@ static void macb_pcs_an_restart(struct phylink_pcs *pcs)
}
static int macb_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -757,8 +757,6 @@ static void macb_mac_link_up(struct phylink_config *config,
if (rx_pause)
ctrl |= MACB_BIT(PAE);
- macb_set_tx_clk(bp, speed);
-
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers.
*/
@@ -778,6 +776,9 @@ static void macb_mac_link_up(struct phylink_config *config,
spin_unlock_irqrestore(&bp->lock, flags);
+ if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
+ macb_set_tx_clk(bp, speed);
+
/* Enable Rx and Tx; Enable PTP unicast */
ctrl = macb_readl(bp, NCR);
if (gem_has_ptp(bp))
@@ -862,7 +863,9 @@ static int macb_mii_probe(struct net_device *dev)
struct macb *bp = netdev_priv(dev);
bp->phylink_sgmii_pcs.ops = &macb_phylink_pcs_ops;
+ bp->phylink_sgmii_pcs.neg_mode = true;
bp->phylink_usx_pcs.ops = &macb_phylink_usx_pcs_ops;
+ bp->phylink_usx_pcs.neg_mode = true;
bp->phylink_config.dev = &dev->dev;
bp->phylink_config.type = PHYLINK_NETDEV;
@@ -2635,6 +2638,9 @@ static void macb_reset_hw(struct macb *bp)
macb_writel(bp, TSR, -1);
macb_writel(bp, RSR, -1);
+ /* Disable RX partial store and forward and reset watermark value */
+ gem_writel(bp, PBUFRXCUT, 0);
+
/* Disable all interrupts */
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
queue_writel(queue, IDR, -1);
@@ -2792,6 +2798,10 @@ static void macb_init_hw(struct macb *bp)
bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
macb_configure_dma(bp);
+
+ /* Enable RX partial store and forward and set watermark */
+ if (bp->rx_watermark)
+ gem_writel(bp, PBUFRXCUT, (bp->rx_watermark | GEM_BIT(ENCUTTHRU)));
}
/* The hash address register is 64 bits long and takes up two
@@ -4117,14 +4127,12 @@ static int macb_init(struct platform_device *pdev)
/* setup appropriated routines according to adapter type */
if (macb_is_gem(bp)) {
- bp->max_tx_length = GEM_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = gem_init_rings;
bp->macbgem_ops.mog_rx = gem_rx;
dev->ethtool_ops = &gem_ethtool_ops;
} else {
- bp->max_tx_length = MACB_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = macb_init_rings;
@@ -4861,7 +4869,8 @@ static const struct macb_config mpfs_config = {
.clk_init = macb_clk_init,
.init = init_reset_optional,
.usrio = &macb_default_usrio,
- .jumbo_max_len = 10240,
+ .max_tx_length = 4040, /* Cadence Erratum 1686 */
+ .jumbo_max_len = 4040,
};
static const struct macb_config sama7g5_gem_config = {
@@ -4947,6 +4956,7 @@ static int macb_probe(struct platform_device *pdev)
phy_interface_t interface;
struct net_device *dev;
struct resource *regs;
+ u32 wtrmrk_rst_val;
void __iomem *mem;
struct macb *bp;
int err, val;
@@ -5012,6 +5022,13 @@ static int macb_probe(struct platform_device *pdev)
if (macb_config)
bp->jumbo_max_len = macb_config->jumbo_max_len;
+ if (!hw_is_gem(bp->regs, bp->native_io))
+ bp->max_tx_length = MACB_MAX_TX_LEN;
+ else if (macb_config->max_tx_length)
+ bp->max_tx_length = macb_config->max_tx_length;
+ else
+ bp->max_tx_length = GEM_MAX_TX_LEN;
+
bp->wol = 0;
if (of_property_read_bool(np, "magic-packet"))
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
@@ -5019,6 +5036,25 @@ static int macb_probe(struct platform_device *pdev)
bp->usrio = macb_config->usrio;
+ /* By default we set to partial store and forward mode for zynqmp.
+ * Disable if not set in devicetree.
+ */
+ if (GEM_BFEXT(PBUF_CUTTHRU, gem_readl(bp, DCFG6))) {
+ err = of_property_read_u32(bp->pdev->dev.of_node,
+ "cdns,rx-watermark",
+ &bp->rx_watermark);
+
+ if (!err) {
+ /* Disable partial store and forward in case of error or
+ * invalid watermark value
+ */
+ wtrmrk_rst_val = (1 << (GEM_BFEXT(RX_PBUF_ADDR, gem_readl(bp, DCFG2)))) - 1;
+ if (bp->rx_watermark > wtrmrk_rst_val || !bp->rx_watermark) {
+ dev_info(&bp->pdev->dev, "Invalid watermark value\n");
+ bp->rx_watermark = 0;
+ }
+ }
+ }
spin_lock_init(&bp->lock);
/* setup capabilities */
@@ -5159,6 +5195,9 @@ static int __maybe_unused macb_suspend(struct device *dev)
unsigned int q;
int err;
+ if (!device_may_wakeup(&bp->dev->dev))
+ phy_exit(bp->sgmii_phy);
+
if (!netif_running(netdev))
return 0;
@@ -5219,7 +5258,6 @@ static int __maybe_unused macb_suspend(struct device *dev)
if (!(bp->wol & MACB_WOL_ENABLED)) {
rtnl_lock();
phylink_stop(bp->phylink);
- phy_exit(bp->sgmii_phy);
rtnl_unlock();
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
@@ -5249,6 +5287,9 @@ static int __maybe_unused macb_resume(struct device *dev)
unsigned int q;
int err;
+ if (!device_may_wakeup(&bp->dev->dev))
+ phy_init(bp->sgmii_phy);
+
if (!netif_running(netdev))
return 0;
@@ -5309,8 +5350,6 @@ static int __maybe_unused macb_resume(struct device *dev)
macb_set_rx_mode(netdev);
macb_restore_features(bp);
rtnl_lock();
- if (!device_may_wakeup(&bp->dev->dev))
- phy_init(bp->sgmii_phy);
phylink_start(bp->phylink);
rtnl_unlock();
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 1c76c95b0b27..ca742cc146d7 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -62,6 +62,9 @@ config CAVIUM_PTP
Precision Time Protocol or other purposes. Timestamps can be used in
BGX, TNS, GTI, and NIC blocks.
+config LIQUIDIO_CORE
+ tristate
+
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT && PCI
@@ -69,6 +72,7 @@ config LIQUIDIO
depends on PTP_1588_CLOCK_OPTIONAL
select FW_LOADER
select LIBCRC32C
+ select LIQUIDIO_CORE
select NET_DEVLINK
help
This driver supports Cavium LiquidIO Intelligent Server Adapters
@@ -92,6 +96,7 @@ config LIQUIDIO_VF
tristate "Cavium LiquidIO VF support"
depends on 64BIT && PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL
+ select LIQUIDIO_CORE
help
This driver supports Cavium LiquidIO Intelligent Server Adapter
based on CN23XX chips.
diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile
index bc9937502043..4ee80af88e79 100644
--- a/drivers/net/ethernet/cavium/liquidio/Makefile
+++ b/drivers/net/ethernet/cavium/liquidio/Makefile
@@ -3,7 +3,9 @@
# Cavium Liquidio ethernet device driver
#
-common-objs := lio_ethtool.o \
+obj-$(CONFIG_LIQUIDIO_CORE) += liquidio-core.o
+liquidio-core-y := \
+ lio_ethtool.o \
lio_core.o \
request_manager.o \
response_manager.o \
@@ -18,7 +20,7 @@ common-objs := lio_ethtool.o \
octeon_nic.o
obj-$(CONFIG_LIQUIDIO) += liquidio.o
-liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o $(common-objs)
+liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o
obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o
-liquidio_vf-y := lio_vf_main.o $(common-objs)
+liquidio_vf-y := lio_vf_main.o
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
index 9ed3d1ab2ca5..068ed52b66c9 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -719,12 +719,10 @@ static int cn23xx_setup_pf_mbox(struct octeon_device *oct)
for (i = 0; i < oct->sriov_info.max_vfs; i++) {
q_no = i * oct->sriov_info.rings_per_vf;
- mbox = vmalloc(sizeof(*mbox));
+ mbox = vzalloc(sizeof(*mbox));
if (!mbox)
goto free_mbox;
- memset(mbox, 0, sizeof(struct octeon_mbox));
-
spin_lock_init(&mbox->lock);
mbox->oct_dev = oct;
@@ -1377,6 +1375,7 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(setup_cn23xx_octeon_pf_device);
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
struct octeon_config *conf23xx)
@@ -1435,6 +1434,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct)
val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2);
return (val >> SCR2_BIT_FW_LOADED) & 1ULL;
}
+EXPORT_SYMBOL_GPL(cn23xx_fw_loaded);
void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
u8 *mac)
@@ -1456,6 +1456,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
octeon_mbox_write(oct, &mbox_cmd);
}
}
+EXPORT_SYMBOL_GPL(cn23xx_tell_vf_its_macaddr_changed);
static void
cn23xx_get_vf_stats_callback(struct octeon_device *oct,
@@ -1510,3 +1511,4 @@ int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx,
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_get_vf_stats);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
index fda49404968c..dd5d80fee24f 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
@@ -279,12 +279,10 @@ static int cn23xx_setup_vf_mbox(struct octeon_device *oct)
{
struct octeon_mbox *mbox = NULL;
- mbox = vmalloc(sizeof(*mbox));
+ mbox = vzalloc(sizeof(*mbox));
if (!mbox)
return 1;
- memset(mbox, 0, sizeof(struct octeon_mbox));
-
spin_lock_init(&mbox->lock);
mbox->oct_dev = oct;
@@ -386,6 +384,7 @@ void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct)
octeon_mbox_write(oct, &mbox_cmd);
}
+EXPORT_SYMBOL_GPL(cn23xx_vf_ask_pf_to_do_flr);
static void octeon_pfvf_hs_callback(struct octeon_device *oct,
struct octeon_mbox_cmd *cmd,
@@ -468,6 +467,7 @@ int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_octeon_pfvf_handshake);
static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector)
{
@@ -680,3 +680,4 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(cn23xx_setup_octeon_vf_device);
diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
index 39643be8c30a..93fccfec288d 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
@@ -697,6 +697,7 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_cn66xx_octeon_device);
int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
struct octeon_config *conf6xxx)
diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
index 30254e4cf70f..b5103def3761 100644
--- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
@@ -181,3 +181,4 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_cn68xx_octeon_device);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index 882b2be06ea0..9cc6303c82ff 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -26,6 +26,9 @@
#include "octeon_main.h"
#include "octeon_network.h"
+MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
+MODULE_LICENSE("GPL");
+
/* OOM task polling interval */
#define LIO_OOM_POLL_INTERVAL_MS 250
@@ -71,6 +74,7 @@ void lio_delete_glists(struct lio *lio)
kfree(lio->glist);
lio->glist = NULL;
}
+EXPORT_SYMBOL_GPL(lio_delete_glists);
/**
* lio_setup_glists - Setup gather lists
@@ -154,6 +158,7 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs)
return 0;
}
+EXPORT_SYMBOL_GPL(lio_setup_glists);
int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
{
@@ -180,6 +185,7 @@ int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
}
return ret;
}
+EXPORT_SYMBOL_GPL(liquidio_set_feature);
void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
unsigned int bytes_compl)
@@ -395,6 +401,7 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
nctrl->ncmd.s.cmd);
}
}
+EXPORT_SYMBOL_GPL(liquidio_link_ctrl_cmd_completion);
void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
{
@@ -478,6 +485,7 @@ int setup_rx_oom_poll_fn(struct net_device *netdev)
return 0;
}
+EXPORT_SYMBOL_GPL(setup_rx_oom_poll_fn);
void cleanup_rx_oom_poll_fn(struct net_device *netdev)
{
@@ -495,6 +503,7 @@ void cleanup_rx_oom_poll_fn(struct net_device *netdev)
}
}
}
+EXPORT_SYMBOL_GPL(cleanup_rx_oom_poll_fn);
/* Runs in interrupt context. */
static void lio_update_txq_status(struct octeon_device *oct, int iq_num)
@@ -899,6 +908,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx,
return 0;
}
+EXPORT_SYMBOL_GPL(liquidio_setup_io_queues);
static
int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret)
@@ -1194,6 +1204,7 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs)
}
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_interrupt);
/**
* liquidio_change_mtu - Net device change_mtu
@@ -1256,6 +1267,7 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
WRITE_ONCE(sc->caller_is_done, true);
return 0;
}
+EXPORT_SYMBOL_GPL(liquidio_change_mtu);
int lio_wait_for_clean_oq(struct octeon_device *oct)
{
@@ -1279,6 +1291,7 @@ int lio_wait_for_clean_oq(struct octeon_device *oct)
return pending_pkts;
}
+EXPORT_SYMBOL_GPL(lio_wait_for_clean_oq);
static void
octnet_nic_stats_callback(struct octeon_device *oct_dev,
@@ -1509,6 +1522,7 @@ lio_fetch_stats_exit:
return;
}
+EXPORT_SYMBOL_GPL(lio_fetch_stats);
int liquidio_set_speed(struct lio *lio, int speed)
{
@@ -1659,6 +1673,7 @@ int liquidio_get_speed(struct lio *lio)
return retval;
}
+EXPORT_SYMBOL_GPL(liquidio_get_speed);
int liquidio_set_fec(struct lio *lio, int on_off)
{
@@ -1812,3 +1827,4 @@ int liquidio_get_fec(struct lio *lio)
return retval;
}
+EXPORT_SYMBOL_GPL(liquidio_get_fec);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
index 2c10ae3f7fc1..9d56181a301f 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
@@ -3180,3 +3180,4 @@ void liquidio_set_ethtool_ops(struct net_device *netdev)
else
netdev->ethtool_ops = &lio_ethtool_ops;
}
+EXPORT_SYMBOL_GPL(liquidio_set_ethtool_ops);
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 9bd1d2d7027d..100daadbea2a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -191,8 +191,7 @@ static void octeon_droq_bh(struct tasklet_struct *t)
static int lio_wait_for_oq_pkts(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
int retry = 100, pkt_cnt = 0, pending_pkts = 0;
int i;
@@ -950,8 +949,7 @@ static void octeon_destroy_resources(struct octeon_device *oct)
{
int i, refcount;
struct msix_entry *msix_entries;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct handshake *hs;
@@ -1211,8 +1209,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;
@@ -1774,8 +1771,7 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -1855,8 +1851,7 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -4057,8 +4052,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
char bootcmd[] = "\n";
char *dbg_enb = NULL;
enum lio_fw_state fw_state;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)octeon_dev->priv;
+ struct octeon_device_priv *oct_priv = octeon_dev->priv;
atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
/* Enable access to the octeon device and make its DMA capability
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index e2921aec3da0..62c2eadc33e3 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -72,8 +72,7 @@ static int liquidio_stop(struct net_device *netdev);
static int lio_wait_for_oq_pkts(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
int retry = MAX_IO_PENDING_PKT_COUNT;
int pkt_cnt = 0, pending_pkts;
int i;
@@ -442,8 +441,7 @@ static void octeon_pci_flr(struct octeon_device *oct)
*/
static void octeon_destroy_resources(struct octeon_device *oct)
{
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct msix_entry *msix_entries;
int i;
@@ -659,8 +657,7 @@ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
{
struct net_device *netdev = oct->props[ifidx].netdev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
struct lio *lio;
@@ -909,8 +906,7 @@ static int liquidio_open(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
@@ -956,8 +952,7 @@ static int liquidio_stop(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
- struct octeon_device_priv *oct_priv =
- (struct octeon_device_priv *)oct->priv;
+ struct octeon_device_priv *oct_priv = oct->priv;
struct napi_struct *napi, *n;
int ret = 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index e159194d0aef..364f4f912dc2 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -564,6 +564,7 @@ void octeon_init_device_list(int conf_type)
for (i = 0; i < MAX_OCTEON_DEVICES; i++)
oct_set_config_info(i, conf_type);
}
+EXPORT_SYMBOL_GPL(octeon_init_device_list);
static void *__retrieve_octeon_config_info(struct octeon_device *oct,
u16 card_type)
@@ -633,6 +634,7 @@ char *lio_get_state_string(atomic_t *state_ptr)
return oct_dev_state_str[OCT_DEV_STATE_INVALID];
return oct_dev_state_str[istate];
}
+EXPORT_SYMBOL_GPL(lio_get_state_string);
static char *get_oct_app_string(u32 app_mode)
{
@@ -661,6 +663,7 @@ void octeon_free_device_mem(struct octeon_device *oct)
octeon_device[i] = NULL;
octeon_device_count--;
}
+EXPORT_SYMBOL_GPL(octeon_free_device_mem);
static struct octeon_device *octeon_allocate_device_mem(u32 pci_id,
u32 priv_size)
@@ -747,6 +750,7 @@ struct octeon_device *octeon_allocate_device(u32 pci_id,
return oct;
}
+EXPORT_SYMBOL_GPL(octeon_allocate_device);
/** Register a device's bus location at initialization time.
* @param octeon_dev - pointer to the octeon device structure.
@@ -804,6 +808,7 @@ int octeon_register_device(struct octeon_device *oct,
return refcount;
}
+EXPORT_SYMBOL_GPL(octeon_register_device);
/** Deregister a device at de-initialization time.
* @param octeon_dev - pointer to the octeon device structure.
@@ -821,6 +826,7 @@ int octeon_deregister_device(struct octeon_device *oct)
return refcount;
}
+EXPORT_SYMBOL_GPL(octeon_deregister_device);
int
octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs)
@@ -853,12 +859,14 @@ octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_allocate_ioq_vector);
void
octeon_free_ioq_vector(struct octeon_device *oct)
{
vfree(oct->ioq_vector);
}
+EXPORT_SYMBOL_GPL(octeon_free_ioq_vector);
/* this function is only for setting up the first queue */
int octeon_setup_instr_queues(struct octeon_device *oct)
@@ -904,6 +912,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
oct->num_iqs++;
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_instr_queues);
int octeon_setup_output_queues(struct octeon_device *oct)
{
@@ -940,6 +949,7 @@ int octeon_setup_output_queues(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_output_queues);
int octeon_set_io_queues_off(struct octeon_device *oct)
{
@@ -989,6 +999,7 @@ int octeon_set_io_queues_off(struct octeon_device *oct)
}
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_set_io_queues_off);
void octeon_set_droq_pkt_op(struct octeon_device *oct,
u32 q_no,
@@ -1027,6 +1038,7 @@ int octeon_init_dispatch_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_init_dispatch_list);
void octeon_delete_dispatch_list(struct octeon_device *oct)
{
@@ -1058,6 +1070,7 @@ void octeon_delete_dispatch_list(struct octeon_device *oct)
kfree(temp);
}
}
+EXPORT_SYMBOL_GPL(octeon_delete_dispatch_list);
octeon_dispatch_fn_t
octeon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode,
@@ -1180,6 +1193,7 @@ octeon_register_dispatch_fn(struct octeon_device *oct,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_register_dispatch_fn);
int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
{
@@ -1262,6 +1276,7 @@ core_drv_init_err:
octeon_free_recv_info(recv_info);
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_core_drv_init);
int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
@@ -1272,6 +1287,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no)
return -1;
}
+EXPORT_SYMBOL_GPL(octeon_get_tx_qsize);
int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
{
@@ -1280,6 +1296,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
return oct->droq[q_no]->max_count;
return -1;
}
+EXPORT_SYMBOL_GPL(octeon_get_rx_qsize);
/* Retruns the host firmware handshake OCTEON specific configuration */
struct octeon_config *octeon_get_conf(struct octeon_device *oct)
@@ -1302,6 +1319,7 @@ struct octeon_config *octeon_get_conf(struct octeon_device *oct)
}
return default_oct_conf;
}
+EXPORT_SYMBOL_GPL(octeon_get_conf);
/* scratch register address is same in all the OCT-II and CN70XX models */
#define CNXX_SLI_SCRATCH1 0x3C0
@@ -1318,6 +1336,7 @@ struct octeon_device *lio_get_device(u32 octeon_id)
else
return octeon_device[octeon_id];
}
+EXPORT_SYMBOL_GPL(lio_get_device);
u64 lio_pci_readq(struct octeon_device *oct, u64 addr)
{
@@ -1349,6 +1368,7 @@ u64 lio_pci_readq(struct octeon_device *oct, u64 addr)
return val64;
}
+EXPORT_SYMBOL_GPL(lio_pci_readq);
void lio_pci_writeq(struct octeon_device *oct,
u64 val,
@@ -1369,6 +1389,7 @@ void lio_pci_writeq(struct octeon_device *oct,
spin_unlock_irqrestore(&oct->pci_win_lock, flags);
}
+EXPORT_SYMBOL_GPL(lio_pci_writeq);
int octeon_mem_access_ok(struct octeon_device *oct)
{
@@ -1388,6 +1409,7 @@ int octeon_mem_access_ok(struct octeon_device *oct)
return access_okay ? 0 : 1;
}
+EXPORT_SYMBOL_GPL(octeon_mem_access_ok);
int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
{
@@ -1408,6 +1430,7 @@ int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout)
return ret;
}
+EXPORT_SYMBOL_GPL(octeon_wait_for_ddr_init);
/* Get the octeon id assigned to the octeon device passed as argument.
* This function is exported to other modules.
@@ -1462,3 +1485,4 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
}
}
}
+EXPORT_SYMBOL_GPL(lio_enable_irq);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
index d4080bddcb6b..0d6ee30affb9 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
@@ -107,6 +107,7 @@ u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq)
return last_count;
}
+EXPORT_SYMBOL_GPL(octeon_droq_check_hw_for_pkts);
static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq)
{
@@ -216,6 +217,7 @@ int octeon_delete_droq(struct octeon_device *oct, u32 q_no)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_delete_droq);
int octeon_init_droq(struct octeon_device *oct,
u32 q_no,
@@ -773,6 +775,7 @@ octeon_droq_process_packets(struct octeon_device *oct,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_droq_process_packets);
/*
* Utility function to poll for packets. check_hw_for_packets must be
@@ -921,6 +924,7 @@ int octeon_unregister_droq_ops(struct octeon_device *oct, u32 q_no)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_unregister_droq_ops);
int octeon_create_droq(struct octeon_device *oct,
u32 q_no, u32 num_descs,
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
index 7ccab36143c1..d70132437af3 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
@@ -164,6 +164,7 @@ octeon_pci_read_core_mem(struct octeon_device *oct,
{
__octeon_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
}
+EXPORT_SYMBOL_GPL(octeon_pci_read_core_mem);
void
octeon_pci_write_core_mem(struct octeon_device *oct,
@@ -173,6 +174,7 @@ octeon_pci_write_core_mem(struct octeon_device *oct,
{
__octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)buf, len, 0);
}
+EXPORT_SYMBOL_GPL(octeon_pci_write_core_mem);
u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr)
{
@@ -182,6 +184,7 @@ u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr)
return be64_to_cpu(ret);
}
+EXPORT_SYMBOL_GPL(octeon_read_device_mem64);
u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr)
{
@@ -191,6 +194,7 @@ u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr)
return be32_to_cpu(ret);
}
+EXPORT_SYMBOL_GPL(octeon_read_device_mem32);
void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr,
u32 val)
@@ -199,3 +203,4 @@ void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr,
__octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&t, 4, 0);
}
+EXPORT_SYMBOL_GPL(octeon_write_device_mem32);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
index 1a706f81bbb0..dee56ea740e7 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
@@ -79,6 +79,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
return sc;
}
+EXPORT_SYMBOL_GPL(octeon_alloc_soft_command_resp);
int octnet_send_nic_data_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata,
@@ -90,6 +91,7 @@ int octnet_send_nic_data_pkt(struct octeon_device *oct,
ndata->buf, ndata->datasize,
ndata->reqtype);
}
+EXPORT_SYMBOL_GPL(octnet_send_nic_data_pkt);
static inline struct octeon_soft_command
*octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct,
@@ -196,3 +198,4 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
return retval;
}
+EXPORT_SYMBOL_GPL(octnet_send_nic_ctrl_pkt);
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 32f854c0cd79..de8a6ce86ad7 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -185,6 +185,7 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
}
return 1;
}
+EXPORT_SYMBOL_GPL(octeon_delete_instr_queue);
/* Return 0 on success, 1 on failure */
int octeon_setup_iq(struct octeon_device *oct,
@@ -258,6 +259,7 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct)
return instr_cnt;
}
+EXPORT_SYMBOL_GPL(lio_wait_for_instr_fetch);
static inline void
ring_doorbell(struct octeon_device *oct, struct octeon_instr_queue *iq)
@@ -282,6 +284,7 @@ octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no)
ring_doorbell(oct, iq);
spin_unlock(&iq->post_lock);
}
+EXPORT_SYMBOL_GPL(octeon_ring_doorbell_locked);
static inline void __copy_cmd_into_iq(struct octeon_instr_queue *iq,
u8 *cmd)
@@ -345,6 +348,7 @@ octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype,
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_register_reqtype_free_fn);
static inline void
__add_to_request_list(struct octeon_instr_queue *iq,
@@ -430,6 +434,7 @@ lio_process_iq_request_list(struct octeon_device *oct,
return inst_count;
}
+EXPORT_SYMBOL_GPL(lio_process_iq_request_list);
/* Can only be called from process context */
int
@@ -566,6 +571,7 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no,
return st.status;
}
+EXPORT_SYMBOL_GPL(octeon_send_command);
void
octeon_prepare_soft_command(struct octeon_device *oct,
@@ -673,6 +679,7 @@ octeon_prepare_soft_command(struct octeon_device *oct,
}
}
}
+EXPORT_SYMBOL_GPL(octeon_prepare_soft_command);
int octeon_send_soft_command(struct octeon_device *oct,
struct octeon_soft_command *sc)
@@ -726,6 +733,7 @@ int octeon_send_soft_command(struct octeon_device *oct,
return (octeon_send_command(oct, sc->iq_no, 1, &sc->cmd, sc,
len, REQTYPE_SOFT_COMMAND));
}
+EXPORT_SYMBOL_GPL(octeon_send_soft_command);
int octeon_setup_sc_buffer_pool(struct octeon_device *oct)
{
@@ -755,6 +763,7 @@ int octeon_setup_sc_buffer_pool(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_setup_sc_buffer_pool);
int octeon_free_sc_done_list(struct octeon_device *oct)
{
@@ -794,6 +803,7 @@ int octeon_free_sc_done_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_done_list);
int octeon_free_sc_zombie_list(struct octeon_device *oct)
{
@@ -818,6 +828,7 @@ int octeon_free_sc_zombie_list(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_zombie_list);
int octeon_free_sc_buffer_pool(struct octeon_device *oct)
{
@@ -842,6 +853,7 @@ int octeon_free_sc_buffer_pool(struct octeon_device *oct)
return 0;
}
+EXPORT_SYMBOL_GPL(octeon_free_sc_buffer_pool);
struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct,
u32 datasize,
@@ -913,6 +925,7 @@ struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct,
return sc;
}
+EXPORT_SYMBOL_GPL(octeon_alloc_soft_command);
void octeon_free_soft_command(struct octeon_device *oct,
struct octeon_soft_command *sc)
@@ -925,3 +938,4 @@ void octeon_free_soft_command(struct octeon_device *oct,
spin_unlock_bh(&oct->sc_buf_pool.lock);
}
+EXPORT_SYMBOL_GPL(octeon_free_soft_command);
diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c
index ac7747ccf56a..861050966e18 100644
--- a/drivers/net/ethernet/cavium/liquidio/response_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c
@@ -52,12 +52,14 @@ int octeon_setup_response_list(struct octeon_device *oct)
return ret;
}
+EXPORT_SYMBOL_GPL(octeon_setup_response_list);
void octeon_delete_response_list(struct octeon_device *oct)
{
cancel_delayed_work_sync(&oct->dma_comp_wq.wk.work);
destroy_workqueue(oct->dma_comp_wq.wq);
}
+EXPORT_SYMBOL_GPL(octeon_delete_response_list);
int lio_process_ordered_list(struct octeon_device *octeon_dev,
u32 force_quit)
@@ -219,6 +221,7 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev,
return 0;
}
+EXPORT_SYMBOL_GPL(lio_process_ordered_list);
static void oct_poll_req_completion(struct work_struct *work)
{
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 7eb2ddbe9bad..a317feb8decb 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1126,8 +1126,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
}
poll:
- lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ lmac->check_link = alloc_ordered_workqueue("check_link", WQ_MEM_RECLAIM);
if (!lmac->check_link)
return -ENOMEM;
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index efa7f401529e..2e9a74fe0970 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -2184,9 +2184,8 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
len -= offset;
rx_frag += nr_frags;
- __skb_frag_set_page(rx_frag, sd->pg_chunk.page);
- skb_frag_off_set(rx_frag, sd->pg_chunk.offset + offset);
- skb_frag_size_set(rx_frag, len);
+ skb_frag_fill_page_desc(rx_frag, sd->pg_chunk.page,
+ sd->pg_chunk.offset + offset, len);
skb->len += len;
skb->data_len += len;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f0bc7396ce2b..2eb33a727bba 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1175,7 +1175,7 @@ static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
txq = netdev_pick_tx(dev, skb, sb_dev);
if (xfrm_offload(skb) || is_ptp_enabled(skb, dev) ||
skb->encapsulation ||
- cxgb4_is_ktls_skb(skb) ||
+ tls_is_skb_tx_device_offloaded(skb) ||
(proto != IPPROTO_TCP && proto != IPPROTO_UDP))
txq = txq % pi->nqsets;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 34546f5312ee..a9599ba26975 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -497,11 +497,6 @@ struct cxgb4_uld_info {
#endif
};
-static inline bool cxgb4_is_ktls_skb(struct sk_buff *skb)
-{
- return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk);
-}
-
void cxgb4_uld_enable(struct adapter *adap);
void cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
int cxgb4_unregister_uld(enum cxgb4_uld type);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 46809e2d94ee..98dd78551d89 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1530,7 +1530,7 @@ static netdev_tx_t cxgb4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
#endif /* CHELSIO_IPSEC_INLINE */
#if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
- if (cxgb4_is_ktls_skb(skb) &&
+ if (tls_is_skb_tx_device_offloaded(skb) &&
(skb->len - skb_tcp_all_headers(skb)))
return adap->uld[CXGB4_ULD_KTLS].tx_handler(skb, dev);
#endif /* CHELSIO_TLS_DEVICE */
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
index 1a5fdd755e9e..bcdc7fc2f427 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
@@ -1946,7 +1946,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
tls_ctx = tls_get_ctx(skb->sk);
tls_netdev = rcu_dereference_bh(tls_ctx->netdev);
/* Don't quit on NULL: if tls_device_down is running in parallel,
- * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was
+ * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was
* true. Rather continue processing this packet.
*/
if (unlikely(tls_netdev && tls_netdev != dev))
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
index 41714203ace8..68562a82d036 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h
@@ -568,8 +568,7 @@ void chtls_destroy_sock(struct sock *sk);
int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
int chtls_recvmsg(struct sock *sk, struct msghdr *msg,
size_t len, int flags, int *addr_len);
-int chtls_sendpage(struct sock *sk, struct page *page,
- int offset, size_t size, int flags);
+void chtls_splice_eof(struct socket *sock);
int send_tx_flowc_wr(struct sock *sk, int compl,
u32 snd_nxt, u32 rcv_nxt);
void chtls_tcp_push(struct sock *sk, int flags);
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
index c2e7037c7ba1..7750702900fa 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c
@@ -1466,7 +1466,7 @@ static void make_established(struct sock *sk, u32 snd_isn, unsigned int opt)
tp->write_seq = snd_isn;
tp->snd_nxt = snd_isn;
tp->snd_una = snd_isn;
- inet_sk(sk)->inet_id = get_random_u16();
+ atomic_set(&inet_sk(sk)->inet_id, get_random_u16());
assign_rxopt(sk, opt);
if (tp->rcv_wnd > (RCV_BUFSIZ_M << 10))
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
index ae6b17b96bf1..5fc64e47568a 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
@@ -1092,7 +1092,17 @@ new_buf:
if (copy > size)
copy = size;
- if (skb_tailroom(skb) > 0) {
+ if (msg->msg_flags & MSG_SPLICE_PAGES) {
+ err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
+ sk->sk_allocation);
+ if (err < 0) {
+ if (err == -EMSGSIZE)
+ goto new_buf;
+ goto do_fault;
+ }
+ copy = err;
+ sk_wmem_queued_add(sk, copy);
+ } else if (skb_tailroom(skb) > 0) {
copy = min(copy, skb_tailroom(skb));
if (is_tls_tx(csk))
copy = min_t(int, copy, csk->tlshws.txleft);
@@ -1227,113 +1237,13 @@ out_err:
goto done;
}
-int chtls_sendpage(struct sock *sk, struct page *page,
- int offset, size_t size, int flags)
+void chtls_splice_eof(struct socket *sock)
{
- struct chtls_sock *csk;
- struct chtls_dev *cdev;
- int mss, err, copied;
- struct tcp_sock *tp;
- long timeo;
+ struct sock *sk = sock->sk;
- tp = tcp_sk(sk);
- copied = 0;
- csk = rcu_dereference_sk_user_data(sk);
- cdev = csk->cdev;
lock_sock(sk);
- timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
-
- err = sk_stream_wait_connect(sk, &timeo);
- if (!sk_in_state(sk, TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
- err != 0)
- goto out_err;
-
- mss = csk->mss;
- csk_set_flag(csk, CSK_TX_MORE_DATA);
-
- while (size > 0) {
- struct sk_buff *skb = skb_peek_tail(&csk->txq);
- int copy, i;
-
- if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) ||
- (copy = mss - skb->len) <= 0) {
-new_buf:
- if (!csk_mem_free(cdev, sk))
- goto wait_for_sndbuf;
-
- if (is_tls_tx(csk)) {
- skb = get_record_skb(sk,
- select_size(sk, size,
- flags,
- TX_TLSHDR_LEN),
- true);
- } else {
- skb = get_tx_skb(sk, 0);
- }
- if (!skb)
- goto wait_for_memory;
- copy = mss;
- }
- if (copy > size)
- copy = size;
-
- i = skb_shinfo(skb)->nr_frags;
- if (skb_can_coalesce(skb, i, page, offset)) {
- skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
- } else if (i < MAX_SKB_FRAGS) {
- get_page(page);
- skb_fill_page_desc(skb, i, page, offset, copy);
- } else {
- tx_skb_finalize(skb);
- push_frames_if_head(sk);
- goto new_buf;
- }
-
- skb->len += copy;
- if (skb->len == mss)
- tx_skb_finalize(skb);
- skb->data_len += copy;
- skb->truesize += copy;
- sk->sk_wmem_queued += copy;
- tp->write_seq += copy;
- copied += copy;
- offset += copy;
- size -= copy;
-
- if (corked(tp, flags) &&
- (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)))
- ULP_SKB_CB(skb)->flags |= ULPCB_FLAG_NO_APPEND;
-
- if (!size)
- break;
-
- if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND))
- push_frames_if_head(sk);
- continue;
-wait_for_sndbuf:
- set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
-wait_for_memory:
- err = csk_wait_memory(cdev, sk, &timeo);
- if (err)
- goto do_error;
- }
-out:
- csk_reset_flag(csk, CSK_TX_MORE_DATA);
- if (copied)
- chtls_tcp_push(sk, flags);
-done:
+ chtls_tcp_push(sk, 0);
release_sock(sk);
- return copied;
-
-do_error:
- if (copied)
- goto out;
-
-out_err:
- if (csk_conn_inline(csk))
- csk_reset_flag(csk, CSK_TX_MORE_DATA);
- copied = sk_stream_error(sk, flags, err);
- goto done;
}
static void chtls_select_window(struct sock *sk)
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index 1e55b12fee51..455a54708be4 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -606,7 +606,7 @@ static void __init chtls_init_ulp_ops(void)
chtls_cpl_prot.destroy = chtls_destroy_sock;
chtls_cpl_prot.shutdown = chtls_shutdown;
chtls_cpl_prot.sendmsg = chtls_sendmsg;
- chtls_cpl_prot.sendpage = chtls_sendpage;
+ chtls_cpl_prot.splice_eof = chtls_splice_eof;
chtls_cpl_prot.recvmsg = chtls_recvmsg;
chtls_cpl_prot.setsockopt = chtls_setsockopt;
chtls_cpl_prot.getsockopt = chtls_getsockopt;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 0defd519ba62..0616b5fe241c 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1138,7 +1138,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
(lancer_chip(adapter) || BE3_chip(adapter) ||
skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
ip = (struct iphdr *)ip_hdr(skb);
- pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
+ if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len))))
+ goto tx_drop;
}
/* If vlan tag is already inlined in the packet, skip HW VLAN
@@ -2343,11 +2344,10 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
hdr_len = ETH_HLEN;
memcpy(skb->data, start, hdr_len);
skb_shinfo(skb)->nr_frags = 1;
- skb_frag_set_page(skb, 0, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[0],
- page_info->page_offset + hdr_len);
- skb_frag_size_set(&skb_shinfo(skb)->frags[0],
- curr_frag_len - hdr_len);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[0],
+ page_info->page,
+ page_info->page_offset + hdr_len,
+ curr_frag_len - hdr_len);
skb->data_len = curr_frag_len - hdr_len;
skb->truesize += rx_frag_size;
skb->tail += hdr_len;
@@ -2369,16 +2369,17 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
if (page_info->page_offset == 0) {
/* Fresh page */
j++;
- skb_frag_set_page(skb, j, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[j],
- page_info->page_offset);
- skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j],
+ page_info->page,
+ page_info->page_offset,
+ curr_frag_len);
skb_shinfo(skb)->nr_frags++;
} else {
put_page(page_info->page);
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j],
+ curr_frag_len);
}
- skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
skb->len += curr_frag_len;
skb->data_len += curr_frag_len;
skb->truesize += rx_frag_size;
@@ -2451,14 +2452,16 @@ static void be_rx_compl_process_gro(struct be_rx_obj *rxo,
if (i == 0 || page_info->page_offset == 0) {
/* First frag or Fresh page */
j++;
- skb_frag_set_page(skb, j, page_info->page);
- skb_frag_off_set(&skb_shinfo(skb)->frags[j],
- page_info->page_offset);
- skb_frag_size_set(&skb_shinfo(skb)->frags[j], 0);
+ skb_frag_fill_page_desc(&skb_shinfo(skb)->frags[j],
+ page_info->page,
+ page_info->page_offset,
+ curr_frag_len);
} else {
put_page(page_info->page);
+ skb_frag_size_add(&skb_shinfo(skb)->frags[j],
+ curr_frag_len);
}
- skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
+
skb->truesize += rx_frag_size;
remaining -= curr_frag_len;
memset(page_info, 0, sizeof(*page_info));
diff --git a/drivers/net/ethernet/engleder/tsnep_selftests.c b/drivers/net/ethernet/engleder/tsnep_selftests.c
index 1581d6b22232..8a9145f93147 100644
--- a/drivers/net/ethernet/engleder/tsnep_selftests.c
+++ b/drivers/net/ethernet/engleder/tsnep_selftests.c
@@ -329,7 +329,7 @@ static bool disable_taprio(struct tsnep_adapter *adapter)
int retval;
memset(&qopt, 0, sizeof(qopt));
- qopt.enable = 0;
+ qopt.cmd = TAPRIO_CMD_DESTROY;
retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt);
if (retval)
return false;
@@ -360,7 +360,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 1500000;
qopt->cycle_time_extension = 0;
@@ -382,7 +382,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 411854;
qopt->cycle_time_extension = 0;
@@ -406,7 +406,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter)
if (!run_taprio(adapter, qopt, 100))
goto failed;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
delay_base_time(adapter, qopt, 12);
qopt->cycle_time = 125000;
@@ -457,7 +457,7 @@ static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 0;
@@ -610,7 +610,7 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
for (i = 0; i < 255; i++)
qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES;
- qopt->enable = 1;
+ qopt->cmd = TAPRIO_CMD_REPLACE;
qopt->base_time = ktime_set(0, 0);
qopt->cycle_time = 100000;
qopt->cycle_time_extension = 50000;
diff --git a/drivers/net/ethernet/engleder/tsnep_tc.c b/drivers/net/ethernet/engleder/tsnep_tc.c
index d083e6684f12..745b191a5540 100644
--- a/drivers/net/ethernet/engleder/tsnep_tc.c
+++ b/drivers/net/ethernet/engleder/tsnep_tc.c
@@ -325,7 +325,7 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
if (!adapter->gate_control)
return -EOPNOTSUPP;
- if (!qopt->enable) {
+ if (qopt->cmd == TAPRIO_CMD_DESTROY) {
/* disable gate control if active */
mutex_lock(&adapter->gate_control_lock);
@@ -337,6 +337,8 @@ static int tsnep_taprio(struct tsnep_adapter *adapter,
mutex_unlock(&adapter->gate_control_lock);
return 0;
+ } else if (qopt->cmd != TAPRIO_CMD_REPLACE) {
+ return -EOPNOTSUPP;
}
retval = tsnep_validate_gcl(qopt);
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 1c78f66a89da..75401d2a5fb4 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -29,7 +29,7 @@ config FEC
select CRC32
select PHYLIB
select PAGE_POOL
- select PAGE_POOL_STATS
+ imply PAGE_POOL_STATS
imply NET_SELFTESTS
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index a62cffaf6ff1..a9676d0dece8 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -5025,7 +5025,7 @@ err_wq_alloc:
return err;
}
-static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
+static void dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
{
struct device *dev;
struct net_device *net_dev;
@@ -5073,8 +5073,6 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
free_netdev(net_dev);
-
- return 0;
}
static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 00e50bd30189..a69bb22c37ea 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -252,8 +252,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
struct fwnode_handle *dpmac_node,
int id)
{
- struct mdio_device *mdiodev;
struct fwnode_handle *node;
+ struct phylink_pcs *pcs;
node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
if (IS_ERR(node)) {
@@ -262,26 +262,27 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac,
return 0;
}
- if (!fwnode_device_is_available(node)) {
- netdev_err(mac->net_dev, "pcs-handle node not available\n");
- fwnode_handle_put(node);
- return -ENODEV;
- }
-
- mdiodev = fwnode_mdio_find_device(node);
+ pcs = lynx_pcs_create_fwnode(node);
fwnode_handle_put(node);
- if (!mdiodev) {
+
+ if (pcs == ERR_PTR(-EPROBE_DEFER)) {
netdev_dbg(mac->net_dev, "missing PCS device\n");
return -EPROBE_DEFER;
}
- mac->pcs = lynx_pcs_create(mdiodev);
- if (!mac->pcs) {
- netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
- put_device(&mdiodev->dev);
- return -ENOMEM;
+ if (pcs == ERR_PTR(-ENODEV)) {
+ netdev_err(mac->net_dev, "pcs-handle node not available\n");
+ return PTR_ERR(pcs);
+ }
+
+ if (IS_ERR(pcs)) {
+ netdev_err(mac->net_dev,
+ "lynx_pcs_create_fwnode() failed: %pe\n", pcs);
+ return PTR_ERR(pcs);
}
+ mac->pcs = pcs;
+
return 0;
}
@@ -290,11 +291,7 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
struct phylink_pcs *phylink_pcs = mac->pcs;
if (phylink_pcs) {
- struct mdio_device *mdio = lynx_get_mdio_device(phylink_pcs);
- struct device *dev = &mdio->dev;
-
lynx_pcs_destroy(phylink_pcs);
- put_device(dev);
mac->pcs = NULL;
}
}
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
index 90d23ab1ce9d..4497e3c0456d 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
@@ -219,7 +219,7 @@ err_exit:
return err;
}
-static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
+static void dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
{
struct device *dev = &mc_dev->dev;
struct ptp_qoriq *ptp_qoriq;
@@ -232,8 +232,6 @@ static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
fsl_mc_free_irqs(mc_dev);
dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
fsl_mc_portal_free(mc_dev->mc_io);
-
- return 0;
}
static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index f4ae4289c41a..21cc4e52425a 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -3221,7 +3221,7 @@ static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev)
dev_warn(dev, "dpsw_close err %d\n", err);
}
-static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
+static void dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
{
struct ethsw_port_priv *port_priv;
struct ethsw_core *ethsw;
@@ -3252,8 +3252,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
kfree(ethsw);
dev_set_drvdata(dev, NULL);
-
- return 0;
}
static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 9e1b2536e9a9..35461165de0d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1451,9 +1451,8 @@ static void enetc_add_rx_buff_to_xdp(struct enetc_bdr *rx_ring, int i,
xdp_buff_set_frag_pfmemalloc(xdp_buff);
frag = &shinfo->frags[shinfo->nr_frags];
- skb_frag_off_set(frag, rx_swbd->page_offset);
- skb_frag_size_set(frag, size);
- __skb_frag_set_page(frag, rx_swbd->page);
+ skb_frag_fill_page_desc(frag, rx_swbd->page, rx_swbd->page_offset,
+ size);
shinfo->nr_frags++;
}
@@ -1790,7 +1789,7 @@ static int enetc_alloc_tx_resource(struct enetc_bdr_resource *res,
res->bd_count = bd_count;
res->bd_size = sizeof(union enetc_tx_bd);
- res->tx_swbd = vzalloc(bd_count * sizeof(*res->tx_swbd));
+ res->tx_swbd = vcalloc(bd_count, sizeof(*res->tx_swbd));
if (!res->tx_swbd)
return -ENOMEM;
@@ -1878,7 +1877,7 @@ static int enetc_alloc_rx_resource(struct enetc_bdr_resource *res,
if (extended)
res->bd_size *= 2;
- res->rx_swbd = vzalloc(bd_count * sizeof(struct enetc_rx_swbd));
+ res->rx_swbd = vcalloc(bd_count, sizeof(struct enetc_rx_swbd));
if (!res->rx_swbd)
return -ENOMEM;
@@ -2639,7 +2638,7 @@ static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv)
priv->tx_ring[i]->prio);
}
-static void enetc_reset_tc_mqprio(struct net_device *ndev)
+void enetc_reset_tc_mqprio(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
@@ -2664,6 +2663,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev)
enetc_change_preemptible_tcs(priv, 0);
}
+EXPORT_SYMBOL_GPL(enetc_reset_tc_mqprio);
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
{
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index c97a8e3d7a7f..8577cf7699a0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -429,6 +429,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev);
void enetc_set_features(struct net_device *ndev, netdev_features_t features);
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data);
+void enetc_reset_tc_mqprio(struct net_device *ndev);
int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
struct xdp_frame **frames, u32 flags);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 7cd22d370caa..c153dc083aff 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -863,7 +863,6 @@ static int enetc_imdio_create(struct enetc_pf *pf)
struct device *dev = &pf->si->pdev->dev;
struct enetc_mdio_priv *mdio_priv;
struct phylink_pcs *phylink_pcs;
- struct mdio_device *mdio_device;
struct mii_bus *bus;
int err;
@@ -889,17 +888,9 @@ static int enetc_imdio_create(struct enetc_pf *pf)
goto free_mdio_bus;
}
- mdio_device = mdio_device_create(bus, 0);
- if (IS_ERR(mdio_device)) {
- err = PTR_ERR(mdio_device);
- dev_err(dev, "cannot create mdio device (%d)\n", err);
- goto unregister_mdiobus;
- }
-
- phylink_pcs = lynx_pcs_create(mdio_device);
- if (!phylink_pcs) {
- mdio_device_free(mdio_device);
- err = -ENOMEM;
+ phylink_pcs = lynx_pcs_create_mdiodev(bus, 0);
+ if (IS_ERR(phylink_pcs)) {
+ err = PTR_ERR(phylink_pcs);
dev_err(dev, "cannot create lynx pcs (%d)\n", err);
goto unregister_mdiobus;
}
@@ -918,13 +909,8 @@ free_mdio_bus:
static void enetc_imdio_remove(struct enetc_pf *pf)
{
- struct mdio_device *mdio_device;
-
- if (pf->pcs) {
- mdio_device = lynx_get_mdio_device(pf->pcs);
- mdio_device_free(mdio_device);
+ if (pf->pcs)
lynx_pcs_destroy(pf->pcs);
- }
if (pf->imdio) {
mdiobus_unregister(pf->imdio);
mdiobus_free(pf->imdio);
@@ -1200,14 +1186,9 @@ static int enetc_init_port_rss_memory(struct enetc_si *si)
static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
{
- struct device_node *node = pdev->dev.of_node;
struct platform_device *ierb_pdev;
struct device_node *ierb_node;
- /* Don't register with the IERB if the PF itself is disabled */
- if (!node || !of_device_is_available(node))
- return 0;
-
ierb_node = of_find_compatible_node(NULL, NULL,
"fsl,ls1028a-enetc-ierb");
if (!ierb_node || !of_device_is_available(ierb_node))
@@ -1222,56 +1203,81 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
return enetc_ierb_register_pf(ierb_pdev, pdev);
}
-static int enetc_pf_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
{
- struct device_node *node = pdev->dev.of_node;
- struct enetc_ndev_priv *priv;
- struct net_device *ndev;
struct enetc_si *si;
- struct enetc_pf *pf;
int err;
- err = enetc_pf_register_with_ierb(pdev);
- if (err == -EPROBE_DEFER)
- return err;
- if (err)
- dev_warn(&pdev->dev,
- "Could not register with IERB driver: %pe, please update the device tree\n",
- ERR_PTR(err));
-
- err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
- if (err)
- return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+ err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf));
+ if (err) {
+ dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
+ goto out;
+ }
si = pci_get_drvdata(pdev);
if (!si->hw.port || !si->hw.global) {
err = -ENODEV;
dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
- goto err_map_pf_space;
+ goto out_pci_remove;
}
err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
&si->cbd_ring);
if (err)
- goto err_setup_cbdr;
+ goto out_pci_remove;
err = enetc_init_port_rfs_memory(si);
if (err) {
dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
- goto err_init_port_rfs;
+ goto out_teardown_cbdr;
}
err = enetc_init_port_rss_memory(si);
if (err) {
dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
- goto err_init_port_rss;
+ goto out_teardown_cbdr;
}
- if (node && !of_device_is_available(node)) {
- dev_info(&pdev->dev, "device is disabled, skipping\n");
- err = -ENODEV;
- goto err_device_disabled;
+ return si;
+
+out_teardown_cbdr:
+ enetc_teardown_cbdr(&si->cbd_ring);
+out_pci_remove:
+ enetc_pci_remove(pdev);
+out:
+ return ERR_PTR(err);
+}
+
+static void enetc_psi_destroy(struct pci_dev *pdev)
+{
+ struct enetc_si *si = pci_get_drvdata(pdev);
+
+ enetc_teardown_cbdr(&si->cbd_ring);
+ enetc_pci_remove(pdev);
+}
+
+static int enetc_pf_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct enetc_ndev_priv *priv;
+ struct net_device *ndev;
+ struct enetc_si *si;
+ struct enetc_pf *pf;
+ int err;
+
+ err = enetc_pf_register_with_ierb(pdev);
+ if (err == -EPROBE_DEFER)
+ return err;
+ if (err)
+ dev_warn(&pdev->dev,
+ "Could not register with IERB driver: %pe, please update the device tree\n",
+ ERR_PTR(err));
+
+ si = enetc_psi_create(pdev);
+ if (IS_ERR(si)) {
+ err = PTR_ERR(si);
+ goto err_psi_create;
}
pf = enetc_si_priv(si);
@@ -1353,15 +1359,9 @@ err_alloc_si_res:
si->ndev = NULL;
free_netdev(ndev);
err_alloc_netdev:
-err_init_port_rss:
-err_init_port_rfs:
-err_device_disabled:
err_setup_mac_addresses:
- enetc_teardown_cbdr(&si->cbd_ring);
-err_setup_cbdr:
-err_map_pf_space:
- enetc_pci_remove(pdev);
-
+ enetc_psi_destroy(pdev);
+err_psi_create:
return err;
}
@@ -1384,12 +1384,29 @@ static void enetc_pf_remove(struct pci_dev *pdev)
enetc_free_msix(priv);
enetc_free_si_resources(priv);
- enetc_teardown_cbdr(&si->cbd_ring);
free_netdev(si->ndev);
- enetc_pci_remove(pdev);
+ enetc_psi_destroy(pdev);
+}
+
+static void enetc_fixup_clear_rss_rfs(struct pci_dev *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct enetc_si *si;
+
+ /* Only apply quirk for disabled functions. For the ones
+ * that are enabled, enetc_pf_probe() will apply it.
+ */
+ if (node && of_device_is_available(node))
+ return;
+
+ si = enetc_psi_create(pdev);
+ if (!IS_ERR(si))
+ enetc_psi_destroy(pdev);
}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF,
+ enetc_fixup_clear_rss_rfs);
static const struct pci_device_id enetc_pf_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
index 17c097cef7d4..5243fc031058 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
@@ -8,7 +8,7 @@
#include "enetc.h"
int enetc_phc_index = -1;
-EXPORT_SYMBOL(enetc_phc_index);
+EXPORT_SYMBOL_GPL(enetc_phc_index);
static struct ptp_clock_info enetc_ptp_caps = {
.owner = THIS_MODULE,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
index 126007ab70f6..270cbd5e8684 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c
@@ -43,10 +43,9 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed)
enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed);
}
-static int enetc_setup_taprio(struct net_device *ndev,
+static int enetc_setup_taprio(struct enetc_ndev_priv *priv,
struct tc_taprio_qopt_offload *admin_conf)
{
- struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
struct enetc_cbd cbd = {.cmd = 0};
struct tgs_gcl_conf *gcl_config;
@@ -60,19 +59,13 @@ static int enetc_setup_taprio(struct net_device *ndev,
int err;
int i;
+ /* TSD and Qbv are mutually exclusive in hardware */
+ for (i = 0; i < priv->num_tx_rings; i++)
+ if (priv->tx_ring[i]->tsd_enable)
+ return -EBUSY;
+
if (admin_conf->num_entries > enetc_get_max_gcl_len(hw))
return -EINVAL;
- gcl_len = admin_conf->num_entries;
-
- tge = enetc_rd(hw, ENETC_PTGCR);
- if (!admin_conf->enable) {
- enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE);
- enetc_reset_ptcmsdur(hw);
-
- priv->active_offloads &= ~ENETC_F_QBV;
-
- return 0;
- }
if (admin_conf->cycle_time > U32_MAX ||
admin_conf->cycle_time_extension > U32_MAX)
@@ -82,6 +75,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
* control BD descriptor.
*/
gcl_config = &cbd.gcl_conf;
+ gcl_len = admin_conf->num_entries;
data_size = struct_size(gcl_data, entry, gcl_len);
tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size,
@@ -115,6 +109,7 @@ static int enetc_setup_taprio(struct net_device *ndev,
cbd.cls = BDCR_CMD_PORT_GCL;
cbd.status_flags = 0;
+ tge = enetc_rd(hw, ENETC_PTGCR);
enetc_wr(hw, ENETC_PTGCR, tge | ENETC_PTGCR_TGE);
err = enetc_send_cmd(priv->si, &cbd);
@@ -132,25 +127,95 @@ static int enetc_setup_taprio(struct net_device *ndev,
return 0;
}
-int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
+static void enetc_reset_taprio_stats(struct enetc_ndev_priv *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_tx_rings; i++)
+ priv->tx_ring[i]->stats.win_drop = 0;
+}
+
+static void enetc_reset_taprio(struct enetc_ndev_priv *priv)
+{
+ struct enetc_hw *hw = &priv->si->hw;
+ u32 val;
+
+ val = enetc_rd(hw, ENETC_PTGCR);
+ enetc_wr(hw, ENETC_PTGCR, val & ~ENETC_PTGCR_TGE);
+ enetc_reset_ptcmsdur(hw);
+
+ priv->active_offloads &= ~ENETC_F_QBV;
+}
+
+static void enetc_taprio_destroy(struct net_device *ndev)
{
- struct tc_taprio_qopt_offload *taprio = type_data;
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- int err, i;
- /* TSD and Qbv are mutually exclusive in hardware */
+ enetc_reset_taprio(priv);
+ enetc_reset_tc_mqprio(ndev);
+ enetc_reset_taprio_stats(priv);
+}
+
+static void enetc_taprio_stats(struct net_device *ndev,
+ struct tc_taprio_qopt_stats *stats)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ u64 window_drops = 0;
+ int i;
+
for (i = 0; i < priv->num_tx_rings; i++)
- if (priv->tx_ring[i]->tsd_enable)
- return -EBUSY;
+ window_drops += priv->tx_ring[i]->stats.win_drop;
+
+ stats->window_drops = window_drops;
+}
+
+static void enetc_taprio_queue_stats(struct net_device *ndev,
+ struct tc_taprio_qopt_queue_stats *queue_stats)
+{
+ struct tc_taprio_qopt_stats *stats = &queue_stats->stats;
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int queue = queue_stats->queue;
- err = enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
+ stats->window_drops = priv->tx_ring[queue]->stats.win_drop;
+}
+
+static int enetc_taprio_replace(struct net_device *ndev,
+ struct tc_taprio_qopt_offload *offload)
+{
+ struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ int err;
+
+ err = enetc_setup_tc_mqprio(ndev, &offload->mqprio);
if (err)
return err;
- err = enetc_setup_taprio(ndev, taprio);
- if (err) {
- taprio->mqprio.qopt.num_tc = 0;
- enetc_setup_tc_mqprio(ndev, &taprio->mqprio);
+ err = enetc_setup_taprio(priv, offload);
+ if (err)
+ enetc_reset_tc_mqprio(ndev);
+
+ return err;
+}
+
+int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data)
+{
+ struct tc_taprio_qopt_offload *offload = type_data;
+ int err = 0;
+
+ switch (offload->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ err = enetc_taprio_replace(ndev, offload);
+ break;
+ case TAPRIO_CMD_DESTROY:
+ enetc_taprio_destroy(ndev);
+ break;
+ case TAPRIO_CMD_STATS:
+ enetc_taprio_stats(ndev, &offload->stats);
+ break;
+ case TAPRIO_CMD_QUEUE_STATS:
+ enetc_taprio_queue_stats(ndev, &offload->queue_stats);
+ break;
+ default:
+ err = -EOPNOTSUPP;
}
return err;
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 9939ccafb556..63a053dea819 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -355,7 +355,7 @@ struct bufdesc_ex {
#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
#define FEC_ENET_TX_FRSIZE 2048
#define FEC_ENET_TX_FRPPG (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE 512 /* Must be power of two */
+#define TX_RING_SIZE 1024 /* Must be power of two */
#define TX_RING_MOD_MASK 511 /* for this to work */
#define BD_ENET_RX_INT 0x00800000
@@ -544,10 +544,23 @@ enum {
XDP_STATS_TOTAL,
};
+enum fec_txbuf_type {
+ FEC_TXBUF_T_SKB,
+ FEC_TXBUF_T_XDP_NDO,
+};
+
+struct fec_tx_buffer {
+ union {
+ struct sk_buff *skb;
+ struct xdp_frame *xdp;
+ };
+ enum fec_txbuf_type type;
+};
+
struct fec_enet_priv_tx_q {
struct bufdesc_prop bd;
unsigned char *tx_bounce[TX_RING_SIZE];
- struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct fec_tx_buffer tx_buf[TX_RING_SIZE];
unsigned short tx_stop_threshold;
unsigned short tx_wake_threshold;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 38e5b5abe067..66b5cbdb43b9 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -397,7 +397,7 @@ static void fec_dump(struct net_device *ndev)
fec16_to_cpu(bdp->cbd_sc),
fec32_to_cpu(bdp->cbd_bufaddr),
fec16_to_cpu(bdp->cbd_datlen),
- txq->tx_skbuff[index]);
+ txq->tx_buf[index].skb);
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
index++;
} while (bdp != txq->bd.base);
@@ -654,7 +654,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
index = fec_enet_get_bd_index(last_bdp, &txq->bd);
/* Save skb pointer */
- txq->tx_skbuff[index] = skb;
+ txq->tx_buf[index].skb = skb;
/* Make sure the updates to rest of the descriptor are performed before
* transferring ownership.
@@ -672,9 +672,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
skb_tx_timestamp(skb);
- /* Make sure the update to bdp and tx_skbuff are performed before
- * txq->bd.cur.
- */
+ /* Make sure the update to bdp is performed before txq->bd.cur. */
wmb();
txq->bd.cur = bdp;
@@ -862,7 +860,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
}
/* Save skb pointer */
- txq->tx_skbuff[index] = skb;
+ txq->tx_buf[index].skb = skb;
skb_tx_timestamp(skb);
txq->bd.cur = bdp;
@@ -952,16 +950,33 @@ static void fec_enet_bd_init(struct net_device *dev)
for (i = 0; i < txq->bd.ring_size; i++) {
/* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = cpu_to_fec16(0);
- if (bdp->cbd_bufaddr &&
- !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
- dma_unmap_single(&fep->pdev->dev,
- fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen),
- DMA_TO_DEVICE);
- if (txq->tx_skbuff[i]) {
- dev_kfree_skb_any(txq->tx_skbuff[i]);
- txq->tx_skbuff[i] = NULL;
+ if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+ if (bdp->cbd_bufaddr &&
+ !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ if (txq->tx_buf[i].skb) {
+ dev_kfree_skb_any(txq->tx_buf[i].skb);
+ txq->tx_buf[i].skb = NULL;
+ }
+ } else {
+ if (bdp->cbd_bufaddr)
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+
+ if (txq->tx_buf[i].xdp) {
+ xdp_return_frame(txq->tx_buf[i].xdp);
+ txq->tx_buf[i].xdp = NULL;
+ }
+
+ /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+ txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
}
+
bdp->cbd_bufaddr = cpu_to_fec32(0);
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
}
@@ -1011,24 +1026,6 @@ static void fec_enet_enable_ring(struct net_device *ndev)
}
}
-static void fec_enet_reset_skb(struct net_device *ndev)
-{
- struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_enet_priv_tx_q *txq;
- int i, j;
-
- for (i = 0; i < fep->num_tx_queues; i++) {
- txq = fep->tx_queue[i];
-
- for (j = 0; j < txq->bd.ring_size; j++) {
- if (txq->tx_skbuff[j]) {
- dev_kfree_skb_any(txq->tx_skbuff[j]);
- txq->tx_skbuff[j] = NULL;
- }
- }
- }
-}
-
/*
* This function is called to start or restart the FEC during a link
* change, transmit timeout, or to reconfigure the FEC. The network
@@ -1071,9 +1068,6 @@ fec_restart(struct net_device *ndev)
fec_enet_enable_ring(ndev);
- /* Reset tx SKB buffers. */
- fec_enet_reset_skb(ndev);
-
/* Enable MII mode */
if (fep->full_duplex == DUPLEX_FULL) {
/* FD enable */
@@ -1378,9 +1372,10 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
}
static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
{
struct fec_enet_private *fep;
+ struct xdp_frame *xdpf;
struct bufdesc *bdp;
unsigned short status;
struct sk_buff *skb;
@@ -1408,16 +1403,39 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
index = fec_enet_get_bd_index(bdp, &txq->bd);
- skb = txq->tx_skbuff[index];
- txq->tx_skbuff[index] = NULL;
- if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
- dma_unmap_single(&fep->pdev->dev,
- fec32_to_cpu(bdp->cbd_bufaddr),
- fec16_to_cpu(bdp->cbd_datlen),
- DMA_TO_DEVICE);
- bdp->cbd_bufaddr = cpu_to_fec32(0);
- if (!skb)
- goto skb_done;
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+ skb = txq->tx_buf[index].skb;
+ txq->tx_buf[index].skb = NULL;
+ if (bdp->cbd_bufaddr &&
+ !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
+ if (!skb)
+ goto tx_buf_done;
+ } else {
+ /* Tx processing cannot call any XDP (or page pool) APIs if
+ * the "budget" is 0. Because NAPI is called with budget of
+ * 0 (such as netpoll) indicates we may be in an IRQ context,
+ * however, we can't use the page pool from IRQ context.
+ */
+ if (unlikely(!budget))
+ break;
+
+ xdpf = txq->tx_buf[index].xdp;
+ if (bdp->cbd_bufaddr)
+ dma_unmap_single(&fep->pdev->dev,
+ fec32_to_cpu(bdp->cbd_bufaddr),
+ fec16_to_cpu(bdp->cbd_datlen),
+ DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = cpu_to_fec32(0);
+ if (!xdpf) {
+ txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+ goto tx_buf_done;
+ }
+ }
/* Check for errors. */
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1436,21 +1454,11 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
ndev->stats.tx_carrier_errors++;
} else {
ndev->stats.tx_packets++;
- ndev->stats.tx_bytes += skb->len;
- }
- /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
- * are to time stamp the packet, so we still need to check time
- * stamping enabled flag.
- */
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
- fep->hwts_tx_en) &&
- fep->bufdesc_ex) {
- struct skb_shared_hwtstamps shhwtstamps;
- struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
-
- fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
- skb_tstamp_tx(skb, &shhwtstamps);
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB)
+ ndev->stats.tx_bytes += skb->len;
+ else
+ ndev->stats.tx_bytes += xdpf->len;
}
/* Deferred means some collisions occurred during transmit,
@@ -1459,10 +1467,32 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
if (status & BD_ENET_TX_DEF)
ndev->stats.collisions++;
- /* Free the sk buffer associated with this last transmit */
- dev_kfree_skb_any(skb);
-skb_done:
- /* Make sure the update to bdp and tx_skbuff are performed
+ if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+ /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
+ * are to time stamp the packet, so we still need to check time
+ * stamping enabled flag.
+ */
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+ fep->hwts_tx_en) && fep->bufdesc_ex) {
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+ fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+
+ /* Free the sk buffer associated with this last transmit */
+ dev_kfree_skb_any(skb);
+ } else {
+ xdp_return_frame(xdpf);
+
+ txq->tx_buf[index].xdp = NULL;
+ /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+ txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+ }
+
+tx_buf_done:
+ /* Make sure the update to bdp and tx_buf are performed
* before dirty_tx
*/
wmb();
@@ -1486,14 +1516,14 @@ skb_done:
writel(0, txq->bd.reg_desc_active);
}
-static void fec_enet_tx(struct net_device *ndev)
+static void fec_enet_tx(struct net_device *ndev, int budget)
{
struct fec_enet_private *fep = netdev_priv(ndev);
int i;
/* Make sure that AVB queues are processed first. */
for (i = fep->num_tx_queues - 1; i >= 0; i--)
- fec_enet_tx_queue(ndev, i);
+ fec_enet_tx_queue(ndev, i, budget);
}
static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
@@ -1836,7 +1866,7 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
do {
done += fec_enet_rx(ndev, budget - done);
- fec_enet_tx(ndev);
+ fec_enet_tx(ndev, budget);
} while ((done < budget) && fec_enet_collect_events(fep));
if (done < budget) {
@@ -2810,6 +2840,7 @@ static void fec_enet_get_xdp_stats(struct fec_enet_private *fep, u64 *data)
static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data)
{
+#ifdef CONFIG_PAGE_POOL_STATS
struct page_pool_stats stats = {};
struct fec_enet_priv_rx_q *rxq;
int i;
@@ -2824,6 +2855,7 @@ static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data)
}
page_pool_ethtool_stats_get(data, &stats);
+#endif
}
static void fec_enet_get_ethtool_stats(struct net_device *dev,
@@ -3268,9 +3300,19 @@ static void fec_enet_free_buffers(struct net_device *ndev)
for (i = 0; i < txq->bd.ring_size; i++) {
kfree(txq->tx_bounce[i]);
txq->tx_bounce[i] = NULL;
- skb = txq->tx_skbuff[i];
- txq->tx_skbuff[i] = NULL;
- dev_kfree_skb(skb);
+
+ if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+ skb = txq->tx_buf[i].skb;
+ txq->tx_buf[i].skb = NULL;
+ dev_kfree_skb(skb);
+ } else {
+ if (txq->tx_buf[i].xdp) {
+ xdp_return_frame(txq->tx_buf[i].xdp);
+ txq->tx_buf[i].xdp = NULL;
+ }
+
+ txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
+ }
}
}
}
@@ -3315,8 +3357,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size;
txq->tx_stop_threshold = FEC_MAX_SKB_DESCS;
- txq->tx_wake_threshold =
- (txq->bd.ring_size - txq->tx_stop_threshold) / 2;
+ txq->tx_wake_threshold = FEC_MAX_SKB_DESCS + 2 * MAX_SKB_FRAGS;
txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev,
txq->bd.ring_size * TSO_HEADER_SIZE,
@@ -3751,12 +3792,18 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
return -EOPNOTSUPP;
+ if (!bpf->prog)
+ xdp_features_clear_redirect_target(dev);
+
if (is_run) {
napi_disable(&fep->napi);
netif_tx_disable(dev);
}
old_prog = xchg(&fep->xdp_prog, bpf->prog);
+ if (old_prog)
+ bpf_prog_put(old_prog);
+
fec_restart(dev);
if (is_run) {
@@ -3764,8 +3811,8 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
netif_tx_start_all_queues(dev);
}
- if (old_prog)
- bpf_prog_put(old_prog);
+ if (bpf->prog)
+ xdp_features_set_redirect_target(dev, false);
return 0;
@@ -3791,19 +3838,18 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
struct xdp_frame *frame)
{
unsigned int index, status, estatus;
- struct bufdesc *bdp, *last_bdp;
+ struct bufdesc *bdp;
dma_addr_t dma_addr;
int entries_free;
entries_free = fec_enet_get_free_txdesc_num(txq);
if (entries_free < MAX_SKB_FRAGS + 1) {
- netdev_err(fep->netdev, "NOT enough BD for SG!\n");
- return NETDEV_TX_BUSY;
+ netdev_err_once(fep->netdev, "NOT enough BD for SG!\n");
+ return -EBUSY;
}
/* Fill in a Tx ring entry */
bdp = txq->bd.cur;
- last_bdp = bdp;
status = fec16_to_cpu(bdp->cbd_sc);
status &= ~BD_ENET_TX_STATS;
@@ -3812,7 +3858,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
dma_addr = dma_map_single(&fep->pdev->dev, frame->data,
frame->len, DMA_TO_DEVICE);
if (dma_mapping_error(&fep->pdev->dev, dma_addr))
- return FEC_ENET_XDP_CONSUMED;
+ return -ENOMEM;
status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
if (fep->bufdesc_ex)
@@ -3831,8 +3877,8 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
ebdp->cbd_esc = cpu_to_fec32(estatus);
}
- index = fec_enet_get_bd_index(last_bdp, &txq->bd);
- txq->tx_skbuff[index] = NULL;
+ txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO;
+ txq->tx_buf[index].xdp = frame;
/* Make sure the updates to rest of the descriptor are performed before
* transferring ownership.
@@ -3846,7 +3892,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
bdp->cbd_sc = cpu_to_fec16(status);
/* If this was the last BD in the ring, start at the beginning again. */
- bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
+ bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
/* Make sure the update to bdp are performed before txq->bd.cur. */
dma_wmb();
@@ -3878,8 +3924,10 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
__netif_tx_lock(nq, cpu);
+ /* Avoid tx timeout as XDP shares the queue with kernel stack */
+ txq_trans_cond_update(nq);
for (i = 0; i < num_frames; i++) {
- if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) != 0)
+ if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0)
break;
sent_frames++;
}
@@ -4035,6 +4083,10 @@ static int fec_enet_init(struct net_device *ndev)
ndev->hw_features = ndev->features;
+ if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME))
+ ndev->xdp_features = NETDEV_XDP_ACT_BASIC |
+ NETDEV_XDP_ACT_REDIRECT;
+
fec_restart(ndev);
if (fep->quirks & FEC_QUIRK_MIB_CLEAR)
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index d528ca681b6f..3088da7adf0f 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -763,15 +763,15 @@ static void dtsec_pcs_get_state(struct phylink_pcs *pcs,
phylink_mii_c22_pcs_get_state(dtsec->tbidev, state);
}
-static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int dtsec_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct fman_mac *dtsec = pcs_to_dtsec(pcs);
- return phylink_mii_c22_pcs_config(dtsec->tbidev, mode, interface,
- advertising);
+ return phylink_mii_c22_pcs_config(dtsec->tbidev, interface,
+ advertising, neg_mode);
}
static void dtsec_pcs_an_restart(struct phylink_pcs *pcs)
@@ -1447,6 +1447,7 @@ int dtsec_initialization(struct mac_device *mac_dev,
goto _return_fm_mac_free;
}
dtsec->pcs.ops = &dtsec_pcs_ops;
+ dtsec->pcs.neg_mode = true;
dtsec->pcs.poll = true;
supported = mac_dev->phylink_config.supported_interfaces;
diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c
index 625c79d5636f..3b75cc543be9 100644
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -976,14 +976,10 @@ static int memac_init(struct fman_mac *memac)
static void pcs_put(struct phylink_pcs *pcs)
{
- struct mdio_device *mdiodev;
-
if (IS_ERR_OR_NULL(pcs))
return;
- mdiodev = lynx_get_mdio_device(pcs);
lynx_pcs_destroy(pcs);
- mdio_device_free(mdiodev);
}
static int memac_free(struct fman_mac *memac)
@@ -1043,20 +1039,14 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node,
int index)
{
struct device_node *node;
- struct mdio_device *mdiodev = NULL;
struct phylink_pcs *pcs;
node = of_parse_phandle(mac_node, "pcsphy-handle", index);
- if (node && of_device_is_available(node))
- mdiodev = of_mdio_find_device(node);
- of_node_put(node);
+ if (!node)
+ return ERR_PTR(-ENODEV);
- if (!mdiodev)
- return ERR_PTR(-EPROBE_DEFER);
-
- pcs = lynx_pcs_create(mdiodev);
- if (!pcs)
- mdio_device_free(mdiodev);
+ pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node));
+ of_node_put(node);
return pcs;
}
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index d37d7a19a759..59a8f0bd0f5c 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -127,7 +127,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev)
if (ret)
goto out_res;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pap", &res.start);
fec->fecp = ioremap(res.start, resource_size(&res));
if (!fec->fecp) {
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_rx.c b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
index 29a6c2ede43a..7e2584895de3 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_rx.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_rx.c
@@ -323,9 +323,8 @@ static int fun_gather_pkt(struct funeth_rxq *q, unsigned int tot_len,
if (ref_ok)
ref_ok |= buf->node;
- __skb_frag_set_page(frags, buf->page);
- skb_frag_off_set(frags, q->buf_offset);
- skb_frag_size_set(frags++, frag_len);
+ skb_frag_fill_page_desc(frags++, buf->page, q->buf_offset,
+ frag_len);
tot_len -= frag_len;
if (!tot_len)
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_tx.c b/drivers/net/ethernet/fungible/funeth/funeth_tx.c
index 706d81e39a54..8ddefd3ec15b 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_tx.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_tx.c
@@ -348,8 +348,7 @@ netdev_tx_t fun_start_xmit(struct sk_buff *skb, struct net_device *netdev)
unsigned int tls_len = 0;
unsigned int ndesc;
- if (IS_ENABLED(CONFIG_TLS_DEVICE) && skb->sk &&
- tls_is_sk_tx_device_offloaded(skb->sk)) {
+ if (tls_is_skb_tx_device_offloaded(skb)) {
skb = fun_tls_tx(skb, q, &tls_len);
if (unlikely(!skb))
goto dropped;
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 98eb78d98e9f..4b425bf71ede 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -964,5 +964,6 @@ void gve_handle_report_stats(struct gve_priv *priv);
/* exported by ethtool.c */
extern const struct ethtool_ops gve_ethtool_ops;
/* needed by ethtool */
+extern char gve_driver_name[];
extern const char gve_version_str[];
#endif /* _GVE_H_ */
diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
index cfd4b8d284d1..233e5946905e 100644
--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
+++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
@@ -15,7 +15,7 @@ static void gve_get_drvinfo(struct net_device *netdev,
{
struct gve_priv *priv = netdev_priv(netdev);
- strscpy(info->driver, "gve", sizeof(info->driver));
+ strscpy(info->driver, gve_driver_name, sizeof(info->driver));
strscpy(info->version, gve_version_str, sizeof(info->version));
strscpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info));
}
@@ -590,6 +590,9 @@ static int gve_get_link_ksettings(struct net_device *netdev,
err = gve_adminq_report_link_speed(priv);
cmd->base.speed = priv->link_speed;
+
+ cmd->base.duplex = DUPLEX_FULL;
+
return err;
}
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index caa00c72aeeb..e6f1711d9be0 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -31,7 +31,9 @@
// Minimum amount of time between queue kicks in msec (10 seconds)
#define MIN_TX_TIMEOUT_GAP (1000 * 10)
+#define DQO_TX_MAX 0x3FFFF
+char gve_driver_name[] = "gve";
const char gve_version_str[] = GVE_VERSION;
static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
@@ -2047,6 +2049,10 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
goto err;
}
+ /* Big TCP is only supported on DQ*/
+ if (!gve_is_gqi(priv))
+ netif_set_tso_max_size(priv->dev, DQO_TX_MAX);
+
priv->num_registered_pages = 0;
priv->rx_copybreak = GVE_DEFAULT_RX_COPYBREAK;
/* gvnic has one Notification Block per MSI-x vector, except for the
@@ -2195,7 +2201,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
return err;
- err = pci_request_regions(pdev, "gvnic-cfg");
+ err = pci_request_regions(pdev, gve_driver_name);
if (err)
goto abort_with_enabled;
@@ -2388,8 +2394,8 @@ static const struct pci_device_id gve_id_table[] = {
{ }
};
-static struct pci_driver gvnic_driver = {
- .name = "gvnic",
+static struct pci_driver gve_driver = {
+ .name = gve_driver_name,
.id_table = gve_id_table,
.probe = gve_probe,
.remove = gve_remove,
@@ -2400,10 +2406,10 @@ static struct pci_driver gvnic_driver = {
#endif
};
-module_pci_driver(gvnic_driver);
+module_pci_driver(gve_driver);
MODULE_DEVICE_TABLE(pci, gve_id_table);
MODULE_AUTHOR("Google, Inc.");
-MODULE_DESCRIPTION("gVNIC Driver");
+MODULE_DESCRIPTION("Google Virtual NIC Driver");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION(GVE_VERSION);
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index e57b73eb70f6..ac041cc5714c 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -492,7 +492,10 @@ static int gve_rx_append_frags(struct napi_struct *napi,
if (!skb)
return -1;
- skb_shinfo(rx->ctx.skb_tail)->frag_list = skb;
+ if (rx->ctx.skb_tail == rx->ctx.skb_head)
+ skb_shinfo(rx->ctx.skb_head)->frag_list = skb;
+ else
+ rx->ctx.skb_tail->next = skb;
rx->ctx.skb_tail = skb;
num_frags = 0;
}
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
index 813da572abca..6957a865cff3 100644
--- a/drivers/net/ethernet/google/gve/gve_tx.c
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
@@ -248,7 +248,7 @@ static int gve_tx_alloc_ring(struct gve_priv *priv, int idx)
tx->mask = slots - 1;
/* alloc metadata */
- tx->info = vzalloc(sizeof(*tx->info) * slots);
+ tx->info = vcalloc(slots, sizeof(*tx->info));
if (!tx->info)
return -ENOMEM;
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index b76143bfd594..3c09e66ba1ab 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -8,6 +8,7 @@
#include "gve_adminq.h"
#include "gve_utils.h"
#include "gve_dqo.h"
+#include <net/ip.h>
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
@@ -646,6 +647,9 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx,
goto drop;
}
+ if (unlikely(ipv6_hopopt_jumbo_remove(skb)))
+ goto drop;
+
num_buffer_descs = gve_num_buffer_descs_needed(skb);
} else {
num_buffer_descs = gve_num_buffer_descs_needed(skb);
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
index 6efea4662858..e214bfaece1f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -17,11 +17,11 @@ hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o
obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o
-hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o \
+hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o hns3vf/hclgevf_regs.o \
hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o
obj-$(CONFIG_HNS3_HCLGE) += hclge.o
-hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o \
+hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o hns3pf/hclge_regs.o \
hns3pf/hclge_mbx.o hns3pf/hclge_err.o hns3pf/hclge_debugfs.o hns3pf/hclge_ptp.o hns3pf/hclge_devlink.o \
hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 9c9c72dc57e0..aaf1f42624a7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/pkt_sched.h>
#include <linux/types.h>
+#include <linux/bitmap.h>
#include <net/pkt_cls.h>
#include <net/pkt_sched.h>
@@ -101,6 +102,7 @@ enum HNAE3_DEV_CAP_BITS {
HNAE3_DEV_SUPPORT_FEC_STATS_B,
HNAE3_DEV_SUPPORT_LANE_NUM_B,
HNAE3_DEV_SUPPORT_WOL_B,
+ HNAE3_DEV_SUPPORT_TM_FLUSH_B,
};
#define hnae3_ae_dev_fd_supported(ae_dev) \
@@ -172,6 +174,9 @@ enum HNAE3_DEV_CAP_BITS {
#define hnae3_ae_dev_wol_supported(ae_dev) \
test_bit(HNAE3_DEV_SUPPORT_WOL_B, (ae_dev)->caps)
+#define hnae3_ae_dev_tm_flush_supported(hdev) \
+ test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps)
+
enum HNAE3_PF_CAP_BITS {
HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
};
@@ -377,6 +382,7 @@ struct hnae3_dev_specs {
u16 umv_size;
u16 mc_mac_size;
u32 mac_stats_num;
+ u8 tnl_num;
};
struct hnae3_client_ops {
@@ -407,7 +413,7 @@ struct hnae3_ae_dev {
unsigned long hw_err_reset_req;
struct hnae3_dev_specs dev_specs;
u32 dev_version;
- unsigned long caps[BITS_TO_LONGS(HNAE3_DEV_CAPS_MAX_NUM)];
+ DECLARE_BITMAP(caps, HNAE3_DEV_CAPS_MAX_NUM);
void *priv;
};
@@ -647,8 +653,7 @@ struct hnae3_ae_ops {
int (*rm_mc_addr)(struct hnae3_handle *handle,
const unsigned char *addr);
void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
- void (*update_stats)(struct hnae3_handle *handle,
- struct net_device_stats *net_stats);
+ void (*update_stats)(struct hnae3_handle *handle);
void (*get_stats)(struct hnae3_handle *handle, u64 *data);
void (*get_mac_stats)(struct hnae3_handle *handle,
struct hns3_mac_stats *mac_stats);
@@ -809,6 +814,7 @@ struct hnae3_tc_info {
u8 max_tc; /* Total number of TCs */
u8 num_tc; /* Total number of enabled TCs */
bool mqprio_active;
+ bool dcb_ets_active;
};
#define HNAE3_MAX_DSCP 64
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
index b85c412683dd..dcecb23daac6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
@@ -156,6 +156,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
{HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
{HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
{HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B},
+ {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B},
};
static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
@@ -172,6 +173,20 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
};
static void
+hclge_comm_capability_to_bitmap(unsigned long *bitmap, __le32 *caps)
+{
+ const unsigned int words = HCLGE_COMM_QUERY_CAP_LENGTH;
+ u32 val[HCLGE_COMM_QUERY_CAP_LENGTH];
+ unsigned int i;
+
+ for (i = 0; i < words; i++)
+ val[i] = __le32_to_cpu(caps[i]);
+
+ bitmap_from_arr32(bitmap, val,
+ HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+}
+
+static void
hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
struct hclge_comm_query_version_cmd *cmd)
{
@@ -179,11 +194,12 @@ hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
is_pf ? hclge_pf_cmd_caps : hclge_vf_cmd_caps;
u32 size = is_pf ? ARRAY_SIZE(hclge_pf_cmd_caps) :
ARRAY_SIZE(hclge_vf_cmd_caps);
- u32 caps, i;
+ DECLARE_BITMAP(caps, HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+ u32 i;
- caps = __le32_to_cpu(cmd->caps[0]);
+ hclge_comm_capability_to_bitmap(caps, cmd->caps);
for (i = 0; i < size; i++)
- if (hnae3_get_bit(caps, caps_map[i].imp_bit))
+ if (test_bit(caps_map[i].imp_bit, caps))
set_bit(caps_map[i].local_bit, ae_dev->caps);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
index 18f1b4bf362d..2b7197ce0ae8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
@@ -153,6 +153,7 @@ enum hclge_opcode_type {
HCLGE_OPC_TM_INTERNAL_STS = 0x0850,
HCLGE_OPC_TM_INTERNAL_CNT = 0x0851,
HCLGE_OPC_TM_INTERNAL_STS_1 = 0x0852,
+ HCLGE_OPC_TM_FLUSH = 0x0872,
/* Packet buffer allocate commands */
HCLGE_OPC_TX_BUFF_ALLOC = 0x0901,
@@ -349,6 +350,7 @@ enum HCLGE_COMM_CAP_BITS {
HCLGE_COMM_CAP_FEC_STATS_B = 25,
HCLGE_COMM_CAP_LANE_NUM_B = 27,
HCLGE_COMM_CAP_WOL_B = 28,
+ HCLGE_COMM_CAP_TM_FLUSH_B = 31,
};
enum HCLGE_COMM_API_CAP_BITS {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
index ae2736549526..b4ae2160aff4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c
@@ -305,8 +305,7 @@ int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev,
return 0;
}
-int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic,
- struct hclge_comm_hw *hw, bool is_pf,
+int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw,
struct hclge_comm_rss_cfg *rss_cfg)
{
struct hclge_comm_rss_input_tuple_cmd *req;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
index 92af3d2980d3..cdafa63fe38b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.h
@@ -112,8 +112,7 @@ int hclge_comm_init_rss_tuple_cmd(struct hclge_comm_rss_cfg *rss_cfg,
struct hnae3_ae_dev *ae_dev,
struct hclge_comm_rss_input_tuple_cmd *req);
u64 hclge_comm_convert_rss_tuple(u8 tuple_sets);
-int hclge_comm_set_rss_input_tuple(struct hnae3_handle *nic,
- struct hclge_comm_hw *hw, bool is_pf,
+int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw,
struct hclge_comm_rss_cfg *rss_cfg);
int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev,
struct hclge_comm_hw *hw, const u16 *indir);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index d385ffc21876..26fb6fefcb9d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -411,6 +411,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
}, {
.name = "support wake on lan",
.cap_bit = HNAE3_DEV_SUPPORT_WOL_B,
+ }, {
+ .name = "support tm flush",
+ .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B,
}
};
@@ -438,19 +441,36 @@ static void hns3_dbg_fill_content(char *content, u16 len,
const struct hns3_dbg_item *items,
const char **result, u16 size)
{
+#define HNS3_DBG_LINE_END_LEN 2
char *pos = content;
+ u16 item_len;
u16 i;
+ if (!len) {
+ return;
+ } else if (len <= HNS3_DBG_LINE_END_LEN) {
+ *pos++ = '\0';
+ return;
+ }
+
memset(content, ' ', len);
- for (i = 0; i < size; i++) {
- if (result)
- strncpy(pos, result[i], strlen(result[i]));
- else
- strncpy(pos, items[i].name, strlen(items[i].name));
+ len -= HNS3_DBG_LINE_END_LEN;
- pos += strlen(items[i].name) + items[i].interval;
+ for (i = 0; i < size; i++) {
+ item_len = strlen(items[i].name) + items[i].interval;
+ if (len < item_len)
+ break;
+
+ if (result) {
+ if (item_len < strlen(result[i]))
+ break;
+ memcpy(pos, result[i], strlen(result[i]));
+ } else {
+ memcpy(pos, items[i].name, strlen(items[i].name));
+ }
+ pos += item_len;
+ len -= item_len;
}
-
*pos++ = '\n';
*pos++ = '\0';
}
@@ -941,8 +961,7 @@ static const struct hns3_dbg_item tx_bd_info_items[] = {
{ "MSS_HW_CSUM", 0 },
};
-static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv,
- struct hns3_desc *desc, char **result, int idx)
+static void hns3_dump_tx_bd_info(struct hns3_desc *desc, char **result, int idx)
{
unsigned int j = 0;
@@ -991,7 +1010,7 @@ static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len)
for (i = 0; i < ring->desc_num; i++) {
desc = &ring->desc[i];
- hns3_dump_tx_bd_info(priv, desc, result, i);
+ hns3_dump_tx_bd_info(desc, result, i);
hns3_dbg_fill_content(content, sizeof(content),
tx_bd_info_items, (const char **)result,
ARRAY_SIZE(tx_bd_info_items));
@@ -1392,9 +1411,9 @@ int hns3_dbg_init(struct hnae3_handle *handle)
return 0;
out:
- mutex_destroy(&handle->dbgfs_lock);
debugfs_remove_recursive(handle->hnae3_dbgfs);
handle->hnae3_dbgfs = NULL;
+ mutex_destroy(&handle->dbgfs_lock);
return ret;
}
@@ -1402,6 +1421,9 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
{
u32 i;
+ debugfs_remove_recursive(handle->hnae3_dbgfs);
+ handle->hnae3_dbgfs = NULL;
+
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++)
if (handle->dbgfs_buf[i]) {
kvfree(handle->dbgfs_buf[i]);
@@ -1409,8 +1431,6 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
}
mutex_destroy(&handle->dbgfs_lock);
- debugfs_remove_recursive(handle->hnae3_dbgfs);
- handle->hnae3_dbgfs = NULL;
}
void hns3_dbg_register_debugfs(const char *debugfs_dir_name)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index b676496ec6d7..613d0a779cef 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2102,8 +2102,12 @@ static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
*/
if (test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state) && num &&
!ring->pending_buf && num <= HNS3_MAX_PUSH_BD_NUM && doorbell) {
+ /* This smp_store_release() pairs with smp_load_aquire() in
+ * hns3_nic_reclaim_desc(). Ensure that the BD valid bit
+ * is updated.
+ */
+ smp_store_release(&ring->last_to_use, ring->next_to_use);
hns3_tx_push_bd(ring, num);
- WRITE_ONCE(ring->last_to_use, ring->next_to_use);
return;
}
@@ -2114,6 +2118,11 @@ static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
return;
}
+ /* This smp_store_release() pairs with smp_load_aquire() in
+ * hns3_nic_reclaim_desc(). Ensure that the BD valid bit is updated.
+ */
+ smp_store_release(&ring->last_to_use, ring->next_to_use);
+
if (ring->tqp->mem_base)
hns3_tx_mem_doorbell(ring);
else
@@ -2121,7 +2130,6 @@ static void hns3_tx_doorbell(struct hns3_enet_ring *ring, int num,
ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
ring->pending_buf = 0;
- WRITE_ONCE(ring->last_to_use, ring->next_to_use);
}
static void hns3_tsyn(struct net_device *netdev, struct sk_buff *skb,
@@ -2538,7 +2546,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
if (test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
return;
- handle->ae_algo->ops->update_stats(handle, &netdev->stats);
+ handle->ae_algo->ops->update_stats(handle);
memset(&ring_total_stats, 0, sizeof(ring_total_stats));
for (idx = 0; idx < queue_num; idx++) {
@@ -3307,8 +3315,6 @@ static void hns3_set_default_feature(struct net_device *netdev)
netdev->priv_flags |= IFF_UNICAST_FLT;
- netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
-
netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
@@ -3562,9 +3568,8 @@ static void hns3_reuse_buffer(struct hns3_enet_ring *ring, int i)
static bool hns3_nic_reclaim_desc(struct hns3_enet_ring *ring,
int *bytes, int *pkts, int budget)
{
- /* pair with ring->last_to_use update in hns3_tx_doorbell(),
- * smp_store_release() is not used in hns3_tx_doorbell() because
- * the doorbell operation already have the needed barrier operation.
+ /* This smp_load_acquire() pairs with smp_store_release() in
+ * hns3_tx_doorbell().
*/
int ltu = smp_load_acquire(&ring->last_to_use);
int ntc = ring->next_to_clean;
@@ -5854,6 +5859,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running)
if (!if_running)
return;
+ if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+ return;
+
netif_carrier_off(ndev);
netif_tx_disable(ndev);
@@ -5882,7 +5890,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running)
if (!if_running)
return;
- hns3_nic_reset_all_ring(priv->ae_handle);
+ if (hns3_nic_resetting(ndev))
+ return;
+
+ if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+ return;
+
+ if (hns3_nic_reset_all_ring(priv->ae_handle))
+ return;
+
+ clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
for (i = 0; i < priv->vector_num; i++)
hns3_vector_enable(&priv->tqp_vector[i]);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 51d1278b18f6..64858b3114ac 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -228,7 +228,7 @@ static u32 hns3_lb_check_rx_ring(struct hns3_nic_priv *priv, u32 budget)
}
static void hns3_lb_clear_tx_ring(struct hns3_nic_priv *priv, u32 start_ringid,
- u32 end_ringid, u32 budget)
+ u32 end_ringid)
{
u32 i;
@@ -295,8 +295,7 @@ static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode)
out:
hns3_lb_clear_tx_ring(priv, HNS3_NIC_LB_TEST_RING_ID,
- HNS3_NIC_LB_TEST_RING_ID,
- HNS3_NIC_LB_TEST_PKT_NUM);
+ HNS3_NIC_LB_TEST_RING_ID);
kfree_skb(skb);
return ret_val;
@@ -618,7 +617,7 @@ static void hns3_get_stats(struct net_device *netdev,
return;
}
- h->ae_algo->ops->update_stats(h, &netdev->stats);
+ h->ae_algo->ops->update_stats(h);
/* get per-queue stats */
p = hns3_get_stats_tqps(h, p);
@@ -774,7 +773,9 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
hns3_get_ksettings(h, cmd);
break;
case HNAE3_MEDIA_TYPE_FIBER:
- if (module_type == HNAE3_MODULE_TYPE_CR)
+ if (module_type == HNAE3_MODULE_TYPE_UNKNOWN)
+ cmd->base.port = PORT_OTHER;
+ else if (module_type == HNAE3_MODULE_TYPE_CR)
cmd->base.port = PORT_DA;
else
cmd->base.port = PORT_FIBRE;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 91c173f40701..d5cfdc4c082d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -826,7 +826,9 @@ struct hclge_dev_specs_1_cmd {
u8 rsv0[2];
__le16 umv_size;
__le16 mc_mac_size;
- u8 rsv1[12];
+ u8 rsv1[6];
+ u8 tnl_num;
+ u8 rsv2[5];
};
/* mac speed type defined in firmware command */
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
index c4aded65e848..b98301e205f7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
@@ -52,7 +52,10 @@ static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
for (i = 0; i < HNAE3_MAX_TC; i++) {
ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
- ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+ if (i < hdev->tm_info.num_tc)
+ ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+ else
+ ets->tc_tx_bw[i] = 0;
if (hdev->tm_info.tc_info[i].tc_sch_mode ==
HCLGE_SCH_MODE_SP)
@@ -123,7 +126,8 @@ static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,
}
static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
- struct ieee_ets *ets, bool *changed)
+ struct ieee_ets *ets, bool *changed,
+ u8 tc_num)
{
bool has_ets_tc = false;
u32 total_ets_bw = 0;
@@ -137,6 +141,13 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
*changed = true;
break;
case IEEE_8021QAZ_TSA_ETS:
+ if (i >= tc_num) {
+ dev_err(&hdev->pdev->dev,
+ "tc%u is disabled, cannot set ets bw\n",
+ i);
+ return -EINVAL;
+ }
+
/* The hardware will switch to sp mode if bandwidth is
* 0, so limit ets bandwidth must be greater than 0.
*/
@@ -176,7 +187,7 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
if (ret)
return ret;
- ret = hclge_ets_sch_mode_validate(hdev, ets, changed);
+ ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num);
if (ret)
return ret;
@@ -216,6 +227,10 @@ static int hclge_notify_down_uinit(struct hclge_dev *hdev)
if (ret)
return ret;
+ ret = hclge_tm_flush_cfg(hdev, true);
+ if (ret)
+ return ret;
+
return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
}
@@ -227,6 +242,10 @@ static int hclge_notify_init_up(struct hclge_dev *hdev)
if (ret)
return ret;
+ ret = hclge_tm_flush_cfg(hdev, false);
+ if (ret)
+ return ret;
+
return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
}
@@ -240,7 +259,7 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
int ret;
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
- hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
+ h->kinfo.tc_info.mqprio_active)
return -EINVAL;
ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
@@ -256,10 +275,7 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
}
hclge_tm_schd_info_update(hdev, num_tc);
- if (num_tc > 1)
- hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
- else
- hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
+ h->kinfo.tc_info.dcb_ets_active = num_tc > 1;
ret = hclge_ieee_ets_to_tm_info(hdev, ets);
if (ret)
@@ -313,6 +329,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
struct net_device *netdev = h->kinfo.netdev;
struct hclge_dev *hdev = vport->back;
u8 i, j, pfc_map, *prio_tc;
+ int last_bad_ret = 0;
int ret;
if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -350,13 +367,28 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
if (ret)
return ret;
- ret = hclge_buffer_alloc(hdev);
- if (ret) {
- hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ ret = hclge_tm_flush_cfg(hdev, true);
+ if (ret)
return ret;
- }
- return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ /* No matter whether the following operations are performed
+ * successfully or not, disabling the tm flush and notify
+ * the network status to up are necessary.
+ * Do not return immediately.
+ */
+ ret = hclge_buffer_alloc(hdev);
+ if (ret)
+ last_bad_ret = ret;
+
+ ret = hclge_tm_flush_cfg(hdev, false);
+ if (ret)
+ last_bad_ret = ret;
+
+ ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+ if (ret)
+ last_bad_ret = ret;
+
+ return last_bad_ret;
}
static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app)
@@ -452,7 +484,7 @@ static u8 hclge_getdcbx(struct hnae3_handle *h)
struct hclge_vport *vport = hclge_get_vport(h);
struct hclge_dev *hdev = vport->back;
- if (hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
+ if (h->kinfo.tc_info.mqprio_active)
return 0;
return hdev->dcbx_cap;
@@ -576,7 +608,8 @@ static int hclge_setup_tc(struct hnae3_handle *h,
if (!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state))
return -EBUSY;
- if (hdev->flag & HCLGE_FLAG_DCB_ENABLE)
+ kinfo = &vport->nic.kinfo;
+ if (kinfo->tc_info.dcb_ets_active)
return -EINVAL;
ret = hclge_mqprio_qopt_check(hdev, mqprio_qopt);
@@ -590,7 +623,6 @@ static int hclge_setup_tc(struct hnae3_handle *h,
if (ret)
return ret;
- kinfo = &vport->nic.kinfo;
memcpy(&old_tc_info, &kinfo->tc_info, sizeof(old_tc_info));
hclge_sync_mqprio_qopt(&kinfo->tc_info, mqprio_qopt);
kinfo->tc_info.mqprio_active = tc > 0;
@@ -599,13 +631,6 @@ static int hclge_setup_tc(struct hnae3_handle *h,
if (ret)
goto err_out;
- hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
-
- if (tc > 1)
- hdev->flag |= HCLGE_FLAG_MQPRIO_ENABLE;
- else
- hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE;
-
return hclge_notify_init_up(hdev);
err_out:
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
index a0b46e7d863e..ff3f8f424ad9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -7,6 +7,7 @@
#include "hclge_debugfs.h"
#include "hclge_err.h"
#include "hclge_main.h"
+#include "hclge_regs.h"
#include "hclge_tm.h"
#include "hnae3.h"
@@ -88,16 +89,35 @@ static void hclge_dbg_fill_content(char *content, u16 len,
const struct hclge_dbg_item *items,
const char **result, u16 size)
{
+#define HCLGE_DBG_LINE_END_LEN 2
char *pos = content;
+ u16 item_len;
u16 i;
+ if (!len) {
+ return;
+ } else if (len <= HCLGE_DBG_LINE_END_LEN) {
+ *pos++ = '\0';
+ return;
+ }
+
memset(content, ' ', len);
+ len -= HCLGE_DBG_LINE_END_LEN;
+
for (i = 0; i < size; i++) {
- if (result)
- strncpy(pos, result[i], strlen(result[i]));
- else
- strncpy(pos, items[i].name, strlen(items[i].name));
- pos += strlen(items[i].name) + items[i].interval;
+ item_len = strlen(items[i].name) + items[i].interval;
+ if (len < item_len)
+ break;
+
+ if (result) {
+ if (item_len < strlen(result[i]))
+ break;
+ memcpy(pos, result[i], strlen(result[i]));
+ } else {
+ memcpy(pos, items[i].name, strlen(items[i].name));
+ }
+ pos += item_len;
+ len -= item_len;
}
*pos++ = '\n';
*pos++ = '\0';
@@ -674,8 +694,7 @@ static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len)
for (i = 0; i < HNAE3_MAX_TC; i++) {
sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp";
pos += scnprintf(buf + pos, len - pos, "%u %4s %3u\n",
- i, sch_mode_str,
- hdev->tm_info.pg_info[0].tc_dwrr[i]);
+ i, sch_mode_str, ets_weight->tc_weight[i]);
}
return 0;
@@ -1500,7 +1519,7 @@ static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x,
struct hclge_desc desc[3];
int pos = 0;
int ret, i;
- u32 *req;
+ __le32 *req;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_FD_TCAM_OP, true);
desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
@@ -1525,22 +1544,22 @@ static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, bool sel_x,
tcam_msg.loc);
/* tcam_data0 ~ tcam_data1 */
- req = (u32 *)req1->tcam_data;
+ req = (__le32 *)req1->tcam_data;
for (i = 0; i < 2; i++)
pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos,
- "%08x\n", *req++);
+ "%08x\n", le32_to_cpu(*req++));
/* tcam_data2 ~ tcam_data7 */
- req = (u32 *)req2->tcam_data;
+ req = (__le32 *)req2->tcam_data;
for (i = 0; i < 6; i++)
pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos,
- "%08x\n", *req++);
+ "%08x\n", le32_to_cpu(*req++));
/* tcam_data8 ~ tcam_data12 */
- req = (u32 *)req3->tcam_data;
+ req = (__le32 *)req3->tcam_data;
for (i = 0; i < 5; i++)
pos += scnprintf(tcam_buf + pos, HCLGE_DBG_TCAM_BUF_SIZE - pos,
- "%08x\n", *req++);
+ "%08x\n", le32_to_cpu(*req++));
return ret;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 2689b108f7df..ce6b658a930c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -20,6 +20,7 @@
#include "hclge_main.h"
#include "hclge_mbx.h"
#include "hclge_mdio.h"
+#include "hclge_regs.h"
#include "hclge_tm.h"
#include "hclge_err.h"
#include "hnae3.h"
@@ -40,20 +41,6 @@
#define HCLGE_PF_RESET_SYNC_TIME 20
#define HCLGE_PF_RESET_SYNC_CNT 1500
-/* Get DFX BD number offset */
-#define HCLGE_DFX_BIOS_BD_OFFSET 1
-#define HCLGE_DFX_SSU_0_BD_OFFSET 2
-#define HCLGE_DFX_SSU_1_BD_OFFSET 3
-#define HCLGE_DFX_IGU_BD_OFFSET 4
-#define HCLGE_DFX_RPU_0_BD_OFFSET 5
-#define HCLGE_DFX_RPU_1_BD_OFFSET 6
-#define HCLGE_DFX_NCSI_BD_OFFSET 7
-#define HCLGE_DFX_RTC_BD_OFFSET 8
-#define HCLGE_DFX_PPP_BD_OFFSET 9
-#define HCLGE_DFX_RCB_BD_OFFSET 10
-#define HCLGE_DFX_TQP_BD_OFFSET 11
-#define HCLGE_DFX_SSU_2_BD_OFFSET 12
-
#define HCLGE_LINK_STATUS_MS 10
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps);
@@ -72,6 +59,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev);
static void hclge_sync_promisc_mode(struct hclge_dev *hdev);
static void hclge_sync_fd_table(struct hclge_dev *hdev);
static void hclge_update_fec_stats(struct hclge_dev *hdev);
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+ int wait_cnt);
static struct hnae3_ae_algo ae_algo;
@@ -92,62 +81,6 @@ static const struct pci_device_id ae_algo_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl);
-static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG,
- HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG,
- HCLGE_COMM_NIC_CSQ_DEPTH_REG,
- HCLGE_COMM_NIC_CSQ_TAIL_REG,
- HCLGE_COMM_NIC_CSQ_HEAD_REG,
- HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG,
- HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG,
- HCLGE_COMM_NIC_CRQ_DEPTH_REG,
- HCLGE_COMM_NIC_CRQ_TAIL_REG,
- HCLGE_COMM_NIC_CRQ_HEAD_REG,
- HCLGE_COMM_VECTOR0_CMDQ_SRC_REG,
- HCLGE_COMM_CMDQ_INTR_STS_REG,
- HCLGE_COMM_CMDQ_INTR_EN_REG,
- HCLGE_COMM_CMDQ_INTR_GEN_REG};
-
-static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE,
- HCLGE_PF_OTHER_INT_REG,
- HCLGE_MISC_RESET_STS_REG,
- HCLGE_MISC_VECTOR_INT_STS,
- HCLGE_GLOBAL_RESET_REG,
- HCLGE_FUN_RST_ING,
- HCLGE_GRO_EN_REG};
-
-static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG,
- HCLGE_RING_RX_ADDR_H_REG,
- HCLGE_RING_RX_BD_NUM_REG,
- HCLGE_RING_RX_BD_LENGTH_REG,
- HCLGE_RING_RX_MERGE_EN_REG,
- HCLGE_RING_RX_TAIL_REG,
- HCLGE_RING_RX_HEAD_REG,
- HCLGE_RING_RX_FBD_NUM_REG,
- HCLGE_RING_RX_OFFSET_REG,
- HCLGE_RING_RX_FBD_OFFSET_REG,
- HCLGE_RING_RX_STASH_REG,
- HCLGE_RING_RX_BD_ERR_REG,
- HCLGE_RING_TX_ADDR_L_REG,
- HCLGE_RING_TX_ADDR_H_REG,
- HCLGE_RING_TX_BD_NUM_REG,
- HCLGE_RING_TX_PRIORITY_REG,
- HCLGE_RING_TX_TC_REG,
- HCLGE_RING_TX_MERGE_EN_REG,
- HCLGE_RING_TX_TAIL_REG,
- HCLGE_RING_TX_HEAD_REG,
- HCLGE_RING_TX_FBD_NUM_REG,
- HCLGE_RING_TX_OFFSET_REG,
- HCLGE_RING_TX_EBD_NUM_REG,
- HCLGE_RING_TX_EBD_OFFSET_REG,
- HCLGE_RING_TX_BD_ERR_REG,
- HCLGE_RING_EN_REG};
-
-static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG,
- HCLGE_TQP_INTR_GL0_REG,
- HCLGE_TQP_INTR_GL1_REG,
- HCLGE_TQP_INTR_GL2_REG,
- HCLGE_TQP_INTR_RL_REG};
-
static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = {
"External Loopback test",
"App Loopback test",
@@ -373,36 +306,6 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = {
},
};
-static const u32 hclge_dfx_bd_offset_list[] = {
- HCLGE_DFX_BIOS_BD_OFFSET,
- HCLGE_DFX_SSU_0_BD_OFFSET,
- HCLGE_DFX_SSU_1_BD_OFFSET,
- HCLGE_DFX_IGU_BD_OFFSET,
- HCLGE_DFX_RPU_0_BD_OFFSET,
- HCLGE_DFX_RPU_1_BD_OFFSET,
- HCLGE_DFX_NCSI_BD_OFFSET,
- HCLGE_DFX_RTC_BD_OFFSET,
- HCLGE_DFX_PPP_BD_OFFSET,
- HCLGE_DFX_RCB_BD_OFFSET,
- HCLGE_DFX_TQP_BD_OFFSET,
- HCLGE_DFX_SSU_2_BD_OFFSET
-};
-
-static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = {
- HCLGE_OPC_DFX_BIOS_COMMON_REG,
- HCLGE_OPC_DFX_SSU_REG_0,
- HCLGE_OPC_DFX_SSU_REG_1,
- HCLGE_OPC_DFX_IGU_EGU_REG,
- HCLGE_OPC_DFX_RPU_REG_0,
- HCLGE_OPC_DFX_RPU_REG_1,
- HCLGE_OPC_DFX_NCSI_REG,
- HCLGE_OPC_DFX_RTC_REG,
- HCLGE_OPC_DFX_PPP_REG,
- HCLGE_OPC_DFX_RCB_REG,
- HCLGE_OPC_DFX_TQP_REG,
- HCLGE_OPC_DFX_SSU_REG_2
-};
-
static const struct key_info meta_data_key_info[] = {
{ PACKET_TYPE_ID, 6 },
{ IP_FRAGEMENT, 1 },
@@ -689,8 +592,7 @@ static void hclge_update_stats_for_all(struct hclge_dev *hdev)
"Update MAC stats fail, status = %d.\n", status);
}
-static void hclge_update_stats(struct hnae3_handle *handle,
- struct net_device_stats *net_stats)
+static void hclge_update_stats(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
@@ -824,7 +726,7 @@ static void hclge_get_mac_stat(struct hnae3_handle *handle,
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- hclge_update_stats(handle, NULL);
+ hclge_update_stats(handle);
mac_stats->tx_pause_cnt = hdev->mac_stats.mac_tx_mac_pause_num;
mac_stats->rx_pause_cnt = hdev->mac_stats.mac_rx_mac_pause_num;
@@ -1424,6 +1326,7 @@ static void hclge_set_default_dev_specs(struct hclge_dev *hdev)
ae_dev->dev_specs.max_frm_size = HCLGE_MAC_MAX_FRAME;
ae_dev->dev_specs.max_qset_num = HCLGE_MAX_QSET_NUM;
ae_dev->dev_specs.umv_size = HCLGE_DEFAULT_UMV_SPACE_PER_PF;
+ ae_dev->dev_specs.tnl_num = 0;
}
static void hclge_parse_dev_specs(struct hclge_dev *hdev,
@@ -1447,6 +1350,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev,
ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size);
ae_dev->dev_specs.umv_size = le16_to_cpu(req1->umv_size);
ae_dev->dev_specs.mc_mac_size = le16_to_cpu(req1->mc_mac_size);
+ ae_dev->dev_specs.tnl_num = req1->tnl_num;
}
static void hclge_check_dev_specs(struct hclge_dev *hdev)
@@ -4965,9 +4869,7 @@ int hclge_rss_init_hw(struct hclge_dev *hdev)
if (ret)
return ret;
- ret = hclge_comm_set_rss_input_tuple(&hdev->vport[0].nic,
- &hdev->hw.hw, true,
- &hdev->rss_cfg);
+ ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, &hdev->rss_cfg);
if (ret)
return ret;
@@ -6243,8 +6145,7 @@ static int hclge_fd_check_spec(struct hclge_dev *hdev,
return hclge_fd_check_ext_tuple(hdev, fs, unused_tuple);
}
-static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_tcpip4_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule, u8 ip_proto)
{
rule->tuples.src_ip[IPV4_INDEX] =
@@ -6273,8 +6174,7 @@ static void hclge_fd_get_tcpip4_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ip_proto = 0xFF;
}
-static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ip4_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
rule->tuples.src_ip[IPV4_INDEX] =
@@ -6297,8 +6197,7 @@ static void hclge_fd_get_ip4_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ether_proto = 0xFFFF;
}
-static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_tcpip6_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule, u8 ip_proto)
{
be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.tcp_ip6_spec.ip6src,
@@ -6327,8 +6226,7 @@ static void hclge_fd_get_tcpip6_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ip_proto = 0xFF;
}
-static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ip6_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
be32_to_cpu_array(rule->tuples.src_ip, fs->h_u.usr_ip6_spec.ip6src,
@@ -6351,8 +6249,7 @@ static void hclge_fd_get_ip6_tuple(struct hclge_dev *hdev,
rule->tuples_mask.ether_proto = 0xFFFF;
}
-static void hclge_fd_get_ether_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static void hclge_fd_get_ether_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule)
{
ether_addr_copy(rule->tuples.src_mac, fs->h_u.ether_spec.h_source);
@@ -6388,8 +6285,7 @@ static void hclge_fd_get_user_def_tuple(struct hclge_fd_user_def_info *info,
rule->ep.user_def = *info;
}
-static int hclge_fd_get_tuple(struct hclge_dev *hdev,
- struct ethtool_rx_flow_spec *fs,
+static int hclge_fd_get_tuple(struct ethtool_rx_flow_spec *fs,
struct hclge_fd_rule *rule,
struct hclge_fd_user_def_info *info)
{
@@ -6397,31 +6293,31 @@ static int hclge_fd_get_tuple(struct hclge_dev *hdev,
switch (flow_type) {
case SCTP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_SCTP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_SCTP);
break;
case TCP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_TCP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_TCP);
break;
case UDP_V4_FLOW:
- hclge_fd_get_tcpip4_tuple(hdev, fs, rule, IPPROTO_UDP);
+ hclge_fd_get_tcpip4_tuple(fs, rule, IPPROTO_UDP);
break;
case IP_USER_FLOW:
- hclge_fd_get_ip4_tuple(hdev, fs, rule);
+ hclge_fd_get_ip4_tuple(fs, rule);
break;
case SCTP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_SCTP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_SCTP);
break;
case TCP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_TCP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_TCP);
break;
case UDP_V6_FLOW:
- hclge_fd_get_tcpip6_tuple(hdev, fs, rule, IPPROTO_UDP);
+ hclge_fd_get_tcpip6_tuple(fs, rule, IPPROTO_UDP);
break;
case IPV6_USER_FLOW:
- hclge_fd_get_ip6_tuple(hdev, fs, rule);
+ hclge_fd_get_ip6_tuple(fs, rule);
break;
case ETHER_FLOW:
- hclge_fd_get_ether_tuple(hdev, fs, rule);
+ hclge_fd_get_ether_tuple(fs, rule);
break;
default:
return -EOPNOTSUPP;
@@ -6578,7 +6474,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
if (!rule)
return -ENOMEM;
- ret = hclge_fd_get_tuple(hdev, fs, rule, &info);
+ ret = hclge_fd_get_tuple(fs, rule, &info);
if (ret) {
kfree(rule);
return ret;
@@ -7567,6 +7463,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
{
+#define HCLGE_LINK_STATUS_WAIT_CNT 3
+
struct hclge_desc desc;
struct hclge_config_mac_mode_cmd *req =
(struct hclge_config_mac_mode_cmd *)desc.data;
@@ -7591,9 +7489,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
- if (ret)
+ if (ret) {
dev_err(&hdev->pdev->dev,
"mac enable fail, ret =%d.\n", ret);
+ return;
+ }
+
+ if (!enable)
+ hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN,
+ HCLGE_LINK_STATUS_WAIT_CNT);
}
static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
@@ -7656,10 +7560,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
} while (++i < HCLGE_PHY_LINK_STATUS_NUM);
}
-static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
+static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
+ int wait_cnt)
{
-#define HCLGE_MAC_LINK_STATUS_NUM 100
-
int link_status;
int i = 0;
int ret;
@@ -7672,13 +7575,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
return 0;
msleep(HCLGE_LINK_STATUS_MS);
- } while (++i < HCLGE_MAC_LINK_STATUS_NUM);
+ } while (++i < wait_cnt);
return -EBUSY;
}
static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
bool is_phy)
{
+#define HCLGE_MAC_LINK_STATUS_NUM 100
+
int link_ret;
link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
@@ -7686,7 +7591,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
if (is_phy)
hclge_phy_link_status_wait(hdev, link_ret);
- return hclge_mac_link_status_wait(hdev, link_ret);
+ return hclge_mac_link_status_wait(hdev, link_ret,
+ HCLGE_MAC_LINK_STATUS_NUM);
}
static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
@@ -10924,9 +10830,12 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev)
u32 rx_pause, tx_pause;
u8 flowctl;
- if (!phydev->link || !phydev->autoneg)
+ if (!phydev->link)
return 0;
+ if (!phydev->autoneg)
+ return hclge_mac_pause_setup_hw(hdev);
+
local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising);
if (phydev->pause)
@@ -11117,6 +11026,7 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle,
static void hclge_info_show(struct hclge_dev *hdev)
{
+ struct hnae3_handle *handle = &hdev->vport->nic;
struct device *dev = &hdev->pdev->dev;
dev_info(dev, "PF info begin:\n");
@@ -11133,9 +11043,9 @@ static void hclge_info_show(struct hclge_dev *hdev)
dev_info(dev, "This is %s PF\n",
hdev->flag & HCLGE_FLAG_MAIN ? "main" : "not main");
dev_info(dev, "DCB %s\n",
- hdev->flag & HCLGE_FLAG_DCB_ENABLE ? "enable" : "disable");
+ handle->kinfo.tc_info.dcb_ets_active ? "enable" : "disable");
dev_info(dev, "MQPRIO %s\n",
- hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE ? "enable" : "disable");
+ handle->kinfo.tc_info.mqprio_active ? "enable" : "disable");
dev_info(dev, "Default tx spare buffer size: %u\n",
hdev->tx_spare_buf_size);
@@ -12377,463 +12287,6 @@ out:
return ret;
}
-static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit,
- u32 *regs_num_64_bit)
-{
- struct hclge_desc desc;
- u32 total_num;
- int ret;
-
- hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true);
- ret = hclge_cmd_send(&hdev->hw, &desc, 1);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Query register number cmd failed, ret = %d.\n", ret);
- return ret;
- }
-
- *regs_num_32_bit = le32_to_cpu(desc.data[0]);
- *regs_num_64_bit = le32_to_cpu(desc.data[1]);
-
- total_num = *regs_num_32_bit + *regs_num_64_bit;
- if (!total_num)
- return -EINVAL;
-
- return 0;
-}
-
-static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num,
- void *data)
-{
-#define HCLGE_32_BIT_REG_RTN_DATANUM 8
-#define HCLGE_32_BIT_DESC_NODATA_LEN 2
-
- struct hclge_desc *desc;
- u32 *reg_val = data;
- __le32 *desc_data;
- int nodata_num;
- int cmd_num;
- int i, k, n;
- int ret;
-
- if (regs_num == 0)
- return 0;
-
- nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN;
- cmd_num = DIV_ROUND_UP(regs_num + nodata_num,
- HCLGE_32_BIT_REG_RTN_DATANUM);
- desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true);
- ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Query 32 bit register cmd failed, ret = %d.\n", ret);
- kfree(desc);
- return ret;
- }
-
- for (i = 0; i < cmd_num; i++) {
- if (i == 0) {
- desc_data = (__le32 *)(&desc[i].data[0]);
- n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num;
- } else {
- desc_data = (__le32 *)(&desc[i]);
- n = HCLGE_32_BIT_REG_RTN_DATANUM;
- }
- for (k = 0; k < n; k++) {
- *reg_val++ = le32_to_cpu(*desc_data++);
-
- regs_num--;
- if (!regs_num)
- break;
- }
- }
-
- kfree(desc);
- return 0;
-}
-
-static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
- void *data)
-{
-#define HCLGE_64_BIT_REG_RTN_DATANUM 4
-#define HCLGE_64_BIT_DESC_NODATA_LEN 1
-
- struct hclge_desc *desc;
- u64 *reg_val = data;
- __le64 *desc_data;
- int nodata_len;
- int cmd_num;
- int i, k, n;
- int ret;
-
- if (regs_num == 0)
- return 0;
-
- nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN;
- cmd_num = DIV_ROUND_UP(regs_num + nodata_len,
- HCLGE_64_BIT_REG_RTN_DATANUM);
- desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
- if (!desc)
- return -ENOMEM;
-
- hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true);
- ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Query 64 bit register cmd failed, ret = %d.\n", ret);
- kfree(desc);
- return ret;
- }
-
- for (i = 0; i < cmd_num; i++) {
- if (i == 0) {
- desc_data = (__le64 *)(&desc[i].data[0]);
- n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len;
- } else {
- desc_data = (__le64 *)(&desc[i]);
- n = HCLGE_64_BIT_REG_RTN_DATANUM;
- }
- for (k = 0; k < n; k++) {
- *reg_val++ = le64_to_cpu(*desc_data++);
-
- regs_num--;
- if (!regs_num)
- break;
- }
- }
-
- kfree(desc);
- return 0;
-}
-
-#define MAX_SEPARATE_NUM 4
-#define SEPARATOR_VALUE 0xFDFCFBFA
-#define REG_NUM_PER_LINE 4
-#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32))
-#define REG_SEPARATOR_LINE 1
-#define REG_NUM_REMAIN_MASK 3
-
-int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc)
-{
- int i;
-
- /* initialize command BD except the last one */
- for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) {
- hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM,
- true);
- desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
- }
-
- /* initialize the last command BD */
- hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true);
-
- return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT);
-}
-
-static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev,
- int *bd_num_list,
- u32 type_num)
-{
- u32 entries_per_desc, desc_index, index, offset, i;
- struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT];
- int ret;
-
- ret = hclge_query_bd_num_cmd_send(hdev, desc);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get dfx bd num fail, status is %d.\n", ret);
- return ret;
- }
-
- entries_per_desc = ARRAY_SIZE(desc[0].data);
- for (i = 0; i < type_num; i++) {
- offset = hclge_dfx_bd_offset_list[i];
- index = offset % entries_per_desc;
- desc_index = offset / entries_per_desc;
- bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]);
- }
-
- return ret;
-}
-
-static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev,
- struct hclge_desc *desc_src, int bd_num,
- enum hclge_opcode_type cmd)
-{
- struct hclge_desc *desc = desc_src;
- int i, ret;
-
- hclge_cmd_setup_basic_desc(desc, cmd, true);
- for (i = 0; i < bd_num - 1; i++) {
- desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
- desc++;
- hclge_cmd_setup_basic_desc(desc, cmd, true);
- }
-
- desc = desc_src;
- ret = hclge_cmd_send(&hdev->hw, desc, bd_num);
- if (ret)
- dev_err(&hdev->pdev->dev,
- "Query dfx reg cmd(0x%x) send fail, status is %d.\n",
- cmd, ret);
-
- return ret;
-}
-
-static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num,
- void *data)
-{
- int entries_per_desc, reg_num, separator_num, desc_index, index, i;
- struct hclge_desc *desc = desc_src;
- u32 *reg = data;
-
- entries_per_desc = ARRAY_SIZE(desc->data);
- reg_num = entries_per_desc * bd_num;
- separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK);
- for (i = 0; i < reg_num; i++) {
- index = i % entries_per_desc;
- desc_index = i / entries_per_desc;
- *reg++ = le32_to_cpu(desc[desc_index].data[index]);
- }
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
-
- return reg_num + separator_num;
-}
-
-static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
-{
- u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
- int data_len_per_desc, bd_num, i;
- int *bd_num_list;
- u32 data_len;
- int ret;
-
- bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
- if (!bd_num_list)
- return -ENOMEM;
-
- ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get dfx reg bd num fail, status is %d.\n", ret);
- goto out;
- }
-
- data_len_per_desc = sizeof_field(struct hclge_desc, data);
- *len = 0;
- for (i = 0; i < dfx_reg_type_num; i++) {
- bd_num = bd_num_list[i];
- data_len = data_len_per_desc * bd_num;
- *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE;
- }
-
-out:
- kfree(bd_num_list);
- return ret;
-}
-
-static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
-{
- u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
- int bd_num, bd_num_max, buf_len, i;
- struct hclge_desc *desc_src;
- int *bd_num_list;
- u32 *reg = data;
- int ret;
-
- bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
- if (!bd_num_list)
- return -ENOMEM;
-
- ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get dfx reg bd num fail, status is %d.\n", ret);
- goto out;
- }
-
- bd_num_max = bd_num_list[0];
- for (i = 1; i < dfx_reg_type_num; i++)
- bd_num_max = max_t(int, bd_num_max, bd_num_list[i]);
-
- buf_len = sizeof(*desc_src) * bd_num_max;
- desc_src = kzalloc(buf_len, GFP_KERNEL);
- if (!desc_src) {
- ret = -ENOMEM;
- goto out;
- }
-
- for (i = 0; i < dfx_reg_type_num; i++) {
- bd_num = bd_num_list[i];
- ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num,
- hclge_dfx_reg_opcode_list[i]);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get dfx reg fail, status is %d.\n", ret);
- break;
- }
-
- reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg);
- }
-
- kfree(desc_src);
-out:
- kfree(bd_num_list);
- return ret;
-}
-
-static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
- struct hnae3_knic_private_info *kinfo)
-{
-#define HCLGE_RING_REG_OFFSET 0x200
-#define HCLGE_RING_INT_REG_OFFSET 0x4
-
- int i, j, reg_num, separator_num;
- int data_num_sum;
- u32 *reg = data;
-
- /* fetching per-PF registers valus from PF PCIe register space */
- reg_num = ARRAY_SIZE(cmdq_reg_addr_list);
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (i = 0; i < reg_num; i++)
- *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- data_num_sum = reg_num + separator_num;
-
- reg_num = ARRAY_SIZE(common_reg_addr_list);
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (i = 0; i < reg_num; i++)
- *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- data_num_sum += reg_num + separator_num;
-
- reg_num = ARRAY_SIZE(ring_reg_addr_list);
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (j = 0; j < kinfo->num_tqps; j++) {
- for (i = 0; i < reg_num; i++)
- *reg++ = hclge_read_dev(&hdev->hw,
- ring_reg_addr_list[i] +
- HCLGE_RING_REG_OFFSET * j);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- }
- data_num_sum += (reg_num + separator_num) * kinfo->num_tqps;
-
- reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list);
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (j = 0; j < hdev->num_msi_used - 1; j++) {
- for (i = 0; i < reg_num; i++)
- *reg++ = hclge_read_dev(&hdev->hw,
- tqp_intr_reg_addr_list[i] +
- HCLGE_RING_INT_REG_OFFSET * j);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- }
- data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1);
-
- return data_num_sum;
-}
-
-static int hclge_get_regs_len(struct hnae3_handle *handle)
-{
- int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
- struct hnae3_knic_private_info *kinfo = &handle->kinfo;
- struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_dev *hdev = vport->back;
- int regs_num_32_bit, regs_num_64_bit, dfx_regs_len;
- int regs_lines_32_bit, regs_lines_64_bit;
- int ret;
-
- ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get register number failed, ret = %d.\n", ret);
- return ret;
- }
-
- ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get dfx reg len failed, ret = %d.\n", ret);
- return ret;
- }
-
- cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
- common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
- ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
- tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
- regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
- regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE +
- REG_SEPARATOR_LINE;
-
- return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps +
- tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit +
- regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len;
-}
-
-static void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
- void *data)
-{
- struct hnae3_knic_private_info *kinfo = &handle->kinfo;
- struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_dev *hdev = vport->back;
- u32 regs_num_32_bit, regs_num_64_bit;
- int i, reg_num, separator_num, ret;
- u32 *reg = data;
-
- *version = hdev->fw_version;
-
- ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get register number failed, ret = %d.\n", ret);
- return;
- }
-
- reg += hclge_fetch_pf_reg(hdev, reg, kinfo);
-
- ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get 32 bit register failed, ret = %d.\n", ret);
- return;
- }
- reg_num = regs_num_32_bit;
- reg += reg_num;
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
-
- ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg);
- if (ret) {
- dev_err(&hdev->pdev->dev,
- "Get 64 bit register failed, ret = %d.\n", ret);
- return;
- }
- reg_num = regs_num_64_bit * 2;
- reg += reg_num;
- separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
-
- ret = hclge_get_dfx_reg(hdev, reg);
- if (ret)
- dev_err(&hdev->pdev->dev,
- "Get dfx register failed, ret = %d.\n", ret);
-}
-
static int hclge_set_led_status(struct hclge_dev *hdev, u8 locate_led_status)
{
struct hclge_set_led_state_cmd *req;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 81aa6b0facf5..70319ce49a1d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -835,15 +835,10 @@ struct hclge_vf_vlan_cfg {
* Then for input key(k) and mask(v), we can calculate the value by
* the formulae:
* x = (~k) & v
- * y = (k ^ ~v) & k
+ * y = k & v
*/
-#define calc_x(x, k, v) (x = ~(k) & (v))
-#define calc_y(y, k, v) \
- do { \
- const typeof(k) _k_ = (k); \
- const typeof(v) _v_ = (v); \
- (y) = (_k_ ^ ~_v_) & (_k_); \
- } while (0)
+#define calc_x(x, k, v) ((x) = ~(k) & (v))
+#define calc_y(y, k, v) ((y) = (k) & (v))
#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))
#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset)))
@@ -924,8 +919,6 @@ struct hclge_dev {
#define HCLGE_FLAG_MAIN BIT(0)
#define HCLGE_FLAG_DCB_CAPABLE BIT(1)
-#define HCLGE_FLAG_DCB_ENABLE BIT(2)
-#define HCLGE_FLAG_MQPRIO_ENABLE BIT(3)
u32 flag;
u32 pkt_buf_size; /* Total pf buf size for tx/rx */
@@ -1147,8 +1140,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
u16 state,
struct hclge_vlan_info *vlan_info);
void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time);
-int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev,
- struct hclge_desc *desc);
void hclge_report_hw_error(struct hclge_dev *hdev,
enum hnae3_hw_error_type type);
void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
new file mode 100644
index 000000000000..43c1c18fa81f
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2023 Hisilicon Limited.
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_regs.h"
+#include "hnae3.h"
+
+static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG,
+ HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG,
+ HCLGE_COMM_NIC_CSQ_DEPTH_REG,
+ HCLGE_COMM_NIC_CSQ_TAIL_REG,
+ HCLGE_COMM_NIC_CSQ_HEAD_REG,
+ HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG,
+ HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG,
+ HCLGE_COMM_NIC_CRQ_DEPTH_REG,
+ HCLGE_COMM_NIC_CRQ_TAIL_REG,
+ HCLGE_COMM_NIC_CRQ_HEAD_REG,
+ HCLGE_COMM_VECTOR0_CMDQ_SRC_REG,
+ HCLGE_COMM_CMDQ_INTR_STS_REG,
+ HCLGE_COMM_CMDQ_INTR_EN_REG,
+ HCLGE_COMM_CMDQ_INTR_GEN_REG};
+
+static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE,
+ HCLGE_PF_OTHER_INT_REG,
+ HCLGE_MISC_RESET_STS_REG,
+ HCLGE_MISC_VECTOR_INT_STS,
+ HCLGE_GLOBAL_RESET_REG,
+ HCLGE_FUN_RST_ING,
+ HCLGE_GRO_EN_REG};
+
+static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG,
+ HCLGE_RING_RX_ADDR_H_REG,
+ HCLGE_RING_RX_BD_NUM_REG,
+ HCLGE_RING_RX_BD_LENGTH_REG,
+ HCLGE_RING_RX_MERGE_EN_REG,
+ HCLGE_RING_RX_TAIL_REG,
+ HCLGE_RING_RX_HEAD_REG,
+ HCLGE_RING_RX_FBD_NUM_REG,
+ HCLGE_RING_RX_OFFSET_REG,
+ HCLGE_RING_RX_FBD_OFFSET_REG,
+ HCLGE_RING_RX_STASH_REG,
+ HCLGE_RING_RX_BD_ERR_REG,
+ HCLGE_RING_TX_ADDR_L_REG,
+ HCLGE_RING_TX_ADDR_H_REG,
+ HCLGE_RING_TX_BD_NUM_REG,
+ HCLGE_RING_TX_PRIORITY_REG,
+ HCLGE_RING_TX_TC_REG,
+ HCLGE_RING_TX_MERGE_EN_REG,
+ HCLGE_RING_TX_TAIL_REG,
+ HCLGE_RING_TX_HEAD_REG,
+ HCLGE_RING_TX_FBD_NUM_REG,
+ HCLGE_RING_TX_OFFSET_REG,
+ HCLGE_RING_TX_EBD_NUM_REG,
+ HCLGE_RING_TX_EBD_OFFSET_REG,
+ HCLGE_RING_TX_BD_ERR_REG,
+ HCLGE_RING_EN_REG};
+
+static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG,
+ HCLGE_TQP_INTR_GL0_REG,
+ HCLGE_TQP_INTR_GL1_REG,
+ HCLGE_TQP_INTR_GL2_REG,
+ HCLGE_TQP_INTR_RL_REG};
+
+/* Get DFX BD number offset */
+#define HCLGE_DFX_BIOS_BD_OFFSET 1
+#define HCLGE_DFX_SSU_0_BD_OFFSET 2
+#define HCLGE_DFX_SSU_1_BD_OFFSET 3
+#define HCLGE_DFX_IGU_BD_OFFSET 4
+#define HCLGE_DFX_RPU_0_BD_OFFSET 5
+#define HCLGE_DFX_RPU_1_BD_OFFSET 6
+#define HCLGE_DFX_NCSI_BD_OFFSET 7
+#define HCLGE_DFX_RTC_BD_OFFSET 8
+#define HCLGE_DFX_PPP_BD_OFFSET 9
+#define HCLGE_DFX_RCB_BD_OFFSET 10
+#define HCLGE_DFX_TQP_BD_OFFSET 11
+#define HCLGE_DFX_SSU_2_BD_OFFSET 12
+
+static const u32 hclge_dfx_bd_offset_list[] = {
+ HCLGE_DFX_BIOS_BD_OFFSET,
+ HCLGE_DFX_SSU_0_BD_OFFSET,
+ HCLGE_DFX_SSU_1_BD_OFFSET,
+ HCLGE_DFX_IGU_BD_OFFSET,
+ HCLGE_DFX_RPU_0_BD_OFFSET,
+ HCLGE_DFX_RPU_1_BD_OFFSET,
+ HCLGE_DFX_NCSI_BD_OFFSET,
+ HCLGE_DFX_RTC_BD_OFFSET,
+ HCLGE_DFX_PPP_BD_OFFSET,
+ HCLGE_DFX_RCB_BD_OFFSET,
+ HCLGE_DFX_TQP_BD_OFFSET,
+ HCLGE_DFX_SSU_2_BD_OFFSET
+};
+
+static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = {
+ HCLGE_OPC_DFX_BIOS_COMMON_REG,
+ HCLGE_OPC_DFX_SSU_REG_0,
+ HCLGE_OPC_DFX_SSU_REG_1,
+ HCLGE_OPC_DFX_IGU_EGU_REG,
+ HCLGE_OPC_DFX_RPU_REG_0,
+ HCLGE_OPC_DFX_RPU_REG_1,
+ HCLGE_OPC_DFX_NCSI_REG,
+ HCLGE_OPC_DFX_RTC_REG,
+ HCLGE_OPC_DFX_PPP_REG,
+ HCLGE_OPC_DFX_RCB_REG,
+ HCLGE_OPC_DFX_TQP_REG,
+ HCLGE_OPC_DFX_SSU_REG_2
+};
+
+enum hclge_reg_tag {
+ HCLGE_REG_TAG_CMDQ = 0,
+ HCLGE_REG_TAG_COMMON,
+ HCLGE_REG_TAG_RING,
+ HCLGE_REG_TAG_TQP_INTR,
+ HCLGE_REG_TAG_QUERY_32_BIT,
+ HCLGE_REG_TAG_QUERY_64_BIT,
+ HCLGE_REG_TAG_DFX_BIOS_COMMON,
+ HCLGE_REG_TAG_DFX_SSU_0,
+ HCLGE_REG_TAG_DFX_SSU_1,
+ HCLGE_REG_TAG_DFX_IGU_EGU,
+ HCLGE_REG_TAG_DFX_RPU_0,
+ HCLGE_REG_TAG_DFX_RPU_1,
+ HCLGE_REG_TAG_DFX_NCSI,
+ HCLGE_REG_TAG_DFX_RTC,
+ HCLGE_REG_TAG_DFX_PPP,
+ HCLGE_REG_TAG_DFX_RCB,
+ HCLGE_REG_TAG_DFX_TQP,
+ HCLGE_REG_TAG_DFX_SSU_2,
+ HCLGE_REG_TAG_RPU_TNL,
+};
+
+#pragma pack(4)
+struct hclge_reg_tlv {
+ u16 tag;
+ u16 len;
+};
+
+struct hclge_reg_header {
+ u64 magic_number;
+ u8 is_vf;
+ u8 rsv[7];
+};
+
+#pragma pack()
+
+#define HCLGE_REG_TLV_SIZE sizeof(struct hclge_reg_tlv)
+#define HCLGE_REG_HEADER_SIZE sizeof(struct hclge_reg_header)
+#define HCLGE_REG_TLV_SPACE (sizeof(struct hclge_reg_tlv) / sizeof(u32))
+#define HCLGE_REG_HEADER_SPACE (sizeof(struct hclge_reg_header) / sizeof(u32))
+#define HCLGE_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */
+
+#define HCLGE_REG_RPU_TNL_ID_0 1
+
+static u32 hclge_reg_get_header(void *data)
+{
+ struct hclge_reg_header *header = data;
+
+ header->magic_number = HCLGE_REG_MAGIC_NUMBER;
+ header->is_vf = 0x0;
+
+ return HCLGE_REG_HEADER_SPACE;
+}
+
+static u32 hclge_reg_get_tlv(u32 tag, u32 regs_num, void *data)
+{
+ struct hclge_reg_tlv *tlv = data;
+
+ tlv->tag = tag;
+ tlv->len = regs_num * sizeof(u32) + HCLGE_REG_TLV_SIZE;
+
+ return HCLGE_REG_TLV_SPACE;
+}
+
+static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num,
+ void *data)
+{
+#define HCLGE_32_BIT_REG_RTN_DATANUM 8
+#define HCLGE_32_BIT_DESC_NODATA_LEN 2
+
+ struct hclge_desc *desc;
+ u32 *reg_val = data;
+ __le32 *desc_data;
+ int nodata_num;
+ int cmd_num;
+ int i, k, n;
+ int ret;
+
+ if (regs_num == 0)
+ return 0;
+
+ nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN;
+ cmd_num = DIV_ROUND_UP(regs_num + nodata_num,
+ HCLGE_32_BIT_REG_RTN_DATANUM);
+ desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true);
+ ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query 32 bit register cmd failed, ret = %d.\n", ret);
+ kfree(desc);
+ return ret;
+ }
+
+ for (i = 0; i < cmd_num; i++) {
+ if (i == 0) {
+ desc_data = (__le32 *)(&desc[i].data[0]);
+ n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num;
+ } else {
+ desc_data = (__le32 *)(&desc[i]);
+ n = HCLGE_32_BIT_REG_RTN_DATANUM;
+ }
+ for (k = 0; k < n; k++) {
+ *reg_val++ = le32_to_cpu(*desc_data++);
+
+ regs_num--;
+ if (!regs_num)
+ break;
+ }
+ }
+
+ kfree(desc);
+ return 0;
+}
+
+static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
+ void *data)
+{
+#define HCLGE_64_BIT_REG_RTN_DATANUM 4
+#define HCLGE_64_BIT_DESC_NODATA_LEN 1
+
+ struct hclge_desc *desc;
+ u64 *reg_val = data;
+ __le64 *desc_data;
+ int nodata_len;
+ int cmd_num;
+ int i, k, n;
+ int ret;
+
+ if (regs_num == 0)
+ return 0;
+
+ nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN;
+ cmd_num = DIV_ROUND_UP(regs_num + nodata_len,
+ HCLGE_64_BIT_REG_RTN_DATANUM);
+ desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true);
+ ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query 64 bit register cmd failed, ret = %d.\n", ret);
+ kfree(desc);
+ return ret;
+ }
+
+ for (i = 0; i < cmd_num; i++) {
+ if (i == 0) {
+ desc_data = (__le64 *)(&desc[i].data[0]);
+ n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len;
+ } else {
+ desc_data = (__le64 *)(&desc[i]);
+ n = HCLGE_64_BIT_REG_RTN_DATANUM;
+ }
+ for (k = 0; k < n; k++) {
+ *reg_val++ = le64_to_cpu(*desc_data++);
+
+ regs_num--;
+ if (!regs_num)
+ break;
+ }
+ }
+
+ kfree(desc);
+ return 0;
+}
+
+int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc)
+{
+ int i;
+
+ /* initialize command BD except the last one */
+ for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) {
+ hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM,
+ true);
+ desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
+ }
+
+ /* initialize the last command BD */
+ hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true);
+
+ return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT);
+}
+
+static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev,
+ int *bd_num_list,
+ u32 type_num)
+{
+ u32 entries_per_desc, desc_index, index, offset, i;
+ struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT];
+ int ret;
+
+ ret = hclge_query_bd_num_cmd_send(hdev, desc);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get dfx bd num fail, status is %d.\n", ret);
+ return ret;
+ }
+
+ entries_per_desc = ARRAY_SIZE(desc[0].data);
+ for (i = 0; i < type_num; i++) {
+ offset = hclge_dfx_bd_offset_list[i];
+ index = offset % entries_per_desc;
+ desc_index = offset / entries_per_desc;
+ bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]);
+ }
+
+ return ret;
+}
+
+static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev,
+ struct hclge_desc *desc_src, int bd_num,
+ enum hclge_opcode_type cmd)
+{
+ struct hclge_desc *desc = desc_src;
+ int i, ret;
+
+ hclge_cmd_setup_basic_desc(desc, cmd, true);
+ for (i = 0; i < bd_num - 1; i++) {
+ desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
+ desc++;
+ hclge_cmd_setup_basic_desc(desc, cmd, true);
+ }
+
+ desc = desc_src;
+ ret = hclge_cmd_send(&hdev->hw, desc, bd_num);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "Query dfx reg cmd(0x%x) send fail, status is %d.\n",
+ cmd, ret);
+
+ return ret;
+}
+
+/* tnl_id = 0 means get sum of all tnl reg's value */
+static int hclge_dfx_reg_rpu_tnl_cmd_send(struct hclge_dev *hdev, u32 tnl_id,
+ struct hclge_desc *desc, int bd_num)
+{
+ int i, ret;
+
+ for (i = 0; i < bd_num; i++) {
+ hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_RPU_REG_0,
+ true);
+ if (i != bd_num - 1)
+ desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
+ }
+
+ desc[0].data[0] = cpu_to_le32(tnl_id);
+ ret = hclge_cmd_send(&hdev->hw, desc, bd_num);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "failed to query dfx rpu tnl reg, ret = %d\n",
+ ret);
+ return ret;
+}
+
+static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num,
+ void *data)
+{
+ int entries_per_desc, reg_num, desc_index, index, i;
+ struct hclge_desc *desc = desc_src;
+ u32 *reg = data;
+
+ entries_per_desc = ARRAY_SIZE(desc->data);
+ reg_num = entries_per_desc * bd_num;
+ for (i = 0; i < reg_num; i++) {
+ index = i % entries_per_desc;
+ desc_index = i / entries_per_desc;
+ *reg++ = le32_to_cpu(desc[desc_index].data[index]);
+ }
+
+ return reg_num;
+}
+
+static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
+{
+ u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
+ int data_len_per_desc;
+ int *bd_num_list;
+ int ret;
+ u32 i;
+
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
+ if (!bd_num_list)
+ return -ENOMEM;
+
+ ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get dfx reg bd num fail, status is %d.\n", ret);
+ goto out;
+ }
+
+ data_len_per_desc = sizeof_field(struct hclge_desc, data);
+ *len = 0;
+ for (i = 0; i < dfx_reg_type_num; i++)
+ *len += bd_num_list[i] * data_len_per_desc + HCLGE_REG_TLV_SIZE;
+
+ /**
+ * the num of dfx_rpu_0 is reused by each dfx_rpu_tnl
+ * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is
+ * starting at 0, so offset need '- 1'.
+ */
+ *len += (bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1] * data_len_per_desc +
+ HCLGE_REG_TLV_SIZE) * ae_dev->dev_specs.tnl_num;
+
+out:
+ kfree(bd_num_list);
+ return ret;
+}
+
+static int hclge_get_dfx_rpu_tnl_reg(struct hclge_dev *hdev, u32 *reg,
+ struct hclge_desc *desc_src,
+ int bd_num)
+{
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
+ int ret = 0;
+ u8 i;
+
+ for (i = HCLGE_REG_RPU_TNL_ID_0; i <= ae_dev->dev_specs.tnl_num; i++) {
+ ret = hclge_dfx_reg_rpu_tnl_cmd_send(hdev, i, desc_src, bd_num);
+ if (ret)
+ break;
+
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RPU_TNL,
+ ARRAY_SIZE(desc_src->data) * bd_num,
+ reg);
+ reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg);
+ }
+
+ return ret;
+}
+
+static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
+{
+ u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
+ int bd_num, bd_num_max, buf_len;
+ struct hclge_desc *desc_src;
+ int *bd_num_list;
+ u32 *reg = data;
+ int ret;
+ u32 i;
+
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
+ if (!bd_num_list)
+ return -ENOMEM;
+
+ ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get dfx reg bd num fail, status is %d.\n", ret);
+ goto out;
+ }
+
+ bd_num_max = bd_num_list[0];
+ for (i = 1; i < dfx_reg_type_num; i++)
+ bd_num_max = max_t(int, bd_num_max, bd_num_list[i]);
+
+ buf_len = sizeof(*desc_src) * bd_num_max;
+ desc_src = kzalloc(buf_len, GFP_KERNEL);
+ if (!desc_src) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < dfx_reg_type_num; i++) {
+ bd_num = bd_num_list[i];
+ ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num,
+ hclge_dfx_reg_opcode_list[i]);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get dfx reg fail, status is %d.\n", ret);
+ goto free;
+ }
+
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_DFX_BIOS_COMMON + i,
+ ARRAY_SIZE(desc_src->data) * bd_num,
+ reg);
+ reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg);
+ }
+
+ /**
+ * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is
+ * starting at 0, so offset need '- 1'.
+ */
+ bd_num = bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1];
+ ret = hclge_get_dfx_rpu_tnl_reg(hdev, reg, desc_src, bd_num);
+
+free:
+ kfree(desc_src);
+out:
+ kfree(bd_num_list);
+ return ret;
+}
+
+static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
+ struct hnae3_knic_private_info *kinfo)
+{
+#define HCLGE_RING_REG_OFFSET 0x200
+#define HCLGE_RING_INT_REG_OFFSET 0x4
+
+ int i, j, reg_num;
+ int data_num_sum;
+ u32 *reg = data;
+
+ /* fetching per-PF registers valus from PF PCIe register space */
+ reg_num = ARRAY_SIZE(cmdq_reg_addr_list);
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_CMDQ, reg_num, reg);
+ for (i = 0; i < reg_num; i++)
+ *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
+ data_num_sum = reg_num + HCLGE_REG_TLV_SPACE;
+
+ reg_num = ARRAY_SIZE(common_reg_addr_list);
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_COMMON, reg_num, reg);
+ for (i = 0; i < reg_num; i++)
+ *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]);
+ data_num_sum += reg_num + HCLGE_REG_TLV_SPACE;
+
+ reg_num = ARRAY_SIZE(ring_reg_addr_list);
+ for (j = 0; j < kinfo->num_tqps; j++) {
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg);
+ for (i = 0; i < reg_num; i++)
+ *reg++ = hclge_read_dev(&hdev->hw,
+ ring_reg_addr_list[i] +
+ HCLGE_RING_REG_OFFSET * j);
+ }
+ data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps;
+
+ reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list);
+ for (j = 0; j < hdev->num_msi_used - 1; j++) {
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_TQP_INTR, reg_num, reg);
+ for (i = 0; i < reg_num; i++)
+ *reg++ = hclge_read_dev(&hdev->hw,
+ tqp_intr_reg_addr_list[i] +
+ HCLGE_RING_INT_REG_OFFSET * j);
+ }
+ data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) *
+ (hdev->num_msi_used - 1);
+
+ return data_num_sum;
+}
+
+static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit,
+ u32 *regs_num_64_bit)
+{
+ struct hclge_desc desc;
+ u32 total_num;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true);
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query register number cmd failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ *regs_num_32_bit = le32_to_cpu(desc.data[0]);
+ *regs_num_64_bit = le32_to_cpu(desc.data[1]);
+
+ total_num = *regs_num_32_bit + *regs_num_64_bit;
+ if (!total_num)
+ return -EINVAL;
+
+ return 0;
+}
+
+int hclge_get_regs_len(struct hnae3_handle *handle)
+{
+ struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ int regs_num_32_bit, regs_num_64_bit, dfx_regs_len;
+ int cmdq_len, common_len, ring_len, tqp_intr_len;
+ int regs_len_32_bit, regs_len_64_bit;
+ struct hclge_dev *hdev = vport->back;
+ int ret;
+
+ ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get register number failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get dfx reg len failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ cmdq_len = HCLGE_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list);
+ common_len = HCLGE_REG_TLV_SIZE + sizeof(common_reg_addr_list);
+ ring_len = HCLGE_REG_TLV_SIZE + sizeof(ring_reg_addr_list);
+ tqp_intr_len = HCLGE_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list);
+ regs_len_32_bit = HCLGE_REG_TLV_SIZE + regs_num_32_bit * sizeof(u32);
+ regs_len_64_bit = HCLGE_REG_TLV_SIZE + regs_num_64_bit * sizeof(u64);
+
+ /* return the total length of all register values */
+ return HCLGE_REG_HEADER_SIZE + cmdq_len + common_len + ring_len *
+ kinfo->num_tqps + tqp_intr_len * (hdev->num_msi_used - 1) +
+ regs_len_32_bit + regs_len_64_bit + dfx_regs_len;
+}
+
+void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
+ void *data)
+{
+#define HCLGE_REG_64_BIT_SPACE_MULTIPLE 2
+
+ struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ u32 regs_num_32_bit, regs_num_64_bit;
+ u32 *reg = data;
+ int ret;
+
+ *version = hdev->fw_version;
+
+ ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get register number failed, ret = %d.\n", ret);
+ return;
+ }
+
+ reg += hclge_reg_get_header(reg);
+ reg += hclge_fetch_pf_reg(hdev, reg, kinfo);
+
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_32_BIT,
+ regs_num_32_bit, reg);
+ ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get 32 bit register failed, ret = %d.\n", ret);
+ return;
+ }
+ reg += regs_num_32_bit;
+
+ reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_64_BIT,
+ regs_num_64_bit *
+ HCLGE_REG_64_BIT_SPACE_MULTIPLE, reg);
+ ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get 64 bit register failed, ret = %d.\n", ret);
+ return;
+ }
+ reg += regs_num_64_bit * HCLGE_REG_64_BIT_SPACE_MULTIPLE;
+
+ ret = hclge_get_dfx_reg(hdev, reg);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "Get dfx register failed, ret = %d.\n", ret);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h
new file mode 100644
index 000000000000..b6bc1ecb8054
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+// Copyright (c) 2023 Hisilicon Limited.
+
+#ifndef __HCLGE_REGS_H
+#define __HCLGE_REGS_H
+#include <linux/types.h>
+#include "hclge_comm_cmd.h"
+
+struct hnae3_handle;
+struct hclge_dev;
+
+int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev,
+ struct hclge_desc *desc);
+int hclge_get_regs_len(struct hnae3_handle *handle);
+void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
+ void *data);
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 922c0da3660c..c58c31221762 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -785,6 +785,7 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
{
#define BW_PERCENT 100
+#define DEFAULT_BW_WEIGHT 1
u8 i;
@@ -806,7 +807,7 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
for (k = 0; k < hdev->tm_info.num_tc; k++)
hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
for (; k < HNAE3_MAX_TC; k++)
- hdev->tm_info.pg_info[i].tc_dwrr[k] = 0;
+ hdev->tm_info.pg_info[i].tc_dwrr[k] = DEFAULT_BW_WEIGHT;
}
}
@@ -1484,7 +1485,11 @@ int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
return ret;
/* Cfg schd mode for each level schd */
- return hclge_tm_schd_mode_hw(hdev);
+ ret = hclge_tm_schd_mode_hw(hdev);
+ if (ret)
+ return ret;
+
+ return hclge_tm_flush_cfg(hdev, false);
}
static int hclge_pause_param_setup_hw(struct hclge_dev *hdev)
@@ -1548,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)
return 0;
}
-static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
{
bool tx_en, rx_en;
@@ -2113,3 +2118,28 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
return 0;
}
+
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable)
+{
+ struct hclge_desc desc;
+ int ret;
+
+ if (!hnae3_ae_dev_tm_flush_supported(hdev))
+ return 0;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_FLUSH, false);
+
+ desc.data[0] = cpu_to_le32(enable ? HCLGE_TM_FLUSH_EN_MSK : 0);
+
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "failed to config tm flush, ret = %d\n", ret);
+ return ret;
+ }
+
+ if (enable)
+ msleep(HCLGE_TM_FLUSH_TIME_MS);
+
+ return ret;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index dd6f1fd486cf..53eec6df5194 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -33,6 +33,9 @@ enum hclge_opcode_type;
#define HCLGE_DSCP_MAP_TC_BD_NUM 2
#define HCLGE_DSCP_TC_SHIFT(n) (((n) & 1) * 4)
+#define HCLGE_TM_FLUSH_TIME_MS 10
+#define HCLGE_TM_FLUSH_EN_MSK BIT(0)
+
struct hclge_pg_to_pri_link_cmd {
u8 pg_id;
u8 rsvd1[3];
@@ -242,6 +245,7 @@ int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
u8 pfc_bitmap);
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
+int hclge_mac_pause_setup_hw(struct hclge_dev *hdev);
void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
@@ -272,4 +276,5 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
struct hclge_tm_shaper_para *para);
int hclge_up_to_tc_map(struct hclge_dev *hdev);
int hclge_dscp_to_tc_map(struct hclge_dev *hdev);
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index dd08989a4c7c..7a2f9233d695 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -6,6 +6,7 @@
#include <net/rtnetlink.h>
#include "hclgevf_cmd.h"
#include "hclgevf_main.h"
+#include "hclgevf_regs.h"
#include "hclge_mbx.h"
#include "hnae3.h"
#include "hclgevf_devlink.h"
@@ -33,58 +34,6 @@ static const struct pci_device_id ae_algovf_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl);
-static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG,
- HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG,
- HCLGE_COMM_NIC_CSQ_DEPTH_REG,
- HCLGE_COMM_NIC_CSQ_TAIL_REG,
- HCLGE_COMM_NIC_CSQ_HEAD_REG,
- HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG,
- HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG,
- HCLGE_COMM_NIC_CRQ_DEPTH_REG,
- HCLGE_COMM_NIC_CRQ_TAIL_REG,
- HCLGE_COMM_NIC_CRQ_HEAD_REG,
- HCLGE_COMM_VECTOR0_CMDQ_SRC_REG,
- HCLGE_COMM_VECTOR0_CMDQ_STATE_REG,
- HCLGE_COMM_CMDQ_INTR_EN_REG,
- HCLGE_COMM_CMDQ_INTR_GEN_REG};
-
-static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE,
- HCLGEVF_RST_ING,
- HCLGEVF_GRO_EN_REG};
-
-static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG,
- HCLGEVF_RING_RX_ADDR_H_REG,
- HCLGEVF_RING_RX_BD_NUM_REG,
- HCLGEVF_RING_RX_BD_LENGTH_REG,
- HCLGEVF_RING_RX_MERGE_EN_REG,
- HCLGEVF_RING_RX_TAIL_REG,
- HCLGEVF_RING_RX_HEAD_REG,
- HCLGEVF_RING_RX_FBD_NUM_REG,
- HCLGEVF_RING_RX_OFFSET_REG,
- HCLGEVF_RING_RX_FBD_OFFSET_REG,
- HCLGEVF_RING_RX_STASH_REG,
- HCLGEVF_RING_RX_BD_ERR_REG,
- HCLGEVF_RING_TX_ADDR_L_REG,
- HCLGEVF_RING_TX_ADDR_H_REG,
- HCLGEVF_RING_TX_BD_NUM_REG,
- HCLGEVF_RING_TX_PRIORITY_REG,
- HCLGEVF_RING_TX_TC_REG,
- HCLGEVF_RING_TX_MERGE_EN_REG,
- HCLGEVF_RING_TX_TAIL_REG,
- HCLGEVF_RING_TX_HEAD_REG,
- HCLGEVF_RING_TX_FBD_NUM_REG,
- HCLGEVF_RING_TX_OFFSET_REG,
- HCLGEVF_RING_TX_EBD_NUM_REG,
- HCLGEVF_RING_TX_EBD_OFFSET_REG,
- HCLGEVF_RING_TX_BD_ERR_REG,
- HCLGEVF_RING_EN_REG};
-
-static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG,
- HCLGEVF_TQP_INTR_GL0_REG,
- HCLGEVF_TQP_INTR_GL1_REG,
- HCLGEVF_TQP_INTR_GL2_REG,
- HCLGEVF_TQP_INTR_RL_REG};
-
/* hclgevf_cmd_send - send command to command queue
* @hw: pointer to the hw struct
* @desc: prefilled descriptor for describing the command
@@ -111,7 +60,7 @@ void hclgevf_arq_init(struct hclgevf_dev *hdev)
spin_unlock(&cmdq->crq.lock);
}
-static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
+struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
{
if (!handle->client)
return container_of(handle, struct hclgevf_dev, nic);
@@ -121,8 +70,7 @@ static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
return container_of(handle, struct hclgevf_dev, nic);
}
-static void hclgevf_update_stats(struct hnae3_handle *handle,
- struct net_device_stats *net_stats)
+static void hclgevf_update_stats(struct hnae3_handle *handle)
{
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
int status;
@@ -1645,8 +1593,7 @@ err_reset:
hclgevf_reset_err_handle(hdev);
}
-static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
- unsigned long *addr)
+static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr)
{
enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
@@ -1685,8 +1632,7 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
if (hdev->default_reset_request)
hdev->reset_level =
- hclgevf_get_reset_level(hdev,
- &hdev->default_reset_request);
+ hclgevf_get_reset_level(&hdev->default_reset_request);
else
hdev->reset_level = HNAE3_VF_FUNC_RESET;
@@ -1828,7 +1774,7 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
hdev->last_reset_time = jiffies;
hdev->reset_type =
- hclgevf_get_reset_level(hdev, &hdev->reset_pending);
+ hclgevf_get_reset_level(&hdev->reset_pending);
if (hdev->reset_type != HNAE3_NONE_RESET)
hclgevf_reset(hdev);
} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
@@ -2160,8 +2106,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
if (ret)
return ret;
- ret = hclge_comm_set_rss_input_tuple(&hdev->nic, &hdev->hw.hw,
- false, rss_cfg);
+ ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, rss_cfg);
if (ret)
return ret;
}
@@ -3262,72 +3207,6 @@ static void hclgevf_get_link_mode(struct hnae3_handle *handle,
*advertising = hdev->hw.mac.advertising;
}
-#define MAX_SEPARATE_NUM 4
-#define SEPARATOR_VALUE 0xFDFCFBFA
-#define REG_NUM_PER_LINE 4
-#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32))
-
-static int hclgevf_get_regs_len(struct hnae3_handle *handle)
-{
- int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
- struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
-
- cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1;
- common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1;
- ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1;
- tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1;
-
- return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps +
- tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE;
-}
-
-static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
- void *data)
-{
- struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
- int i, j, reg_um, separator_num;
- u32 *reg = data;
-
- *version = hdev->fw_version;
-
- /* fetching per-VF registers values from VF PCIe register space */
- reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32);
- separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
- for (i = 0; i < reg_um; i++)
- *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
-
- reg_um = sizeof(common_reg_addr_list) / sizeof(u32);
- separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
- for (i = 0; i < reg_um; i++)
- *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
-
- reg_um = sizeof(ring_reg_addr_list) / sizeof(u32);
- separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
- for (j = 0; j < hdev->num_tqps; j++) {
- for (i = 0; i < reg_um; i++)
- *reg++ = hclgevf_read_dev(&hdev->hw,
- ring_reg_addr_list[i] +
- HCLGEVF_TQP_REG_SIZE * j);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- }
-
- reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32);
- separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
- for (j = 0; j < hdev->num_msi_used - 1; j++) {
- for (i = 0; i < reg_um; i++)
- *reg++ = hclgevf_read_dev(&hdev->hw,
- tqp_intr_reg_addr_list[i] +
- 4 * j);
- for (i = 0; i < separator_num; i++)
- *reg++ = SEPARATOR_VALUE;
- }
-}
-
void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
struct hclge_mbx_port_base_vlan *port_base_vlan)
{
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
index 59ca6c794d6d..81c16b8c8da2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -294,4 +294,5 @@ void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev);
void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev);
void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
struct hclge_mbx_port_base_vlan *port_base_vlan);
+struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
new file mode 100644
index 000000000000..197ab733306b
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2023 Hisilicon Limited.
+
+#include "hclgevf_main.h"
+#include "hclgevf_regs.h"
+#include "hnae3.h"
+
+static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG,
+ HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG,
+ HCLGE_COMM_NIC_CSQ_DEPTH_REG,
+ HCLGE_COMM_NIC_CSQ_TAIL_REG,
+ HCLGE_COMM_NIC_CSQ_HEAD_REG,
+ HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG,
+ HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG,
+ HCLGE_COMM_NIC_CRQ_DEPTH_REG,
+ HCLGE_COMM_NIC_CRQ_TAIL_REG,
+ HCLGE_COMM_NIC_CRQ_HEAD_REG,
+ HCLGE_COMM_VECTOR0_CMDQ_SRC_REG,
+ HCLGE_COMM_VECTOR0_CMDQ_STATE_REG,
+ HCLGE_COMM_CMDQ_INTR_EN_REG,
+ HCLGE_COMM_CMDQ_INTR_GEN_REG};
+
+static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE,
+ HCLGEVF_RST_ING,
+ HCLGEVF_GRO_EN_REG};
+
+static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG,
+ HCLGEVF_RING_RX_ADDR_H_REG,
+ HCLGEVF_RING_RX_BD_NUM_REG,
+ HCLGEVF_RING_RX_BD_LENGTH_REG,
+ HCLGEVF_RING_RX_MERGE_EN_REG,
+ HCLGEVF_RING_RX_TAIL_REG,
+ HCLGEVF_RING_RX_HEAD_REG,
+ HCLGEVF_RING_RX_FBD_NUM_REG,
+ HCLGEVF_RING_RX_OFFSET_REG,
+ HCLGEVF_RING_RX_FBD_OFFSET_REG,
+ HCLGEVF_RING_RX_STASH_REG,
+ HCLGEVF_RING_RX_BD_ERR_REG,
+ HCLGEVF_RING_TX_ADDR_L_REG,
+ HCLGEVF_RING_TX_ADDR_H_REG,
+ HCLGEVF_RING_TX_BD_NUM_REG,
+ HCLGEVF_RING_TX_PRIORITY_REG,
+ HCLGEVF_RING_TX_TC_REG,
+ HCLGEVF_RING_TX_MERGE_EN_REG,
+ HCLGEVF_RING_TX_TAIL_REG,
+ HCLGEVF_RING_TX_HEAD_REG,
+ HCLGEVF_RING_TX_FBD_NUM_REG,
+ HCLGEVF_RING_TX_OFFSET_REG,
+ HCLGEVF_RING_TX_EBD_NUM_REG,
+ HCLGEVF_RING_TX_EBD_OFFSET_REG,
+ HCLGEVF_RING_TX_BD_ERR_REG,
+ HCLGEVF_RING_EN_REG};
+
+static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG,
+ HCLGEVF_TQP_INTR_GL0_REG,
+ HCLGEVF_TQP_INTR_GL1_REG,
+ HCLGEVF_TQP_INTR_GL2_REG,
+ HCLGEVF_TQP_INTR_RL_REG};
+
+#define MAX_SEPARATE_NUM 4
+#define SEPARATOR_VALUE 0xFDFCFBFA
+#define REG_NUM_PER_LINE 4
+#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32))
+
+int hclgevf_get_regs_len(struct hnae3_handle *handle)
+{
+ int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+
+ cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1;
+ common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1;
+ ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1;
+ tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1;
+
+ return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps +
+ tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE;
+}
+
+void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
+ void *data)
+{
+#define HCLGEVF_RING_REG_OFFSET 0x200
+#define HCLGEVF_RING_INT_REG_OFFSET 0x4
+
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+ int i, j, reg_um, separator_num;
+ u32 *reg = data;
+
+ *version = hdev->fw_version;
+
+ /* fetching per-VF registers values from VF PCIe register space */
+ reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32);
+ separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
+ for (i = 0; i < reg_um; i++)
+ *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
+ for (i = 0; i < separator_num; i++)
+ *reg++ = SEPARATOR_VALUE;
+
+ reg_um = sizeof(common_reg_addr_list) / sizeof(u32);
+ separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
+ for (i = 0; i < reg_um; i++)
+ *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]);
+ for (i = 0; i < separator_num; i++)
+ *reg++ = SEPARATOR_VALUE;
+
+ reg_um = sizeof(ring_reg_addr_list) / sizeof(u32);
+ separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
+ for (j = 0; j < hdev->num_tqps; j++) {
+ for (i = 0; i < reg_um; i++)
+ *reg++ = hclgevf_read_dev(&hdev->hw,
+ ring_reg_addr_list[i] +
+ HCLGEVF_RING_REG_OFFSET * j);
+ for (i = 0; i < separator_num; i++)
+ *reg++ = SEPARATOR_VALUE;
+ }
+
+ reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32);
+ separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
+ for (j = 0; j < hdev->num_msi_used - 1; j++) {
+ for (i = 0; i < reg_um; i++)
+ *reg++ = hclgevf_read_dev(&hdev->hw,
+ tqp_intr_reg_addr_list[i] +
+ HCLGEVF_RING_INT_REG_OFFSET * j);
+ for (i = 0; i < separator_num; i++)
+ *reg++ = SEPARATOR_VALUE;
+ }
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h
new file mode 100644
index 000000000000..77bdcf60a1af
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2023 Hisilicon Limited. */
+
+#ifndef __HCLGEVF_REGS_H
+#define __HCLGEVF_REGS_H
+#include <linux/types.h>
+
+struct hnae3_handle;
+
+int hclgevf_get_regs_len(struct hnae3_handle *handle);
+void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
+ void *data);
+#endif
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index 3ee89ae496d0..773d7aa29ef5 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* 82596.c: A generic 82596 ethernet driver for linux. */
/*
Based on Apricot.c
@@ -31,9 +32,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c
index 0af70094aba3..3e53e0c243ba 100644
--- a/drivers/net/ethernet/i825xx/lasi_82596.c
+++ b/drivers/net/ethernet/i825xx/lasi_82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
munged into HPPA boxen .
@@ -59,9 +60,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index ca2fb303fcc6..67d248a7a6f4 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-1.0+
/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
munged into HPPA boxen .
@@ -59,9 +60,7 @@
Driver skeleton
Written 1993 by Donald Becker.
Copyright 1993 United States Government as represented by the Director,
- National Security Agency. This software may only be used and distributed
- according to the terms of the GNU General Public License as modified by SRC,
- incorporated herein by reference.
+ National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 3909c6a0af89..5e27470c6b1e 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Sun3 i82586 Ethernet driver
*
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.h b/drivers/net/ethernet/i825xx/sun3_82586.h
index d82eca563266..d8e249d704a7 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.h
+++ b/drivers/net/ethernet/i825xx/sun3_82586.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Intel i82586 Ethernet definitions
*
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 113fcb3e353e..832a2ae01950 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -203,7 +203,7 @@ static inline void ibmveth_flush_buffer(void *addr, unsigned long length)
unsigned long offset;
for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
- asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
+ asm("dcbf %0,%1,1" :: "b" (addr), "r" (offset));
}
/* replenish the buffers for a pool. note that we don't need to
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index c63d3ec9d328..df76cdaddcfb 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -97,6 +97,8 @@ static int pending_scrq(struct ibmvnic_adapter *,
static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
struct ibmvnic_sub_crq_queue *);
static int ibmvnic_poll(struct napi_struct *napi, int data);
+static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter);
+static inline void reinit_init_done(struct ibmvnic_adapter *adapter);
static void send_query_map(struct ibmvnic_adapter *adapter);
static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8);
static int send_request_unmap(struct ibmvnic_adapter *, u8);
@@ -114,6 +116,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
static void free_long_term_buff(struct ibmvnic_adapter *adapter,
struct ibmvnic_long_term_buff *ltb);
static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
+static void flush_reset_queue(struct ibmvnic_adapter *adapter);
struct ibmvnic_stat {
char name[ETH_GSTRING_LEN];
@@ -1505,8 +1508,8 @@ static const char *adapter_state_to_string(enum vnic_state state)
static int ibmvnic_login(struct net_device *netdev)
{
+ unsigned long flags, timeout = msecs_to_jiffies(20000);
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
- unsigned long timeout = msecs_to_jiffies(20000);
int retry_count = 0;
int retries = 10;
bool retry;
@@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev)
if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) {
- netdev_warn(netdev, "Login timed out, retrying...\n");
- retry = true;
- adapter->init_done_rc = 0;
- retry_count++;
- continue;
+ netdev_warn(netdev, "Login timed out\n");
+ adapter->login_pending = false;
+ goto partial_reset;
}
if (adapter->init_done_rc == ABORTED) {
@@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev)
"SCRQ irq initialization failed\n");
return rc;
}
+ /* Default/timeout error handling, reset and start fresh */
} else if (adapter->init_done_rc) {
netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
adapter->init_done_rc);
- return -EIO;
+
+partial_reset:
+ /* adapter login failed, so free any CRQs or sub-CRQs
+ * and register again before attempting to login again.
+ * If we don't do this then the VIOS may think that
+ * we are already logged in and reject any subsequent
+ * attempts
+ */
+ netdev_warn(netdev,
+ "Freeing and re-registering CRQs before attempting to login again\n");
+ retry = true;
+ adapter->init_done_rc = 0;
+ release_sub_crqs(adapter, true);
+ /* Much of this is similar logic as ibmvnic_probe(),
+ * we are essentially re-initializing communication
+ * with the server. We really should not run any
+ * resets/failovers here because this is already a form
+ * of reset and we do not want parallel resets occurring
+ */
+ do {
+ reinit_init_done(adapter);
+ /* Clear any failovers we got in the previous
+ * pass since we are re-initializing the CRQ
+ */
+ adapter->failover_pending = false;
+ release_crq_queue(adapter);
+ /* If we don't sleep here then we risk an
+ * unnecessary failover event from the VIOS.
+ * This is a known VIOS issue caused by a vnic
+ * device freeing and registering a CRQ too
+ * quickly.
+ */
+ msleep(1500);
+ /* Avoid any resets, since we are currently
+ * resetting.
+ */
+ spin_lock_irqsave(&adapter->rwi_lock, flags);
+ flush_reset_queue(adapter);
+ spin_unlock_irqrestore(&adapter->rwi_lock,
+ flags);
+
+ rc = init_crq_queue(adapter);
+ if (rc) {
+ netdev_err(netdev, "login recovery: init CRQ failed %d\n",
+ rc);
+ return -EIO;
+ }
+
+ rc = ibmvnic_reset_init(adapter, false);
+ if (rc)
+ netdev_err(netdev, "login recovery: Reset init failed %d\n",
+ rc);
+ /* IBMVNIC_CRQ_INIT will return EAGAIN if it
+ * fails, since ibmvnic_reset_init will free
+ * irq's in failure, we won't be able to receive
+ * new CRQs so we need to keep trying. probe()
+ * handles this similarly.
+ */
+ } while (rc == -EAGAIN && retry_count++ < retries);
}
} while (retry);
@@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev)
static void release_login_buffer(struct ibmvnic_adapter *adapter)
{
+ if (!adapter->login_buf)
+ return;
+
+ dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token,
+ adapter->login_buf_sz, DMA_TO_DEVICE);
kfree(adapter->login_buf);
adapter->login_buf = NULL;
}
static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter)
{
+ if (!adapter->login_rsp_buf)
+ return;
+
+ dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token,
+ adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
kfree(adapter->login_rsp_buf);
adapter->login_rsp_buf = NULL;
}
@@ -1816,7 +1886,14 @@ static int __ibmvnic_open(struct net_device *netdev)
if (prev_state == VNIC_CLOSED)
enable_irq(adapter->tx_scrq[i]->irq);
enable_scrq_irq(adapter, adapter->tx_scrq[i]);
- netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i));
+ /* netdev_tx_reset_queue will reset dql stats. During NON_FATAL
+ * resets, don't reset the stats because there could be batched
+ * skb's waiting to be sent. If we reset dql stats, we risk
+ * num_completed being greater than num_queued. This will cause
+ * a BUG_ON in dql_completed().
+ */
+ if (adapter->reset_reason != VNIC_RESET_NON_FATAL)
+ netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i));
}
rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
@@ -4823,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter)
if (rc) {
adapter->login_pending = false;
netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
- goto buf_rsp_map_failed;
+ goto buf_send_failed;
}
return 0;
+buf_send_failed:
+ dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size,
+ DMA_FROM_DEVICE);
buf_rsp_map_failed:
kfree(login_rsp_buffer);
adapter->login_rsp_buf = NULL;
@@ -5389,6 +5469,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
int num_tx_pools;
int num_rx_pools;
u64 *size_array;
+ u32 rsp_len;
int i;
/* CHECK: Test/set of login_pending does not need to be atomic
@@ -5400,11 +5481,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
}
adapter->login_pending = false;
- dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
- DMA_TO_DEVICE);
- dma_unmap_single(dev, adapter->login_rsp_buf_token,
- adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
-
/* If the number of queues requested can't be allocated by the
* server, the login response will return with code 1. We will need
* to resend the login buffer with fewer queues requested.
@@ -5440,6 +5516,23 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
ibmvnic_reset(adapter, VNIC_RESET_FATAL);
return -EIO;
}
+
+ rsp_len = be32_to_cpu(login_rsp->len);
+ if (be32_to_cpu(login->login_rsp_len) < rsp_len ||
+ rsp_len <= be32_to_cpu(login_rsp->off_txsubm_subcrqs) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_rxadd_subcrqs) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_rxadd_buff_size) ||
+ rsp_len <= be32_to_cpu(login_rsp->off_supp_tx_desc)) {
+ /* This can happen if a login request times out and there are
+ * 2 outstanding login requests sent, the LOGIN_RSP crq
+ * could have been for the older login request. So we are
+ * parsing the newer response buffer which may be incomplete
+ */
+ dev_err(dev, "FATAL: Login rsp offsets/lengths invalid\n");
+ ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+ return -EIO;
+ }
+
size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
/* variable buffer sizes are not supported, so just read the
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index bd7ef59b1f2e..771a3c909c45 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4198,7 +4198,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
/**
* e1000e_trigger_lsc - trigger an LSC interrupt
- * @adapter:
+ * @adapter: board private structure
*
* Fire a link status change interrupt to start the watchdog.
**/
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 9954493cd448..62497f5565c5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -1839,7 +1839,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf)
void i40e_dbg_init(void)
{
i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL);
- if (!i40e_dbg_root)
+ if (IS_ERR(i40e_dbg_root))
pr_info("init of debugfs failed\n");
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index b847bd105b16..a86bfa3bba74 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1788,12 +1788,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) {
- netdev_info(netdev, "already using mac address %pM\n",
- addr->sa_data);
- return 0;
- }
-
if (test_bit(__I40E_DOWN, pf->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
return -EADDRNOTAVAIL;
@@ -2615,7 +2609,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
retval = i40e_correct_mac_vlan_filters
(vsi, &tmp_add_list, &tmp_del_list,
vlan_filters);
- else
+ else if (pf->vf)
retval = i40e_correct_vf_mac_vlan_filters
(vsi, &tmp_add_list, &tmp_del_list,
vlan_filters, pf->vf[vsi->vf_id].trusted);
@@ -2788,7 +2782,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
}
/* if the VF is not trusted do not do promisc */
- if ((vsi->type == I40E_VSI_SRIOV) && !pf->vf[vsi->vf_id].trusted) {
+ if (vsi->type == I40E_VSI_SRIOV && pf->vf &&
+ !pf->vf[vsi->vf_id].trusted) {
clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
goto out;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 9da0c87f0328..f99c1f7fec40 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -210,11 +210,11 @@ read_nvm_exit:
* @hw: pointer to the HW structure.
* @module_pointer: module pointer location in words from the NVM beginning
* @offset: offset in words from module start
- * @words: number of words to write
- * @data: buffer with words to write to the Shadow RAM
+ * @words: number of words to read
+ * @data: buffer with words to read to the Shadow RAM
* @last_command: tells the AdminQ that this is the last command
*
- * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ * Reads a 16 bit words buffer to the Shadow RAM using the admin command.
**/
static int i40e_read_nvm_aq(struct i40e_hw *hw,
u8 module_pointer, u32 offset,
@@ -234,18 +234,18 @@ static int i40e_read_nvm_aq(struct i40e_hw *hw,
*/
if ((offset + words) > hw->nvm.sr_size)
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write error: offset %d beyond Shadow RAM limit %d\n",
+ "NVM read error: offset %d beyond Shadow RAM limit %d\n",
(offset + words), hw->nvm.sr_size);
else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
- /* We can write only up to 4KB (one sector), in one AQ write */
+ /* We can read only up to 4KB (one sector), in one AQ write */
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write fail error: tried to write %d words, limit is %d.\n",
+ "NVM read fail error: tried to read %d words, limit is %d.\n",
words, I40E_SR_SECTOR_SIZE_IN_WORDS);
else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
!= (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
- /* A single write cannot spread over two sectors */
+ /* A single read cannot spread over two sectors */
i40e_debug(hw, I40E_DEBUG_NVM,
- "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
+ "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",
offset, words);
else
ret_code = i40e_aq_read_nvm(hw, module_pointer,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index cd7b52fb6b46..05ec1181471e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -582,7 +582,7 @@ static void i40e_clean_xdp_tx_buffer(struct i40e_ring *tx_ring,
* @vsi: Current VSI
* @tx_ring: XDP Tx ring
*
- * Returns true if cleanup/tranmission is done.
+ * Returns true if cleanup/transmission is done.
**/
bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring)
{
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h
index 39d0fe76a38f..8cbdebc5b698 100644
--- a/drivers/net/ethernet/intel/iavf/iavf.h
+++ b/drivers/net/ethernet/intel/iavf/iavf.h
@@ -255,8 +255,10 @@ struct iavf_adapter {
struct workqueue_struct *wq;
struct work_struct reset_task;
struct work_struct adminq_task;
+ struct work_struct finish_config;
struct delayed_work client_task;
wait_queue_head_t down_waitqueue;
+ wait_queue_head_t reset_waitqueue;
wait_queue_head_t vc_waitqueue;
struct iavf_q_vector *q_vectors;
struct list_head vlan_filter_list;
@@ -518,14 +520,12 @@ int iavf_up(struct iavf_adapter *adapter);
void iavf_down(struct iavf_adapter *adapter);
int iavf_process_config(struct iavf_adapter *adapter);
int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
-void iavf_schedule_reset(struct iavf_adapter *adapter);
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
void iavf_schedule_request_stats(struct iavf_adapter *adapter);
+void iavf_schedule_finish_config(struct iavf_adapter *adapter);
void iavf_reset(struct iavf_adapter *adapter);
void iavf_set_ethtool_ops(struct net_device *netdev);
void iavf_update_stats(struct iavf_adapter *adapter);
-void iavf_reset_interrupt_capability(struct iavf_adapter *adapter);
-int iavf_init_interrupt_scheme(struct iavf_adapter *adapter);
-void iavf_irq_enable_queues(struct iavf_adapter *adapter);
void iavf_free_all_tx_resources(struct iavf_adapter *adapter);
void iavf_free_all_rx_resources(struct iavf_adapter *adapter);
@@ -579,17 +579,11 @@ void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid);
-int iavf_replace_primary_mac(struct iavf_adapter *adapter,
- const u8 *new_mac);
-void
-iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
- netdev_features_t prev_features,
- netdev_features_t features);
void iavf_add_fdir_filter(struct iavf_adapter *adapter);
void iavf_del_fdir_filter(struct iavf_adapter *adapter);
void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter);
struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
const u8 *macaddr);
-int iavf_lock_timeout(struct mutex *lock, unsigned int msecs);
+int iavf_wait_for_reset(struct iavf_adapter *adapter);
#endif /* _IAVF_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/iavf_alloc.h b/drivers/net/ethernet/intel/iavf/iavf_alloc.h
index 2711573c14ec..162ea70685a6 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_alloc.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_alloc.h
@@ -28,7 +28,6 @@ enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw,
struct iavf_dma_mem *mem);
enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw,
struct iavf_virt_mem *mem, u32 size);
-enum iavf_status iavf_free_virt_mem(struct iavf_hw *hw,
- struct iavf_virt_mem *mem);
+void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem);
#endif /* _IAVF_ALLOC_H_ */
diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c
index dd11dbbd5551..1afd761d8052 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_common.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_common.c
@@ -35,7 +35,6 @@ enum iavf_status iavf_set_mac_type(struct iavf_hw *hw)
status = IAVF_ERR_DEVICE_NOT_SUPPORTED;
}
- hw_dbg(hw, "found mac: %d, returns: %d\n", hw->mac.type, status);
return status;
}
@@ -398,23 +397,6 @@ static enum iavf_status iavf_aq_get_set_rss_lut(struct iavf_hw *hw,
}
/**
- * iavf_aq_get_rss_lut
- * @hw: pointer to the hardware structure
- * @vsi_id: vsi fw index
- * @pf_lut: for PF table set true, for VSI table set false
- * @lut: pointer to the lut buffer provided by the caller
- * @lut_size: size of the lut buffer
- *
- * get the RSS lookup table, PF or VSI type
- **/
-enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 vsi_id,
- bool pf_lut, u8 *lut, u16 lut_size)
-{
- return iavf_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size,
- false);
-}
-
-/**
* iavf_aq_set_rss_lut
* @hw: pointer to the hardware structure
* @vsi_id: vsi fw index
@@ -473,19 +455,6 @@ iavf_status iavf_aq_get_set_rss_key(struct iavf_hw *hw, u16 vsi_id,
}
/**
- * iavf_aq_get_rss_key
- * @hw: pointer to the hw struct
- * @vsi_id: vsi fw index
- * @key: pointer to key info struct
- *
- **/
-enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 vsi_id,
- struct iavf_aqc_get_set_rss_key_data *key)
-{
- return iavf_aq_get_set_rss_key(hw, vsi_id, key, false);
-}
-
-/**
* iavf_aq_set_rss_key
* @hw: pointer to the hw struct
* @vsi_id: vsi fw index
@@ -828,17 +797,3 @@ void iavf_vf_parse_hw_config(struct iavf_hw *hw,
vsi_res++;
}
}
-
-/**
- * iavf_vf_reset
- * @hw: pointer to the hardware structure
- *
- * Send a VF_RESET message to the PF. Does not wait for response from PF
- * as none will be forthcoming. Immediately after calling this function,
- * the admin queue should be shut down and (optionally) reinitialized.
- **/
-enum iavf_status iavf_vf_reset(struct iavf_hw *hw)
-{
- return iavf_aq_send_msg_to_pf(hw, VIRTCHNL_OP_RESET_VF,
- 0, NULL, 0, NULL);
-}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
index 6f171d1d85b7..a34303ad057d 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
@@ -484,6 +484,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 orig_flags, new_flags, changed_flags;
+ int ret = 0;
u32 i;
orig_flags = READ_ONCE(adapter->flags);
@@ -531,12 +532,14 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
/* issue a reset to force legacy-rx change to take effect */
if (changed_flags & IAVF_FLAG_LEGACY_RX) {
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
}
}
- return 0;
+ return ret;
}
/**
@@ -627,6 +630,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 new_rx_count, new_tx_count;
+ int ret = 0;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
@@ -671,11 +675,13 @@ static int iavf_set_ringparam(struct net_device *netdev,
}
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
}
- return 0;
+ return ret;
}
/**
@@ -1283,6 +1289,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos;
+ fltr->ip_ver = 4;
break;
case AH_V4_FLOW:
case ESP_V4_FLOW:
@@ -1294,6 +1301,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst;
fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi;
fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos;
+ fltr->ip_ver = 4;
break;
case IPV4_USER_FLOW:
fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src;
@@ -1306,6 +1314,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes;
fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos;
fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto;
+ fltr->ip_ver = 4;
break;
case TCP_V6_FLOW:
case UDP_V6_FLOW:
@@ -1324,6 +1333,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;
fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass;
+ fltr->ip_ver = 6;
break;
case AH_V6_FLOW:
case ESP_V6_FLOW:
@@ -1339,6 +1349,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
sizeof(struct in6_addr));
fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi;
fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass;
+ fltr->ip_ver = 6;
break;
case IPV6_USER_FLOW:
memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,
@@ -1355,6 +1366,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes;
fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;
fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;
+ fltr->ip_ver = 6;
break;
case ETHER_FLOW:
fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;
@@ -1365,6 +1377,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
return -EINVAL;
}
+ err = iavf_validate_fdir_fltr_masks(adapter, fltr);
+ if (err)
+ return err;
+
if (iavf_fdir_is_dup_fltr(adapter, fltr))
return -EEXIST;
@@ -1395,14 +1411,15 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
if (fsp->flow_type & FLOW_MAC_EXT)
return -EINVAL;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) {
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
dev_err(&adapter->pdev->dev,
"Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n",
IAVF_MAX_FDIR_FILTERS);
return -ENOSPC;
}
- spin_lock_bh(&adapter->fdir_fltr_lock);
if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) {
dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");
spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -1775,7 +1792,9 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
case ETHTOOL_GRXCLSRLCNT:
if (!FDIR_FLTR_SUPPORT(adapter))
break;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
cmd->rule_cnt = adapter->fdir_active_fltr;
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
cmd->data = IAVF_MAX_FDIR_FILTERS;
ret = 0;
break;
@@ -1830,7 +1849,7 @@ static int iavf_set_channels(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
u32 num_req = ch->combined_count;
- int i;
+ int ret = 0;
if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
adapter->num_tc) {
@@ -1852,22 +1871,13 @@ static int iavf_set_channels(struct net_device *netdev,
adapter->num_req_queues = num_req;
adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
- /* wait for the reset is done */
- for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
- msleep(IAVF_RESET_WAIT_MS);
- if (adapter->flags & IAVF_FLAG_RESET_PENDING)
- continue;
- break;
- }
- if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
- adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
- adapter->num_active_queues = num_req;
- return -EOPNOTSUPP;
- }
+ ret = iavf_wait_for_reset(adapter);
+ if (ret)
+ netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");
- return 0;
+ return ret;
}
/**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_fdir.c b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
index 6146203efd84..03e774bd2a5b 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_fdir.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
@@ -18,6 +18,79 @@ static const struct in6_addr ipv6_addr_full_mask = {
}
};
+static const struct in6_addr ipv6_addr_zero_mask = {
+ .in6_u = {
+ .u6_addr8 = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+ }
+};
+
+/**
+ * iavf_validate_fdir_fltr_masks - validate Flow Director filter fields masks
+ * @adapter: pointer to the VF adapter structure
+ * @fltr: Flow Director filter data structure
+ *
+ * Returns 0 if all masks of packet fields are either full or empty. Returns
+ * error on at least one partial mask.
+ */
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+ struct iavf_fdir_fltr *fltr)
+{
+ if (fltr->eth_mask.etype && fltr->eth_mask.etype != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_ver == 4) {
+ if (fltr->ip_mask.v4_addrs.src_ip &&
+ fltr->ip_mask.v4_addrs.src_ip != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.v4_addrs.dst_ip &&
+ fltr->ip_mask.v4_addrs.dst_ip != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.tos && fltr->ip_mask.tos != U8_MAX)
+ goto partial_mask;
+ } else if (fltr->ip_ver == 6) {
+ if (memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_zero_mask,
+ sizeof(struct in6_addr)) &&
+ memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask,
+ sizeof(struct in6_addr)))
+ goto partial_mask;
+
+ if (memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_zero_mask,
+ sizeof(struct in6_addr)) &&
+ memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask,
+ sizeof(struct in6_addr)))
+ goto partial_mask;
+
+ if (fltr->ip_mask.tclass && fltr->ip_mask.tclass != U8_MAX)
+ goto partial_mask;
+ }
+
+ if (fltr->ip_mask.proto && fltr->ip_mask.proto != U8_MAX)
+ goto partial_mask;
+
+ if (fltr->ip_mask.src_port && fltr->ip_mask.src_port != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.dst_port && fltr->ip_mask.dst_port != htons(U16_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.spi && fltr->ip_mask.spi != htonl(U32_MAX))
+ goto partial_mask;
+
+ if (fltr->ip_mask.l4_header &&
+ fltr->ip_mask.l4_header != htonl(U32_MAX))
+ goto partial_mask;
+
+ return 0;
+
+partial_mask:
+ dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, partial masks are not supported\n");
+ return -EOPNOTSUPP;
+}
+
/**
* iavf_pkt_udp_no_pay_len - the length of UDP packet without payload
* @fltr: Flow Director filter data structure
@@ -263,8 +336,6 @@ iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
}
- fltr->ip_ver = 4;
-
return 0;
}
@@ -309,8 +380,6 @@ iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
}
- fltr->ip_ver = 6;
-
return 0;
}
@@ -722,7 +791,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
{
struct iavf_fdir_fltr *tmp;
+ bool ret = false;
+ spin_lock_bh(&adapter->fdir_fltr_lock);
list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
if (tmp->flow_type != fltr->flow_type)
continue;
@@ -732,11 +803,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
!memcmp(&tmp->ip_data, &fltr->ip_data,
sizeof(fltr->ip_data)) &&
!memcmp(&tmp->ext_data, &fltr->ext_data,
- sizeof(fltr->ext_data)))
- return true;
+ sizeof(fltr->ext_data))) {
+ ret = true;
+ break;
+ }
}
+ spin_unlock_bh(&adapter->fdir_fltr_lock);
- return false;
+ return ret;
}
/**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_fdir.h b/drivers/net/ethernet/intel/iavf/iavf_fdir.h
index 33c55c366315..9eb9f73f6adf 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_fdir.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_fdir.h
@@ -110,6 +110,8 @@ struct iavf_fdir_fltr {
struct virtchnl_fdir_add vc_add_msg;
};
+int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
+ struct iavf_fdir_fltr *fltr);
int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 4a66873882d1..9610ca770349 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -167,6 +167,45 @@ static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev)
}
/**
+ * iavf_is_reset_in_progress - Check if a reset is in progress
+ * @adapter: board private structure
+ */
+static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
+{
+ if (adapter->state == __IAVF_RESETTING ||
+ adapter->flags & (IAVF_FLAG_RESET_PENDING |
+ IAVF_FLAG_RESET_NEEDED))
+ return true;
+
+ return false;
+}
+
+/**
+ * iavf_wait_for_reset - Wait for reset to finish.
+ * @adapter: board private structure
+ *
+ * Returns 0 if reset finished successfully, negative on timeout or interrupt.
+ */
+int iavf_wait_for_reset(struct iavf_adapter *adapter)
+{
+ int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
+ !iavf_is_reset_in_progress(adapter),
+ msecs_to_jiffies(5000));
+
+ /* If ret < 0 then it means wait was interrupted.
+ * If ret == 0 then it means we got a timeout while waiting
+ * for reset to finish.
+ * If ret > 0 it means reset has finished.
+ */
+ if (ret > 0)
+ return 0;
+ else if (ret < 0)
+ return -EINTR;
+ else
+ return -EBUSY;
+}
+
+/**
* iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to fill out
@@ -192,12 +231,11 @@ enum iavf_status iavf_allocate_dma_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_free_dma_mem_d - OS specific memory free for shared code
+ * iavf_free_dma_mem - wrapper for DMA memory freeing
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to free
**/
-enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw,
- struct iavf_dma_mem *mem)
+enum iavf_status iavf_free_dma_mem(struct iavf_hw *hw, struct iavf_dma_mem *mem)
{
struct iavf_adapter *adapter = (struct iavf_adapter *)hw->back;
@@ -209,13 +247,13 @@ enum iavf_status iavf_free_dma_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_allocate_virt_mem_d - OS specific memory alloc for shared code
+ * iavf_allocate_virt_mem - virt memory alloc wrapper
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to fill out
* @size: size of memory requested
**/
-enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw,
- struct iavf_virt_mem *mem, u32 size)
+enum iavf_status iavf_allocate_virt_mem(struct iavf_hw *hw,
+ struct iavf_virt_mem *mem, u32 size)
{
if (!mem)
return IAVF_ERR_PARAM;
@@ -230,20 +268,13 @@ enum iavf_status iavf_allocate_virt_mem_d(struct iavf_hw *hw,
}
/**
- * iavf_free_virt_mem_d - OS specific memory free for shared code
+ * iavf_free_virt_mem - virt memory free wrapper
* @hw: pointer to the HW structure
* @mem: ptr to mem struct to free
**/
-enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
- struct iavf_virt_mem *mem)
+void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem)
{
- if (!mem)
- return IAVF_ERR_PARAM;
-
- /* it's ok to kfree a NULL pointer */
kfree(mem->va);
-
- return 0;
}
/**
@@ -253,7 +284,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
*
* Returns 0 on success, negative on failure
**/
-int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
+static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
{
unsigned int wait, delay = 10;
@@ -270,12 +301,14 @@ int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
/**
* iavf_schedule_reset - Set the flags and schedule a reset event
* @adapter: board private structure
+ * @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
**/
-void iavf_schedule_reset(struct iavf_adapter *adapter)
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
{
- if (!(adapter->flags &
- (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+ if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
+ !(adapter->flags &
+ (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
+ adapter->flags |= flags;
queue_work(adapter->wq, &adapter->reset_task);
}
}
@@ -303,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
struct iavf_adapter *adapter = netdev_priv(netdev);
adapter->tx_timeout_count++;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
}
/**
@@ -362,7 +395,7 @@ static void iavf_irq_disable(struct iavf_adapter *adapter)
* iavf_irq_enable_queues - Enable interrupt for all queues
* @adapter: board private structure
**/
-void iavf_irq_enable_queues(struct iavf_adapter *adapter)
+static void iavf_irq_enable_queues(struct iavf_adapter *adapter)
{
struct iavf_hw *hw = &adapter->hw;
int i;
@@ -1003,44 +1036,40 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
*
* Do not call this with mac_vlan_list_lock!
**/
-int iavf_replace_primary_mac(struct iavf_adapter *adapter,
- const u8 *new_mac)
+static int iavf_replace_primary_mac(struct iavf_adapter *adapter,
+ const u8 *new_mac)
{
struct iavf_hw *hw = &adapter->hw;
- struct iavf_mac_filter *f;
+ struct iavf_mac_filter *new_f;
+ struct iavf_mac_filter *old_f;
spin_lock_bh(&adapter->mac_vlan_list_lock);
- list_for_each_entry(f, &adapter->mac_filter_list, list) {
- f->is_primary = false;
+ new_f = iavf_add_filter(adapter, new_mac);
+ if (!new_f) {
+ spin_unlock_bh(&adapter->mac_vlan_list_lock);
+ return -ENOMEM;
}
- f = iavf_find_filter(adapter, hw->mac.addr);
- if (f) {
- f->remove = true;
+ old_f = iavf_find_filter(adapter, hw->mac.addr);
+ if (old_f) {
+ old_f->is_primary = false;
+ old_f->remove = true;
adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER;
}
-
- f = iavf_add_filter(adapter, new_mac);
-
- if (f) {
- /* Always send the request to add if changing primary MAC
- * even if filter is already present on the list
- */
- f->is_primary = true;
- f->add = true;
- adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
- ether_addr_copy(hw->mac.addr, new_mac);
- }
+ /* Always send the request to add if changing primary MAC,
+ * even if filter is already present on the list
+ */
+ new_f->is_primary = true;
+ new_f->add = true;
+ adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
+ ether_addr_copy(hw->mac.addr, new_mac);
spin_unlock_bh(&adapter->mac_vlan_list_lock);
/* schedule the watchdog task to immediately process the request */
- if (f) {
- mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
- return 0;
- }
- return -ENOMEM;
+ mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
+ return 0;
}
/**
@@ -1663,10 +1692,10 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
adapter->msix_entries[vector].entry = vector;
err = iavf_acquire_msix_vectors(adapter, v_budget);
+ if (!err)
+ iavf_schedule_finish_config(adapter);
out:
- netif_set_real_num_rx_queues(adapter->netdev, pairs);
- netif_set_real_num_tx_queues(adapter->netdev, pairs);
return err;
}
@@ -1840,19 +1869,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
static void iavf_free_q_vectors(struct iavf_adapter *adapter)
{
int q_idx, num_q_vectors;
- int napi_vectors;
if (!adapter->q_vectors)
return;
num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- napi_vectors = adapter->num_active_queues;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
- if (q_idx < napi_vectors)
- netif_napi_del(&q_vector->napi);
+ netif_napi_del(&q_vector->napi);
}
kfree(adapter->q_vectors);
adapter->q_vectors = NULL;
@@ -1863,7 +1889,7 @@ static void iavf_free_q_vectors(struct iavf_adapter *adapter)
* @adapter: board private structure
*
**/
-void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
+static void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
{
if (!adapter->msix_entries)
return;
@@ -1878,7 +1904,7 @@ void iavf_reset_interrupt_capability(struct iavf_adapter *adapter)
* @adapter: board private structure to initialize
*
**/
-int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
{
int err;
@@ -1889,9 +1915,7 @@ int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
goto err_alloc_queues;
}
- rtnl_lock();
err = iavf_set_interrupt_capability(adapter);
- rtnl_unlock();
if (err) {
dev_err(&adapter->pdev->dev,
"Unable to setup interrupt capabilities\n");
@@ -1944,15 +1968,16 @@ static void iavf_free_rss(struct iavf_adapter *adapter)
/**
* iavf_reinit_interrupt_scheme - Reallocate queues and vectors
* @adapter: board private structure
+ * @running: true if adapter->state == __IAVF_RUNNING
*
* Returns 0 on success, negative on failure
**/
-static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter, bool running)
{
struct net_device *netdev = adapter->netdev;
int err;
- if (netif_running(netdev))
+ if (running)
iavf_free_traffic_irqs(adapter);
iavf_free_misc_irq(adapter);
iavf_reset_interrupt_capability(adapter);
@@ -1977,6 +2002,78 @@ err:
}
/**
+ * iavf_finish_config - do all netdev work that needs RTNL
+ * @work: our work_struct
+ *
+ * Do work that needs both RTNL and crit_lock.
+ **/
+static void iavf_finish_config(struct work_struct *work)
+{
+ struct iavf_adapter *adapter;
+ int pairs, err;
+
+ adapter = container_of(work, struct iavf_adapter, finish_config);
+
+ /* Always take RTNL first to prevent circular lock dependency */
+ rtnl_lock();
+ mutex_lock(&adapter->crit_lock);
+
+ if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
+ adapter->netdev_registered &&
+ !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
+ netdev_update_features(adapter->netdev);
+ adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
+ }
+
+ switch (adapter->state) {
+ case __IAVF_DOWN:
+ if (!adapter->netdev_registered) {
+ err = register_netdevice(adapter->netdev);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "Unable to register netdev (%d)\n",
+ err);
+
+ /* go back and try again.*/
+ iavf_free_rss(adapter);
+ iavf_free_misc_irq(adapter);
+ iavf_reset_interrupt_capability(adapter);
+ iavf_change_state(adapter,
+ __IAVF_INIT_CONFIG_ADAPTER);
+ goto out;
+ }
+ adapter->netdev_registered = true;
+ }
+
+ /* Set the real number of queues when reset occurs while
+ * state == __IAVF_DOWN
+ */
+ fallthrough;
+ case __IAVF_RUNNING:
+ pairs = adapter->num_active_queues;
+ netif_set_real_num_rx_queues(adapter->netdev, pairs);
+ netif_set_real_num_tx_queues(adapter->netdev, pairs);
+ break;
+
+ default:
+ break;
+ }
+
+out:
+ mutex_unlock(&adapter->crit_lock);
+ rtnl_unlock();
+}
+
+/**
+ * iavf_schedule_finish_config - Set the flags and schedule a reset event
+ * @adapter: board private structure
+ **/
+void iavf_schedule_finish_config(struct iavf_adapter *adapter)
+{
+ if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
+ queue_work(adapter->wq, &adapter->finish_config);
+}
+
+/**
* iavf_process_aq_command - process aq_required flags
* and sends aq command
* @adapter: pointer to iavf adapter structure
@@ -2176,7 +2273,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
* the watchdog if any changes are requested to expedite the request via
* virtchnl.
**/
-void
+static void
iavf_set_vlan_offload_features(struct iavf_adapter *adapter,
netdev_features_t prev_features,
netdev_features_t features)
@@ -2383,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
adapter->vsi_res->num_queue_pairs);
adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
- iavf_schedule_reset(adapter);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
return -EAGAIN;
}
@@ -2613,22 +2710,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
netif_carrier_off(netdev);
adapter->link_up = false;
-
- /* set the semaphore to prevent any callbacks after device registration
- * up to time when state of driver will be set to __IAVF_DOWN
- */
- rtnl_lock();
- if (!adapter->netdev_registered) {
- err = register_netdevice(netdev);
- if (err) {
- rtnl_unlock();
- goto err_register;
- }
- }
-
- adapter->netdev_registered = true;
-
netif_tx_stop_all_queues(netdev);
+
if (CLIENT_ALLOWED(adapter)) {
err = iavf_lan_add_device(adapter);
if (err)
@@ -2641,7 +2724,6 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
iavf_change_state(adapter, __IAVF_DOWN);
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
- rtnl_unlock();
iavf_misc_irq_enable(adapter);
wake_up(&adapter->down_waitqueue);
@@ -2661,10 +2743,11 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
/* request initial VLAN offload settings */
iavf_set_vlan_offload_features(adapter, 0, netdev->features);
+ iavf_schedule_finish_config(adapter);
return;
+
err_mem:
iavf_free_rss(adapter);
-err_register:
iavf_free_misc_irq(adapter);
err_sw_init:
iavf_reset_interrupt_capability(adapter);
@@ -2691,26 +2774,9 @@ static void iavf_watchdog_task(struct work_struct *work)
goto restart_watchdog;
}
- if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
- adapter->netdev_registered &&
- !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
- rtnl_trylock()) {
- netdev_update_features(adapter->netdev);
- rtnl_unlock();
- adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
- }
-
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
iavf_change_state(adapter, __IAVF_COMM_FAILED);
- if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
- adapter->aq_required = 0;
- adapter->current_op = VIRTCHNL_OP_UNKNOWN;
- mutex_unlock(&adapter->crit_lock);
- queue_work(adapter->wq, &adapter->reset_task);
- return;
- }
-
switch (adapter->state) {
case __IAVF_STARTUP:
iavf_startup(adapter);
@@ -2838,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
/* check for hw reset */
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
if (!reg_val) {
- adapter->flags |= IAVF_FLAG_RESET_PENDING;
adapter->aq_required = 0;
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
mutex_unlock(&adapter->crit_lock);
queue_delayed_work(adapter->wq,
&adapter->watchdog_task, HZ * 2);
@@ -2952,11 +3017,6 @@ static void iavf_reset_task(struct work_struct *work)
int i = 0, err;
bool running;
- /* Detach interface to avoid subsequent NDO callbacks */
- rtnl_lock();
- netif_device_detach(netdev);
- rtnl_unlock();
-
/* When device is being removed it doesn't make sense to run the reset
* task, just return in such a case.
*/
@@ -2964,7 +3024,7 @@ static void iavf_reset_task(struct work_struct *work)
if (adapter->state != __IAVF_REMOVE)
queue_work(adapter->wq, &adapter->reset_task);
- goto reset_finish;
+ return;
}
while (!mutex_trylock(&adapter->client_lock))
@@ -3022,11 +3082,6 @@ static void iavf_reset_task(struct work_struct *work)
iavf_disable_vf(adapter);
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
- if (netif_running(netdev)) {
- rtnl_lock();
- dev_close(netdev);
- rtnl_unlock();
- }
return; /* Do not attempt to reinit. It's dead, Jim. */
}
@@ -3068,7 +3123,7 @@ continue_reset:
if ((adapter->flags & IAVF_FLAG_REINIT_MSIX_NEEDED) ||
(adapter->flags & IAVF_FLAG_REINIT_ITR_NEEDED)) {
- err = iavf_reinit_interrupt_scheme(adapter);
+ err = iavf_reinit_interrupt_scheme(adapter, running);
if (err)
goto reset_err;
}
@@ -3163,10 +3218,11 @@ continue_reset:
adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
+ wake_up(&adapter->reset_waitqueue);
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
- goto reset_finish;
+ return;
reset_err:
if (running) {
set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3176,21 +3232,7 @@ reset_err:
mutex_unlock(&adapter->client_lock);
mutex_unlock(&adapter->crit_lock);
-
- if (netif_running(netdev)) {
- /* Close device to ensure that Tx queues will not be started
- * during netif_device_attach() at the end of the reset task.
- */
- rtnl_lock();
- dev_close(netdev);
- rtnl_unlock();
- }
-
dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
-reset_finish:
- rtnl_lock();
- netif_device_attach(netdev);
- rtnl_unlock();
}
/**
@@ -3208,9 +3250,6 @@ static void iavf_adminq_task(struct work_struct *work)
u32 val, oldval;
u16 pending;
- if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
- goto out;
-
if (!mutex_trylock(&adapter->crit_lock)) {
if (adapter->state == __IAVF_REMOVE)
return;
@@ -3219,10 +3258,13 @@ static void iavf_adminq_task(struct work_struct *work)
goto out;
}
+ if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+ goto unlock;
+
event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
if (!event.msg_buf)
- goto out;
+ goto unlock;
do {
ret = iavf_clean_arq_element(hw, &event, &pending);
@@ -3237,11 +3279,8 @@ static void iavf_adminq_task(struct work_struct *work)
if (pending != 0)
memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
} while (pending);
- mutex_unlock(&adapter->crit_lock);
- if ((adapter->flags &
- (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
- adapter->state == __IAVF_RESETTING)
+ if (iavf_is_reset_in_progress(adapter))
goto freedom;
/* check for error indications */
@@ -3283,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work)
freedom:
kfree(event.msg_buf);
+unlock:
+ mutex_unlock(&adapter->crit_lock);
out:
/* re-enable Admin queue interrupt cause */
iavf_misc_irq_enable(adapter);
@@ -4327,6 +4368,7 @@ static int iavf_close(struct net_device *netdev)
static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct iavf_adapter *adapter = netdev_priv(netdev);
+ int ret = 0;
netdev_dbg(netdev, "changing MTU from %d to %d\n",
netdev->mtu, new_mtu);
@@ -4337,11 +4379,15 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
}
if (netif_running(netdev)) {
- adapter->flags |= IAVF_FLAG_RESET_NEEDED;
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+ ret = iavf_wait_for_reset(adapter);
+ if (ret < 0)
+ netdev_warn(netdev, "MTU change interrupted waiting for reset");
+ else if (ret)
+ netdev_warn(netdev, "MTU change timed out waiting for reset");
}
- return 0;
+ return ret;
}
#define NETIF_VLAN_OFFLOAD_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
@@ -4934,6 +4980,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->reset_task, iavf_reset_task);
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
+ INIT_WORK(&adapter->finish_config, iavf_finish_config);
INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
queue_delayed_work(adapter->wq, &adapter->watchdog_task,
@@ -4942,6 +4989,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Setup the wait queue for indicating transition to down status */
init_waitqueue_head(&adapter->down_waitqueue);
+ /* Setup the wait queue for indicating transition to running state */
+ init_waitqueue_head(&adapter->reset_waitqueue);
+
/* Setup the wait queue for indicating virtchannel events */
init_waitqueue_head(&adapter->vc_waitqueue);
@@ -5073,13 +5123,15 @@ static void iavf_remove(struct pci_dev *pdev)
usleep_range(500, 1000);
}
cancel_delayed_work_sync(&adapter->watchdog_task);
+ cancel_work_sync(&adapter->finish_config);
+ rtnl_lock();
if (adapter->netdev_registered) {
- rtnl_lock();
unregister_netdevice(netdev);
adapter->netdev_registered = false;
- rtnl_unlock();
}
+ rtnl_unlock();
+
if (CLIENT_ALLOWED(adapter)) {
err = iavf_lan_del_device(adapter);
if (err)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_osdep.h b/drivers/net/ethernet/intel/iavf/iavf_osdep.h
index a452ce90679a..77d33deaabb5 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_osdep.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_osdep.h
@@ -13,12 +13,6 @@
/* get readq/writeq support for 32 bit kernels, use the low-first version */
#include <linux/io-64-nonatomic-lo-hi.h>
-/* File to be the magic between shared code and
- * actual OS primitives
- */
-
-#define hw_dbg(hw, S, A...) do {} while (0)
-
#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg)))
#define rd32(a, reg) readl((a)->hw_addr + (reg))
@@ -35,14 +29,11 @@ struct iavf_dma_mem {
#define iavf_allocate_dma_mem(h, m, unused, s, a) \
iavf_allocate_dma_mem_d(h, m, s, a)
-#define iavf_free_dma_mem(h, m) iavf_free_dma_mem_d(h, m)
struct iavf_virt_mem {
void *va;
u32 size;
};
-#define iavf_allocate_virt_mem(h, m, s) iavf_allocate_virt_mem_d(h, m, s)
-#define iavf_free_virt_mem(h, m) iavf_free_virt_mem_d(h, m)
#define iavf_debug(h, m, s, ...) \
do { \
diff --git a/drivers/net/ethernet/intel/iavf/iavf_prototype.h b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
index edebfbbcffdc..940cb4203fbe 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_prototype.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_prototype.h
@@ -40,12 +40,8 @@ enum iavf_status iavf_aq_queue_shutdown(struct iavf_hw *hw, bool unloading);
const char *iavf_aq_str(struct iavf_hw *hw, enum iavf_admin_queue_err aq_err);
const char *iavf_stat_str(struct iavf_hw *hw, enum iavf_status stat_err);
-enum iavf_status iavf_aq_get_rss_lut(struct iavf_hw *hw, u16 seid,
- bool pf_lut, u8 *lut, u16 lut_size);
enum iavf_status iavf_aq_set_rss_lut(struct iavf_hw *hw, u16 seid,
bool pf_lut, u8 *lut, u16 lut_size);
-enum iavf_status iavf_aq_get_rss_key(struct iavf_hw *hw, u16 seid,
- struct iavf_aqc_get_set_rss_key_data *key);
enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 seid,
struct iavf_aqc_get_set_rss_key_data *key);
@@ -60,7 +56,6 @@ static inline struct iavf_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
void iavf_vf_parse_hw_config(struct iavf_hw *hw,
struct virtchnl_vf_resource *msg);
-enum iavf_status iavf_vf_reset(struct iavf_hw *hw);
enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw,
enum virtchnl_ops v_opcode,
enum iavf_status v_retval,
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
index e989feda133c..8c5f6096b002 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -54,7 +54,7 @@ static void iavf_unmap_and_free_tx_resource(struct iavf_ring *ring,
* iavf_clean_tx_ring - Free any empty Tx buffers
* @tx_ring: ring to be cleaned
**/
-void iavf_clean_tx_ring(struct iavf_ring *tx_ring)
+static void iavf_clean_tx_ring(struct iavf_ring *tx_ring)
{
unsigned long bi_size;
u16 i;
@@ -110,7 +110,7 @@ void iavf_free_tx_resources(struct iavf_ring *tx_ring)
* Since there is no access to the ring head register
* in XL710, we need to use our local copies
**/
-u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
+static u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
{
u32 head, tail;
@@ -128,6 +128,24 @@ u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
}
/**
+ * iavf_force_wb - Issue SW Interrupt so HW does a wb
+ * @vsi: the VSI we care about
+ * @q_vector: the vector on which to force writeback
+ **/
+static void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector)
+{
+ u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
+ IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
+ IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
+ IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
+ /* allow 00 to be written to the index */;
+
+ wr32(&vsi->back->hw,
+ IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx),
+ val);
+}
+
+/**
* iavf_detect_recover_hung - Function to detect and recover hung_queues
* @vsi: pointer to vsi struct with tx queues
*
@@ -352,25 +370,6 @@ static void iavf_enable_wb_on_itr(struct iavf_vsi *vsi,
q_vector->arm_wb_state = true;
}
-/**
- * iavf_force_wb - Issue SW Interrupt so HW does a wb
- * @vsi: the VSI we care about
- * @q_vector: the vector on which to force writeback
- *
- **/
-void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector)
-{
- u32 val = IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
- IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK | /* set noitr */
- IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_MASK |
- IAVF_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK
- /* allow 00 to be written to the index */;
-
- wr32(&vsi->back->hw,
- IAVF_VFINT_DYN_CTLN1(q_vector->reg_idx),
- val);
-}
-
static inline bool iavf_container_is_rx(struct iavf_q_vector *q_vector,
struct iavf_ring_container *rc)
{
@@ -687,7 +686,7 @@ err:
* iavf_clean_rx_ring - Free Rx buffers
* @rx_ring: ring to be cleaned
**/
-void iavf_clean_rx_ring(struct iavf_ring *rx_ring)
+static void iavf_clean_rx_ring(struct iavf_ring *rx_ring)
{
unsigned long bi_size;
u16 i;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
index 2624bf6d009e..7e6ee32d19b6 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h
+++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h
@@ -442,15 +442,11 @@ static inline unsigned int iavf_rx_pg_order(struct iavf_ring *ring)
bool iavf_alloc_rx_buffers(struct iavf_ring *rxr, u16 cleaned_count);
netdev_tx_t iavf_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
-void iavf_clean_tx_ring(struct iavf_ring *tx_ring);
-void iavf_clean_rx_ring(struct iavf_ring *rx_ring);
int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring);
int iavf_setup_rx_descriptors(struct iavf_ring *rx_ring);
void iavf_free_tx_resources(struct iavf_ring *tx_ring);
void iavf_free_rx_resources(struct iavf_ring *rx_ring);
int iavf_napi_poll(struct napi_struct *napi, int budget);
-void iavf_force_wb(struct iavf_vsi *vsi, struct iavf_q_vector *q_vector);
-u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw);
void iavf_detect_recover_hung(struct iavf_vsi *vsi);
int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size);
bool __iavf_chk_linearize(struct sk_buff *skb);
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 7c0578b5457b..be3c007ce90a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
case VIRTCHNL_EVENT_RESET_IMPENDING:
dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
- adapter->flags |= IAVF_FLAG_RESET_PENDING;
dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
- queue_work(adapter->wq, &adapter->reset_task);
+ iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
}
break;
default:
@@ -2237,6 +2236,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
iavf_process_config(adapter);
adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+ iavf_schedule_finish_config(adapter);
iavf_set_queue_vlan_tag_loc(adapter);
@@ -2285,6 +2285,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
case VIRTCHNL_OP_ENABLE_QUEUES:
/* enable transmits */
iavf_irq_enable(adapter, true);
+ wake_up(&adapter->reset_waitqueue);
adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
break;
case VIRTCHNL_OP_DISABLE_QUEUES:
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index 5d89392f969b..817977e3039d 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -18,6 +18,7 @@ ice-y := ice_main.o \
ice_txrx_lib.o \
ice_txrx.o \
ice_fltr.o \
+ ice_irq.o \
ice_pf_vsi_vlan_ops.o \
ice_vsi_vlan_ops.o \
ice_vsi_vlan_lib.o \
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index aa32111afd6e..4ba3d99439a0 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -32,6 +32,7 @@
#include <linux/pkt_sched.h>
#include <linux/if_bridge.h>
#include <linux/ctype.h>
+#include <linux/linkmode.h>
#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/auxiliary_bus.h>
@@ -74,6 +75,7 @@
#include "ice_lag.h"
#include "ice_vsi_vlan_ops.h"
#include "ice_gnss.h"
+#include "ice_irq.h"
#define ICE_BAR0 0
#define ICE_REQ_DESC_MULTIPLE 32
@@ -103,11 +105,6 @@
#define ICE_Q_WAIT_RETRY_LIMIT 10
#define ICE_Q_WAIT_MAX_RETRY (5 * ICE_Q_WAIT_RETRY_LIMIT)
#define ICE_MAX_LG_RSS_QS 256
-#define ICE_RES_VALID_BIT 0x8000
-#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
-#define ICE_RES_RDMA_VEC_ID (ICE_RES_MISC_VEC_ID - 1)
-/* All VF control VSIs share the same IRQ, so assign a unique ID for them */
-#define ICE_RES_VF_CTRL_VEC_ID (ICE_RES_RDMA_VEC_ID - 1)
#define ICE_INVAL_Q_INDEX 0xffff
#define ICE_MAX_RXQS_PER_TC 256 /* Used when setting VSI context per TC Rx queues */
@@ -245,12 +242,6 @@ struct ice_tc_cfg {
struct ice_tc_info tc_info[ICE_MAX_TRAFFIC_CLASS];
};
-struct ice_res_tracker {
- u16 num_entries;
- u16 end;
- u16 list[];
-};
-
struct ice_qs_cfg {
struct mutex *qs_mutex; /* will be assigned to &pf->avail_q_mutex */
unsigned long *pf_map;
@@ -348,7 +339,9 @@ struct ice_vsi {
u32 rx_buf_failed;
u32 rx_page_failed;
u16 num_q_vectors;
- u16 base_vector; /* IRQ base for OS reserved vectors */
+ /* tell if only dynamic irq allocation is allowed */
+ bool irq_dyn_alloc;
+
enum ice_vsi_type type;
u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */
@@ -479,6 +472,7 @@ struct ice_q_vector {
char name[ICE_INT_NAME_STR_LEN];
u16 total_events; /* net_dim(): number of interrupts processed */
+ struct msi_map irq;
} ____cacheline_internodealigned_in_smp;
enum ice_pf_flags {
@@ -514,6 +508,12 @@ enum ice_pf_flags {
ICE_PF_FLAGS_NBITS /* must be last */
};
+enum ice_misc_thread_tasks {
+ ICE_MISC_THREAD_EXTTS_EVENT,
+ ICE_MISC_THREAD_TX_TSTAMP,
+ ICE_MISC_THREAD_NBITS /* must be last */
+};
+
struct ice_switchdev_info {
struct ice_vsi *control_vsi;
struct ice_vsi *uplink_vsi;
@@ -539,7 +539,7 @@ struct ice_pf {
/* OS reserved IRQ details */
struct msix_entry *msix_entries;
- struct ice_res_tracker *irq_tracker;
+ struct ice_irq_tracker irq_tracker;
/* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the
* number of MSIX vectors needed for all SR-IOV VFs from the number of
* MSIX vectors allowed on this PF.
@@ -556,6 +556,7 @@ struct ice_pf {
DECLARE_BITMAP(features, ICE_F_MAX);
DECLARE_BITMAP(state, ICE_STATE_NBITS);
DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS);
+ DECLARE_BITMAP(misc_thread, ICE_MISC_THREAD_NBITS);
unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */
unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */
unsigned long serv_tmr_period;
@@ -583,8 +584,7 @@ struct ice_pf {
u32 hw_csum_rx_error;
u32 oicr_err_reg;
- u16 oicr_idx; /* Other interrupt cause MSIX vector index */
- u16 num_avail_sw_msix; /* remaining MSIX SW vectors left unclaimed */
+ struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */
u16 max_pf_txqs; /* Total Tx queues PF wide */
u16 max_pf_rxqs; /* Total Rx queues PF wide */
u16 num_lan_msix; /* Total MSIX vectors for base driver */
@@ -670,7 +670,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
struct ice_q_vector *q_vector)
{
u32 vector = (vsi && q_vector) ? q_vector->reg_idx :
- ((struct ice_pf *)hw->back)->oicr_idx;
+ ((struct ice_pf *)hw->back)->oicr_irq.index;
int itr = ICE_ITR_NONE;
u32 val;
@@ -821,25 +821,6 @@ static inline bool ice_is_switchdev_running(struct ice_pf *pf)
return pf->switchdev.is_running;
}
-/**
- * ice_set_sriov_cap - enable SRIOV in PF flags
- * @pf: PF struct
- */
-static inline void ice_set_sriov_cap(struct ice_pf *pf)
-{
- if (pf->hw.func_caps.common_cap.sr_iov_1_1)
- set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
-}
-
-/**
- * ice_clear_sriov_cap - disable SRIOV in PF flags
- * @pf: PF struct
- */
-static inline void ice_clear_sriov_cap(struct ice_pf *pf)
-{
- clear_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
-}
-
#define ICE_FD_STAT_CTR_BLOCK_COUNT 256
#define ICE_FD_STAT_PF_IDX(base_idx) \
((base_idx) * ICE_FD_STAT_CTR_BLOCK_COUNT)
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 838d9b274d68..63d3e1dcbba5 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -1087,7 +1087,7 @@ struct ice_aqc_get_phy_caps {
#define ICE_PHY_TYPE_HIGH_100G_CAUI2 BIT_ULL(2)
#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC BIT_ULL(3)
#define ICE_PHY_TYPE_HIGH_100G_AUI2 BIT_ULL(4)
-#define ICE_PHY_TYPE_HIGH_MAX_INDEX 5
+#define ICE_PHY_TYPE_HIGH_MAX_INDEX 4
struct ice_aqc_get_phy_caps_data {
__le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
index fba178e07600..cca0e753f38f 100644
--- a/drivers/net/ethernet/intel/ice/ice_arfs.c
+++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
@@ -596,7 +596,7 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi)
{
struct net_device *netdev;
struct ice_pf *pf;
- int base_idx, i;
+ int i;
if (!vsi || vsi->type != ICE_VSI_PF)
return 0;
@@ -613,10 +613,9 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi)
if (unlikely(!netdev->rx_cpu_rmap))
return -EINVAL;
- base_idx = vsi->base_vector;
ice_for_each_q_vector(vsi, i)
if (irq_cpu_rmap_add(netdev->rx_cpu_rmap,
- pf->msix_entries[base_idx + i].vector)) {
+ vsi->q_vectors[i]->irq.virq)) {
ice_free_cpu_rx_rmap(vsi);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index 1911d644dfa8..074bf9403cd1 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -103,10 +103,10 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
{
struct ice_pf *pf = vsi->back;
struct ice_q_vector *q_vector;
+ int err;
/* allocate q_vector */
- q_vector = devm_kzalloc(ice_pf_to_dev(pf), sizeof(*q_vector),
- GFP_KERNEL);
+ q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL);
if (!q_vector)
return -ENOMEM;
@@ -118,9 +118,34 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
q_vector->rx.itr_mode = ITR_DYNAMIC;
q_vector->tx.type = ICE_TX_CONTAINER;
q_vector->rx.type = ICE_RX_CONTAINER;
+ q_vector->irq.index = -ENOENT;
- if (vsi->type == ICE_VSI_VF)
+ if (vsi->type == ICE_VSI_VF) {
+ q_vector->reg_idx = ice_calc_vf_reg_idx(vsi->vf, q_vector);
goto out;
+ } else if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
+ struct ice_vsi *ctrl_vsi = ice_get_vf_ctrl_vsi(pf, vsi);
+
+ if (ctrl_vsi) {
+ if (unlikely(!ctrl_vsi->q_vectors)) {
+ err = -ENOENT;
+ goto err_free_q_vector;
+ }
+
+ q_vector->irq = ctrl_vsi->q_vectors[0]->irq;
+ goto skip_alloc;
+ }
+ }
+
+ q_vector->irq = ice_alloc_irq(pf, vsi->irq_dyn_alloc);
+ if (q_vector->irq.index < 0) {
+ err = -ENOMEM;
+ goto err_free_q_vector;
+ }
+
+skip_alloc:
+ q_vector->reg_idx = q_vector->irq.index;
+
/* only set affinity_mask if the CPU is online */
if (cpu_online(v_idx))
cpumask_set_cpu(v_idx, &q_vector->affinity_mask);
@@ -137,6 +162,11 @@ out:
vsi->q_vectors[v_idx] = q_vector;
return 0;
+
+err_free_q_vector:
+ kfree(q_vector);
+
+ return err;
}
/**
@@ -168,7 +198,19 @@ static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx)
if (vsi->netdev)
netif_napi_del(&q_vector->napi);
- devm_kfree(dev, q_vector);
+ /* release MSIX interrupt if q_vector had interrupt allocated */
+ if (q_vector->irq.index < 0)
+ goto free_q_vector;
+
+ /* only free last VF ctrl vsi interrupt */
+ if (vsi->type == ICE_VSI_CTRL && vsi->vf &&
+ ice_get_vf_ctrl_vsi(pf, vsi))
+ goto free_q_vector;
+
+ ice_free_irq(pf, q_vector->irq);
+
+free_q_vector:
+ kfree(q_vector);
vsi->q_vectors[v_idx] = NULL;
}
@@ -393,7 +435,8 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
/* Receive Packet Data Buffer Size.
* The Packet Data Buffer Size is defined in 128 byte units.
*/
- rlan_ctx.dbuf = ring->rx_buf_len >> ICE_RLAN_CTX_DBUF_S;
+ rlan_ctx.dbuf = DIV_ROUND_UP(ring->rx_buf_len,
+ BIT_ULL(ICE_RLAN_CTX_DBUF_S));
/* use 32 byte descriptors */
rlan_ctx.dsize = 1;
@@ -758,6 +801,8 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
ice_for_each_q_vector(vsi, v_idx)
ice_free_q_vector(vsi, v_idx);
+
+ vsi->num_q_vectors = 0;
}
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index eb2dc0983776..e16d4c83ed5f 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -814,8 +814,7 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
devm_kfree(ice_hw_to_dev(hw), lst_itr);
}
}
- if (recps[i].root_buf)
- devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
+ devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
}
ice_rm_all_sw_replay_rule_info(hw);
devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
@@ -834,7 +833,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw)
u16 size;
size = sizeof(*config) * ICE_AQC_FW_LOG_ID_MAX;
- config = devm_kzalloc(ice_hw_to_dev(hw), size, GFP_KERNEL);
+ config = kzalloc(size, GFP_KERNEL);
if (!config)
return -ENOMEM;
@@ -857,7 +856,7 @@ static int ice_get_fw_log_cfg(struct ice_hw *hw)
}
}
- devm_kfree(ice_hw_to_dev(hw), config);
+ kfree(config);
return status;
}
@@ -1011,8 +1010,7 @@ static int ice_cfg_fw_log(struct ice_hw *hw, bool enable)
}
out:
- if (data)
- devm_kfree(ice_hw_to_dev(hw), data);
+ devm_kfree(ice_hw_to_dev(hw), data);
return status;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c
index d2faf1baad2f..e7d2474c431c 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.c
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.c
@@ -339,8 +339,7 @@ do { \
} \
} \
/* free the buffer info list */ \
- if ((qi)->ring.cmd_buf) \
- devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
+ devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
/* free DMA head */ \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
} while (0)
@@ -1056,14 +1055,19 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
if (cq->sq.next_to_use == cq->sq.count)
cq->sq.next_to_use = 0;
wr32(hw, cq->sq.tail, cq->sq.next_to_use);
+ ice_flush(hw);
+
+ /* Wait a short time before initial ice_sq_done() check, to allow
+ * hardware time for completion.
+ */
+ udelay(5);
timeout = jiffies + ICE_CTL_Q_SQ_CMD_TIMEOUT;
do {
if (ice_sq_done(hw, cq))
break;
- usleep_range(ICE_CTL_Q_SQ_CMD_USEC,
- ICE_CTL_Q_SQ_CMD_USEC * 3 / 2);
+ usleep_range(100, 150);
} while (time_before(jiffies, timeout));
/* if ready, copy the desc back to temp */
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h
index 950b7f4a7a05..8f2fd1613a95 100644
--- a/drivers/net/ethernet/intel/ice/ice_controlq.h
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.h
@@ -35,7 +35,6 @@ enum ice_ctl_q {
/* Control Queue timeout settings - max delay 1s */
#define ICE_CTL_Q_SQ_CMD_TIMEOUT HZ /* Wait max 1s */
-#define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */
#define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */
#define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */
diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.h b/drivers/net/ethernet/intel/ice/ice_ddp.h
index 37eadb3d27a8..41acfe26df1c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ddp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ddp.h
@@ -185,7 +185,7 @@ struct ice_buf_hdr {
#define ICE_MAX_ENTRIES_IN_BUF(hd_sz, ent_sz) \
((ICE_PKG_BUF_SIZE - \
- struct_size((struct ice_buf_hdr *)0, section_entry, 1) - (hd_sz)) / \
+ struct_size_t(struct ice_buf_hdr, section_entry, 1) - (hd_sz)) / \
(ent_sz))
/* ice package section IDs */
@@ -297,7 +297,7 @@ struct ice_label_section {
};
#define ICE_MAX_LABELS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_label_section *)0, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_label_section, \
label, 1) - \
sizeof(struct ice_label), \
sizeof(struct ice_label))
@@ -352,7 +352,7 @@ struct ice_boost_tcam_section {
};
#define ICE_MAX_BST_TCAMS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF(struct_size((struct ice_boost_tcam_section *)0, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_boost_tcam_section, \
tcam, 1) - \
sizeof(struct ice_boost_tcam_entry), \
sizeof(struct ice_boost_tcam_entry))
@@ -372,8 +372,7 @@ struct ice_marker_ptype_tcam_section {
};
#define ICE_MAX_MARKER_PTYPE_TCAMS_IN_BUF \
- ICE_MAX_ENTRIES_IN_BUF( \
- struct_size((struct ice_marker_ptype_tcam_section *)0, tcam, \
+ ICE_MAX_ENTRIES_IN_BUF(struct_size_t(struct ice_marker_ptype_tcam_section, tcam, \
1) - \
sizeof(struct ice_marker_ptype_tcam_entry), \
sizeof(struct ice_marker_ptype_tcam_entry))
diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c
index bc44cc220818..80dc5445b50d 100644
--- a/drivers/net/ethernet/intel/ice/ice_devlink.c
+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c
@@ -1256,8 +1256,6 @@ static const struct devlink_ops ice_devlink_ops = {
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
.reload_down = ice_devlink_reload_down,
.reload_up = ice_devlink_reload_up,
- .port_split = ice_devlink_port_split,
- .port_unsplit = ice_devlink_port_unsplit,
.eswitch_mode_get = ice_eswitch_mode_get,
.eswitch_mode_set = ice_eswitch_mode_set,
.info_get = ice_devlink_info_get,
@@ -1512,6 +1510,11 @@ ice_devlink_set_port_split_options(struct ice_pf *pf,
ice_active_port_option = active_idx;
}
+static const struct devlink_port_ops ice_devlink_port_ops = {
+ .port_split = ice_devlink_port_split,
+ .port_unsplit = ice_devlink_port_unsplit,
+};
+
/**
* ice_devlink_create_pf_port - Create a devlink port for this PF
* @pf: the PF to create a devlink port for
@@ -1551,7 +1554,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf)
devlink_port_attrs_set(devlink_port, &attrs);
devlink = priv_to_devlink(pf);
- err = devlink_port_register(devlink, devlink_port, vsi->idx);
+ err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx,
+ &ice_devlink_port_ops);
if (err) {
dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
pf->hw.pf_id, err);
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index f6dd3f8fd936..459e32f6adb5 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -10,16 +10,15 @@
#include "ice_tc_lib.h"
/**
- * ice_eswitch_add_vf_mac_rule - add adv rule with VF's MAC
+ * ice_eswitch_add_vf_sp_rule - add adv rule with VF's VSI index
* @pf: pointer to PF struct
* @vf: pointer to VF struct
- * @mac: VF's MAC address
*
* This function adds advanced rule that forwards packets with
- * VF's MAC address (src MAC) to the corresponding switchdev ctrl VSI queue.
+ * VF's VSI index to the corresponding switchdev ctrl VSI queue.
*/
-int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac)
+static int
+ice_eswitch_add_vf_sp_rule(struct ice_pf *pf, struct ice_vf *vf)
{
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
struct ice_adv_rule_info rule_info = { 0 };
@@ -32,76 +31,41 @@ ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac)
if (!list)
return -ENOMEM;
- list[0].type = ICE_MAC_OFOS;
- ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac);
- eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr);
+ ice_rule_add_src_vsi_metadata(list);
- rule_info.sw_act.flag |= ICE_FLTR_TX;
+ rule_info.sw_act.flag = ICE_FLTR_TX;
rule_info.sw_act.vsi_handle = ctrl_vsi->idx;
rule_info.sw_act.fltr_act = ICE_FWD_TO_Q;
- rule_info.rx = false;
rule_info.sw_act.fwd_id.q_id = hw->func_caps.common_cap.rxq_first_id +
ctrl_vsi->rxq_map[vf->vf_id];
rule_info.flags_info.act |= ICE_SINGLE_ACT_LB_ENABLE;
rule_info.flags_info.act_valid = true;
rule_info.tun_type = ICE_SW_TUN_AND_NON_TUN;
+ rule_info.src_vsi = vf->lan_vsi_idx;
err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info,
- vf->repr->mac_rule);
+ &vf->repr->sp_rule);
if (err)
- dev_err(ice_pf_to_dev(pf), "Unable to add VF mac rule in switchdev mode for VF %d",
+ dev_err(ice_pf_to_dev(pf), "Unable to add VF slow-path rule in switchdev mode for VF %d",
vf->vf_id);
- else
- vf->repr->rule_added = true;
kfree(list);
return err;
}
/**
- * ice_eswitch_replay_vf_mac_rule - replay adv rule with VF's MAC
- * @vf: pointer to vF struct
- *
- * This function replays VF's MAC rule after reset.
- */
-void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf)
-{
- int err;
-
- if (!ice_is_switchdev_running(vf->pf))
- return;
-
- if (is_valid_ether_addr(vf->hw_lan_addr)) {
- err = ice_eswitch_add_vf_mac_rule(vf->pf, vf,
- vf->hw_lan_addr);
- if (err) {
- dev_err(ice_pf_to_dev(vf->pf), "Failed to add MAC %pM for VF %d\n, error %d\n",
- vf->hw_lan_addr, vf->vf_id, err);
- return;
- }
- vf->num_mac++;
-
- ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr);
- }
-}
-
-/**
- * ice_eswitch_del_vf_mac_rule - delete adv rule with VF's MAC
+ * ice_eswitch_del_vf_sp_rule - delete adv rule with VF's VSI index
* @vf: pointer to the VF struct
*
- * Delete the advanced rule that was used to forward packets with the VF's MAC
- * address (src MAC) to the corresponding switchdev ctrl VSI queue.
+ * Delete the advanced rule that was used to forward packets with the VF's VSI
+ * index to the corresponding switchdev ctrl VSI queue.
*/
-void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf)
+static void ice_eswitch_del_vf_sp_rule(struct ice_vf *vf)
{
- if (!ice_is_switchdev_running(vf->pf))
- return;
-
- if (!vf->repr->rule_added)
+ if (!vf->repr)
return;
- ice_rem_adv_rule_by_id(&vf->pf->hw, vf->repr->mac_rule);
- vf->repr->rule_added = false;
+ ice_rem_adv_rule_by_id(&vf->pf->hw, &vf->repr->sp_rule);
}
/**
@@ -237,6 +201,7 @@ ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi)
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
+ ice_eswitch_del_vf_sp_rule(vf);
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
@@ -264,25 +229,30 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf)
vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
GFP_KERNEL);
if (!vf->repr->dst) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
+ ICE_FWD_TO_VSI);
+ goto err;
+ }
+
+ if (ice_eswitch_add_vf_sp_rule(pf, vf)) {
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
goto err;
}
if (ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof)) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
+ ice_eswitch_del_vf_sp_rule(vf);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
goto err;
}
if (ice_vsi_add_vlan_zero(vsi)) {
- ice_fltr_add_mac_and_broadcast(vsi,
- vf->hw_lan_addr,
+ ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr,
ICE_FWD_TO_VSI);
+ ice_eswitch_del_vf_sp_rule(vf);
metadata_dst_free(vf->repr->dst);
vf->repr->dst = NULL;
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
@@ -361,6 +331,9 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
np = netdev_priv(netdev);
vsi = np->vsi;
+ if (!vsi || !ice_is_switchdev_running(vsi->back))
+ return NETDEV_TX_BUSY;
+
if (ice_is_reset_in_progress(vsi->back->state) ||
test_bit(ICE_VF_DIS, vsi->back->state))
return NETDEV_TX_BUSY;
@@ -568,6 +541,12 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
break;
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
{
+ if (ice_is_adq_active(pf)) {
+ dev_err(ice_pf_to_dev(pf), "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+ NL_SET_ERR_MSG_MOD(extack, "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
+ return -EOPNOTSUPP;
+ }
+
dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to switchdev",
pf->hw.pf_id);
NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to switchdev");
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h
index 6a413331572b..b18bf83a2f5b 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h
@@ -20,11 +20,6 @@ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf);
void ice_eswitch_update_repr(struct ice_vsi *vsi);
void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf);
-int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf,
- const u8 *mac);
-void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf);
-void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf);
void ice_eswitch_set_target_vsi(struct sk_buff *skb,
struct ice_tx_offload_params *off);
@@ -34,15 +29,6 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
static inline void ice_eswitch_release(struct ice_pf *pf) { }
static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { }
-static inline void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) { }
-static inline void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) { }
-
-static inline int
-ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf,
- const u8 *mac)
-{
- return -EOPNOTSUPP;
-}
static inline void
ice_eswitch_set_target_vsi(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index f86e814354a3..ad4d4702129f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -4,6 +4,7 @@
/* ethtool support for ice */
#include "ice.h"
+#include "ice_ethtool.h"
#include "ice_flow.h"
#include "ice_fltr.h"
#include "ice_lib.h"
@@ -956,7 +957,7 @@ static u64 ice_intr_test(struct net_device *netdev)
netdev_info(netdev, "interrupt test\n");
- wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_irq.index),
GLINT_DYN_CTL_SW_ITR_INDX_M |
GLINT_DYN_CTL_INTENA_MSK_M |
GLINT_DYN_CTL_SWINT_TRIG_M);
@@ -1658,15 +1659,26 @@ ice_mask_min_supported_speeds(struct ice_hw *hw,
*phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G;
}
-#define ice_ethtool_advertise_link_mode(aq_link_speed, ethtool_link_mode) \
- do { \
- if (req_speeds & (aq_link_speed) || \
- (!req_speeds && \
- (advert_phy_type_lo & phy_type_mask_lo || \
- advert_phy_type_hi & phy_type_mask_hi))) \
- ethtool_link_ksettings_add_link_mode(ks, advertising,\
- ethtool_link_mode); \
- } while (0)
+/**
+ * ice_linkmode_set_bit - set link mode bit
+ * @phy_to_ethtool: PHY type to ethtool link mode struct to set
+ * @ks: ethtool link ksettings struct to fill out
+ * @req_speeds: speed requested by user
+ * @advert_phy_type: advertised PHY type
+ * @phy_type: PHY type
+ */
+static void
+ice_linkmode_set_bit(const struct ice_phy_type_to_ethtool *phy_to_ethtool,
+ struct ethtool_link_ksettings *ks, u32 req_speeds,
+ u64 advert_phy_type, u32 phy_type)
+{
+ linkmode_set_bit(phy_to_ethtool->link_mode, ks->link_modes.supported);
+
+ if (req_speeds & phy_to_ethtool->aq_link_speed ||
+ (!req_speeds && advert_phy_type & BIT(phy_type)))
+ linkmode_set_bit(phy_to_ethtool->link_mode,
+ ks->link_modes.advertising);
+}
/**
* ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes
@@ -1682,11 +1694,10 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
struct ice_pf *pf = vsi->back;
u64 advert_phy_type_lo = 0;
u64 advert_phy_type_hi = 0;
- u64 phy_type_mask_lo = 0;
- u64 phy_type_mask_hi = 0;
u64 phy_types_high = 0;
u64 phy_types_low = 0;
- u16 req_speeds;
+ u32 req_speeds;
+ u32 i;
req_speeds = vsi->port_info->phy.link_info.req_speeds;
@@ -1743,272 +1754,22 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
advert_phy_type_hi = vsi->port_info->phy.phy_type_high;
}
- ethtool_link_ksettings_zero_link_mode(ks, supported);
- ethtool_link_ksettings_zero_link_mode(ks, advertising);
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100BASE_TX |
- ICE_PHY_TYPE_LOW_100M_SGMII;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100baseT_Full);
-
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100MB,
- 100baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_T |
- ICE_PHY_TYPE_LOW_1G_SGMII;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_KX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseKX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseKX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_1000BASE_SX |
- ICE_PHY_TYPE_LOW_1000BASE_LX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 1000baseX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_1000MB,
- 1000baseX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_T;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 2500baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
- 2500baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_2500BASE_X |
- ICE_PHY_TYPE_LOW_2500BASE_KX;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 2500baseX_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_2500MB,
- 2500baseX_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_5GBASE_T |
- ICE_PHY_TYPE_LOW_5GBASE_KR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 5000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_5GB,
- 5000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_T |
- ICE_PHY_TYPE_LOW_10G_SFI_DA |
- ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC |
- ICE_PHY_TYPE_LOW_10G_SFI_C2C;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseT_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseT_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_KR_CR1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseKR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseKR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_SR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseSR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseSR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_10GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 10000baseLR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_10GB,
- 10000baseLR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_T |
- ICE_PHY_TYPE_LOW_25GBASE_CR |
- ICE_PHY_TYPE_LOW_25GBASE_CR_S |
- ICE_PHY_TYPE_LOW_25GBASE_CR1 |
- ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC |
- ICE_PHY_TYPE_LOW_25G_AUI_C2C;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseCR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseCR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_SR |
- ICE_PHY_TYPE_LOW_25GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseSR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseSR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_25GBASE_KR |
- ICE_PHY_TYPE_LOW_25GBASE_KR_S |
- ICE_PHY_TYPE_LOW_25GBASE_KR1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 25000baseKR_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_25GB,
- 25000baseKR_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_KR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseKR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseKR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_CR4 |
- ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC |
- ICE_PHY_TYPE_LOW_40G_XLAUI;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseCR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseCR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_SR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseSR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseSR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_40GBASE_LR4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 40000baseLR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_40GB,
- 40000baseLR4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_CR2 |
- ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_LAUI2 |
- ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_AUI2 |
- ICE_PHY_TYPE_LOW_50GBASE_CP |
- ICE_PHY_TYPE_LOW_50GBASE_SR |
- ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC |
- ICE_PHY_TYPE_LOW_50G_AUI1;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseCR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseCR2_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_KR2 |
- ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseKR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseKR2_Full);
- }
+ linkmode_zero(ks->link_modes.supported);
+ linkmode_zero(ks->link_modes.advertising);
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_50GBASE_SR2 |
- ICE_PHY_TYPE_LOW_50GBASE_LR2 |
- ICE_PHY_TYPE_LOW_50GBASE_FR |
- ICE_PHY_TYPE_LOW_50GBASE_LR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 50000baseSR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_50GB,
- 50000baseSR2_Full);
+ for (i = 0; i < BITS_PER_TYPE(u64); i++) {
+ if (phy_types_low & BIT_ULL(i))
+ ice_linkmode_set_bit(&phy_type_low_lkup[i], ks,
+ req_speeds, advert_phy_type_lo,
+ i);
}
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_CR4 |
- ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC |
- ICE_PHY_TYPE_LOW_100G_CAUI4 |
- ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC |
- ICE_PHY_TYPE_LOW_100G_AUI4 |
- ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4;
- phy_type_mask_hi = ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC |
- ICE_PHY_TYPE_HIGH_100G_CAUI2 |
- ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC |
- ICE_PHY_TYPE_HIGH_100G_AUI2;
- if (phy_types_low & phy_type_mask_lo ||
- phy_types_high & phy_type_mask_hi) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseCR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseCR4_Full);
+ for (i = 0; i < BITS_PER_TYPE(u64); i++) {
+ if (phy_types_high & BIT_ULL(i))
+ ice_linkmode_set_bit(&phy_type_high_lkup[i], ks,
+ req_speeds, advert_phy_type_hi,
+ i);
}
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseCR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseCR2_Full);
- }
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseSR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseSR4_Full);
- }
-
- if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseSR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseSR2_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_LR4 |
- ICE_PHY_TYPE_LOW_100GBASE_DR;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseLR4_ER4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseLR4_ER4_Full);
- }
-
- phy_type_mask_lo = ICE_PHY_TYPE_LOW_100GBASE_KR4 |
- ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4;
- if (phy_types_low & phy_type_mask_lo) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseKR4_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseKR4_Full);
- }
-
- if (phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) {
- ethtool_link_ksettings_add_link_mode(ks, supported,
- 100000baseKR2_Full);
- ice_ethtool_advertise_link_mode(ICE_AQ_LINK_SPEED_100GB,
- 100000baseKR2_Full);
- }
-
}
#define TEST_SET_BITS_TIMEOUT 50
@@ -2920,8 +2681,13 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
ring->rx_max_pending = ICE_MAX_NUM_DESC;
ring->tx_max_pending = ICE_MAX_NUM_DESC;
- ring->rx_pending = vsi->rx_rings[0]->count;
- ring->tx_pending = vsi->tx_rings[0]->count;
+ if (vsi->tx_rings && vsi->rx_rings) {
+ ring->rx_pending = vsi->rx_rings[0]->count;
+ ring->tx_pending = vsi->tx_rings[0]->count;
+ } else {
+ ring->rx_pending = 0;
+ ring->tx_pending = 0;
+ }
/* Rx mini and jumbo rings are not supported */
ring->rx_mini_max_pending = 0;
@@ -2955,6 +2721,10 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
return -EINVAL;
}
+ /* Return if there is no rings (device is reloading) */
+ if (!vsi->tx_rings || !vsi->rx_rings)
+ return -EBUSY;
+
new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE);
if (new_tx_cnt != ring->tx_pending)
netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.h b/drivers/net/ethernet/intel/ice/ice_ethtool.h
new file mode 100644
index 000000000000..b403ee79cd5e
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2023 Intel Corporation */
+
+#ifndef _ICE_ETHTOOL_H_
+#define _ICE_ETHTOOL_H_
+
+struct ice_phy_type_to_ethtool {
+ u64 aq_link_speed;
+ u8 link_mode;
+};
+
+/* Macro to make PHY type to Ethtool link mode table entry.
+ * The index is the PHY type.
+ */
+#define ICE_PHY_TYPE(LINK_SPEED, ETHTOOL_LINK_MODE) {\
+ .aq_link_speed = ICE_AQ_LINK_SPEED_##LINK_SPEED, \
+ .link_mode = ETHTOOL_LINK_MODE_##ETHTOOL_LINK_MODE##_BIT, \
+}
+
+/* Lookup table mapping PHY type low to link speed and Ethtool link modes.
+ * Array index corresponds to HW PHY type bit, see
+ * ice_adminq_cmd.h:ICE_PHY_TYPE_LOW_*.
+ */
+static const struct ice_phy_type_to_ethtool
+phy_type_low_lkup[] = {
+ [0] = ICE_PHY_TYPE(100MB, 100baseT_Full),
+ [1] = ICE_PHY_TYPE(100MB, 100baseT_Full),
+ [2] = ICE_PHY_TYPE(1000MB, 1000baseT_Full),
+ [3] = ICE_PHY_TYPE(1000MB, 1000baseX_Full),
+ [4] = ICE_PHY_TYPE(1000MB, 1000baseX_Full),
+ [5] = ICE_PHY_TYPE(1000MB, 1000baseKX_Full),
+ [6] = ICE_PHY_TYPE(1000MB, 1000baseT_Full),
+ [7] = ICE_PHY_TYPE(2500MB, 2500baseT_Full),
+ [8] = ICE_PHY_TYPE(2500MB, 2500baseX_Full),
+ [9] = ICE_PHY_TYPE(2500MB, 2500baseX_Full),
+ [10] = ICE_PHY_TYPE(5GB, 5000baseT_Full),
+ [11] = ICE_PHY_TYPE(5GB, 5000baseT_Full),
+ [12] = ICE_PHY_TYPE(10GB, 10000baseT_Full),
+ [13] = ICE_PHY_TYPE(10GB, 10000baseCR_Full),
+ [14] = ICE_PHY_TYPE(10GB, 10000baseSR_Full),
+ [15] = ICE_PHY_TYPE(10GB, 10000baseLR_Full),
+ [16] = ICE_PHY_TYPE(10GB, 10000baseKR_Full),
+ [17] = ICE_PHY_TYPE(10GB, 10000baseCR_Full),
+ [18] = ICE_PHY_TYPE(10GB, 10000baseKR_Full),
+ [19] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [20] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [21] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [22] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [23] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [24] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [25] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [26] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [27] = ICE_PHY_TYPE(25GB, 25000baseKR_Full),
+ [28] = ICE_PHY_TYPE(25GB, 25000baseSR_Full),
+ [29] = ICE_PHY_TYPE(25GB, 25000baseCR_Full),
+ [30] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full),
+ [31] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full),
+ [32] = ICE_PHY_TYPE(40GB, 40000baseLR4_Full),
+ [33] = ICE_PHY_TYPE(40GB, 40000baseKR4_Full),
+ [34] = ICE_PHY_TYPE(40GB, 40000baseSR4_Full),
+ [35] = ICE_PHY_TYPE(40GB, 40000baseCR4_Full),
+ [36] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [37] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [38] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [39] = ICE_PHY_TYPE(50GB, 50000baseKR2_Full),
+ [40] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [41] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [42] = ICE_PHY_TYPE(50GB, 50000baseSR2_Full),
+ [43] = ICE_PHY_TYPE(50GB, 50000baseCR2_Full),
+ [44] = ICE_PHY_TYPE(50GB, 50000baseCR_Full),
+ [45] = ICE_PHY_TYPE(50GB, 50000baseSR_Full),
+ [46] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full),
+ [47] = ICE_PHY_TYPE(50GB, 50000baseLR_ER_FR_Full),
+ [48] = ICE_PHY_TYPE(50GB, 50000baseKR_Full),
+ [49] = ICE_PHY_TYPE(50GB, 50000baseSR_Full),
+ [50] = ICE_PHY_TYPE(50GB, 50000baseCR_Full),
+ [51] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [52] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full),
+ [53] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full),
+ [54] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full),
+ [55] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [56] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [57] = ICE_PHY_TYPE(100GB, 100000baseSR4_Full),
+ [58] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [59] = ICE_PHY_TYPE(100GB, 100000baseCR4_Full),
+ [60] = ICE_PHY_TYPE(100GB, 100000baseKR4_Full),
+ [61] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+ [62] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [63] = ICE_PHY_TYPE(100GB, 100000baseLR4_ER4_Full),
+};
+
+/* Lookup table mapping PHY type high to link speed and Ethtool link modes.
+ * Array index corresponds to HW PHY type bit, see
+ * ice_adminq_cmd.h:ICE_PHY_TYPE_HIGH_*
+ */
+static const struct ice_phy_type_to_ethtool
+phy_type_high_lkup[] = {
+ [0] = ICE_PHY_TYPE(100GB, 100000baseKR2_Full),
+ [1] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [2] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+ [3] = ICE_PHY_TYPE(100GB, 100000baseSR2_Full),
+ [4] = ICE_PHY_TYPE(100GB, 100000baseCR2_Full),
+};
+
+#endif /* !_ICE_ETHTOOL_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
index ead6d50fc0ad..8c6e13f87b7d 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
@@ -1281,16 +1281,21 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
ICE_FLOW_FLD_OFF_INVAL);
}
- /* add filter for outer headers */
fltr_idx = ice_ethtool_flow_to_fltr(fsp->flow_type & ~FLOW_EXT);
+
+ assign_bit(fltr_idx, hw->fdir_perfect_fltr, perfect_filter);
+
+ /* add filter for outer headers */
ret = ice_fdir_set_hw_fltr_rule(pf, seg, fltr_idx,
ICE_FD_HW_SEG_NON_TUN);
- if (ret == -EEXIST)
- /* Rule already exists, free memory and continue */
- devm_kfree(dev, seg);
- else if (ret)
+ if (ret == -EEXIST) {
+ /* Rule already exists, free memory and count as success */
+ ret = 0;
+ goto err_exit;
+ } else if (ret) {
/* could not write filter, free memory */
goto err_exit;
+ }
/* make tunneled filter HW entries if possible */
memcpy(&tun_seg[1], seg, sizeof(*seg));
@@ -1305,18 +1310,13 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
devm_kfree(dev, tun_seg);
}
- if (perfect_filter)
- set_bit(fltr_idx, hw->fdir_perfect_fltr);
- else
- clear_bit(fltr_idx, hw->fdir_perfect_fltr);
-
return ret;
err_exit:
devm_kfree(dev, tun_seg);
devm_kfree(dev, seg);
- return -EOPNOTSUPP;
+ return ret;
}
/**
@@ -1914,7 +1914,9 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
/* input struct is added to the HW filter list */
- ice_fdir_update_list_entry(pf, input, fsp->location);
+ ret = ice_fdir_update_list_entry(pf, input, fsp->location);
+ if (ret)
+ goto release_lock;
ret = ice_fdir_write_all_fltr(pf, input, true);
if (ret)
diff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c
index ef103e47a8dc..85cca572c22a 100644
--- a/drivers/net/ethernet/intel/ice/ice_flow.c
+++ b/drivers/net/ethernet/intel/ice/ice_flow.c
@@ -1304,23 +1304,6 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
}
/**
- * ice_dealloc_flow_entry - Deallocate flow entry memory
- * @hw: pointer to the HW struct
- * @entry: flow entry to be removed
- */
-static void
-ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
-{
- if (!entry)
- return;
-
- if (entry->entry)
- devm_kfree(ice_hw_to_dev(hw), entry->entry);
-
- devm_kfree(ice_hw_to_dev(hw), entry);
-}
-
-/**
* ice_flow_rem_entry_sync - Remove a flow entry
* @hw: pointer to the HW struct
* @blk: classification stage
@@ -1335,7 +1318,8 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
list_del(&entry->l_entry);
- ice_dealloc_flow_entry(hw, entry);
+ devm_kfree(ice_hw_to_dev(hw), entry->entry);
+ devm_kfree(ice_hw_to_dev(hw), entry);
return 0;
}
@@ -1662,8 +1646,7 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
out:
if (status && e) {
- if (e->entry)
- devm_kfree(ice_hw_to_dev(hw), e->entry);
+ devm_kfree(ice_hw_to_dev(hw), e->entry);
devm_kfree(ice_hw_to_dev(hw), e);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_idc.c b/drivers/net/ethernet/intel/ice/ice_idc.c
index e6bc2285071e..145b27f2a4ce 100644
--- a/drivers/net/ethernet/intel/ice/ice_idc.c
+++ b/drivers/net/ethernet/intel/ice/ice_idc.c
@@ -229,20 +229,34 @@ void ice_get_qos_params(struct ice_pf *pf, struct iidc_qos_params *qos)
EXPORT_SYMBOL_GPL(ice_get_qos_params);
/**
- * ice_reserve_rdma_qvector - Reserve vector resources for RDMA driver
+ * ice_alloc_rdma_qvectors - Allocate vector resources for RDMA driver
* @pf: board private structure to initialize
*/
-static int ice_reserve_rdma_qvector(struct ice_pf *pf)
+static int ice_alloc_rdma_qvectors(struct ice_pf *pf)
{
if (ice_is_rdma_ena(pf)) {
- int index;
-
- index = ice_get_res(pf, pf->irq_tracker, pf->num_rdma_msix,
- ICE_RES_RDMA_VEC_ID);
- if (index < 0)
- return index;
- pf->num_avail_sw_msix -= pf->num_rdma_msix;
- pf->rdma_base_vector = (u16)index;
+ int i;
+
+ pf->msix_entries = kcalloc(pf->num_rdma_msix,
+ sizeof(*pf->msix_entries),
+ GFP_KERNEL);
+ if (!pf->msix_entries)
+ return -ENOMEM;
+
+ /* RDMA is the only user of pf->msix_entries array */
+ pf->rdma_base_vector = 0;
+
+ for (i = 0; i < pf->num_rdma_msix; i++) {
+ struct msix_entry *entry = &pf->msix_entries[i];
+ struct msi_map map;
+
+ map = ice_alloc_irq(pf, false);
+ if (map.index < 0)
+ break;
+
+ entry->entry = map.index;
+ entry->vector = map.virq;
+ }
}
return 0;
}
@@ -253,9 +267,21 @@ static int ice_reserve_rdma_qvector(struct ice_pf *pf)
*/
static void ice_free_rdma_qvector(struct ice_pf *pf)
{
- pf->num_avail_sw_msix -= pf->num_rdma_msix;
- ice_free_res(pf->irq_tracker, pf->rdma_base_vector,
- ICE_RES_RDMA_VEC_ID);
+ int i;
+
+ if (!pf->msix_entries)
+ return;
+
+ for (i = 0; i < pf->num_rdma_msix; i++) {
+ struct msi_map map;
+
+ map.index = pf->msix_entries[i].entry;
+ map.virq = pf->msix_entries[i].vector;
+ ice_free_irq(pf, map);
+ }
+
+ kfree(pf->msix_entries);
+ pf->msix_entries = NULL;
}
/**
@@ -357,7 +383,7 @@ int ice_init_rdma(struct ice_pf *pf)
}
/* Reserve vector resources */
- ret = ice_reserve_rdma_qvector(pf);
+ ret = ice_alloc_rdma_qvectors(pf);
if (ret < 0) {
dev_err(dev, "failed to reserve vectors for RDMA\n");
goto err_reserve_rdma_qvector;
diff --git a/drivers/net/ethernet/intel/ice/ice_irq.c b/drivers/net/ethernet/intel/ice/ice_irq.c
new file mode 100644
index 000000000000..ad82ff7d1995
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_irq.c
@@ -0,0 +1,378 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2023, Intel Corporation. */
+
+#include "ice.h"
+#include "ice_lib.h"
+#include "ice_irq.h"
+
+/**
+ * ice_init_irq_tracker - initialize interrupt tracker
+ * @pf: board private structure
+ * @max_vectors: maximum number of vectors that tracker can hold
+ * @num_static: number of preallocated interrupts
+ */
+static void
+ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors,
+ unsigned int num_static)
+{
+ pf->irq_tracker.num_entries = max_vectors;
+ pf->irq_tracker.num_static = num_static;
+ xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC);
+}
+
+/**
+ * ice_deinit_irq_tracker - free xarray tracker
+ * @pf: board private structure
+ */
+static void ice_deinit_irq_tracker(struct ice_pf *pf)
+{
+ xa_destroy(&pf->irq_tracker.entries);
+}
+
+/**
+ * ice_free_irq_res - free a block of resources
+ * @pf: board private structure
+ * @index: starting index previously returned by ice_get_res
+ */
+static void ice_free_irq_res(struct ice_pf *pf, u16 index)
+{
+ struct ice_irq_entry *entry;
+
+ entry = xa_erase(&pf->irq_tracker.entries, index);
+ kfree(entry);
+}
+
+/**
+ * ice_get_irq_res - get an interrupt resource
+ * @pf: board private structure
+ * @dyn_only: force entry to be dynamically allocated
+ *
+ * Allocate new irq entry in the free slot of the tracker. Since xarray
+ * is used, always allocate new entry at the lowest possible index. Set
+ * proper allocation limit for maximum tracker entries.
+ *
+ * Returns allocated irq entry or NULL on failure.
+ */
+static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf, bool dyn_only)
+{
+ struct xa_limit limit = { .max = pf->irq_tracker.num_entries,
+ .min = 0 };
+ unsigned int num_static = pf->irq_tracker.num_static;
+ struct ice_irq_entry *entry;
+ unsigned int index;
+ int ret;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return NULL;
+
+ /* skip preallocated entries if the caller says so */
+ if (dyn_only)
+ limit.min = num_static;
+
+ ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit,
+ GFP_KERNEL);
+
+ if (ret) {
+ kfree(entry);
+ entry = NULL;
+ } else {
+ entry->index = index;
+ entry->dynamic = index >= num_static;
+ }
+
+ return entry;
+}
+
+/**
+ * ice_reduce_msix_usage - Reduce usage of MSI-X vectors
+ * @pf: board private structure
+ * @v_remain: number of remaining MSI-X vectors to be distributed
+ *
+ * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled.
+ * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of
+ * remaining vectors.
+ */
+static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain)
+{
+ int v_rdma;
+
+ if (!ice_is_rdma_ena(pf)) {
+ pf->num_lan_msix = v_remain;
+ return;
+ }
+
+ /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */
+ v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1;
+
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) {
+ dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n");
+ clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+
+ pf->num_rdma_msix = 0;
+ pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
+ } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) ||
+ (v_remain - v_rdma < v_rdma)) {
+ /* Support minimum RDMA and give remaining vectors to LAN MSIX
+ */
+ pf->num_rdma_msix = ICE_MIN_RDMA_MSIX;
+ pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX;
+ } else {
+ /* Split remaining MSIX with RDMA after accounting for AEQ MSIX
+ */
+ pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 +
+ ICE_RDMA_NUM_AEQ_MSIX;
+ pf->num_lan_msix = v_remain - pf->num_rdma_msix;
+ }
+}
+
+/**
+ * ice_ena_msix_range - Request a range of MSIX vectors from the OS
+ * @pf: board private structure
+ *
+ * Compute the number of MSIX vectors wanted and request from the OS. Adjust
+ * device usage if there are not enough vectors. Return the number of vectors
+ * reserved or negative on failure.
+ */
+static int ice_ena_msix_range(struct ice_pf *pf)
+{
+ int num_cpus, hw_num_msix, v_other, v_wanted, v_actual;
+ struct device *dev = ice_pf_to_dev(pf);
+ int err;
+
+ hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors;
+ num_cpus = num_online_cpus();
+
+ /* LAN miscellaneous handler */
+ v_other = ICE_MIN_LAN_OICR_MSIX;
+
+ /* Flow Director */
+ if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
+ v_other += ICE_FDIR_MSIX;
+
+ /* switchdev */
+ v_other += ICE_ESWITCH_MSIX;
+
+ v_wanted = v_other;
+
+ /* LAN traffic */
+ pf->num_lan_msix = num_cpus;
+ v_wanted += pf->num_lan_msix;
+
+ /* RDMA auxiliary driver */
+ if (ice_is_rdma_ena(pf)) {
+ pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX;
+ v_wanted += pf->num_rdma_msix;
+ }
+
+ if (v_wanted > hw_num_msix) {
+ int v_remain;
+
+ dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n",
+ v_wanted, hw_num_msix);
+
+ if (hw_num_msix < ICE_MIN_MSIX) {
+ err = -ERANGE;
+ goto exit_err;
+ }
+
+ v_remain = hw_num_msix - v_other;
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX) {
+ v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX;
+ v_remain = ICE_MIN_LAN_TXRX_MSIX;
+ }
+
+ ice_reduce_msix_usage(pf, v_remain);
+ v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other;
+
+ dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n",
+ pf->num_lan_msix);
+ if (ice_is_rdma_ena(pf))
+ dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n",
+ pf->num_rdma_msix);
+ }
+
+ /* actually reserve the vectors */
+ v_actual = pci_alloc_irq_vectors(pf->pdev, ICE_MIN_MSIX, v_wanted,
+ PCI_IRQ_MSIX);
+ if (v_actual < 0) {
+ dev_err(dev, "unable to reserve MSI-X vectors\n");
+ err = v_actual;
+ goto exit_err;
+ }
+
+ if (v_actual < v_wanted) {
+ dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n",
+ v_wanted, v_actual);
+
+ if (v_actual < ICE_MIN_MSIX) {
+ /* error if we can't get minimum vectors */
+ pci_free_irq_vectors(pf->pdev);
+ err = -ERANGE;
+ goto exit_err;
+ } else {
+ int v_remain = v_actual - v_other;
+
+ if (v_remain < ICE_MIN_LAN_TXRX_MSIX)
+ v_remain = ICE_MIN_LAN_TXRX_MSIX;
+
+ ice_reduce_msix_usage(pf, v_remain);
+
+ dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n",
+ pf->num_lan_msix);
+
+ if (ice_is_rdma_ena(pf))
+ dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n",
+ pf->num_rdma_msix);
+ }
+ }
+
+ return v_actual;
+
+exit_err:
+ pf->num_rdma_msix = 0;
+ pf->num_lan_msix = 0;
+ return err;
+}
+
+/**
+ * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
+ * @pf: board private structure
+ */
+void ice_clear_interrupt_scheme(struct ice_pf *pf)
+{
+ pci_free_irq_vectors(pf->pdev);
+ ice_deinit_irq_tracker(pf);
+}
+
+/**
+ * ice_init_interrupt_scheme - Determine proper interrupt scheme
+ * @pf: board private structure to initialize
+ */
+int ice_init_interrupt_scheme(struct ice_pf *pf)
+{
+ int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
+ int vectors, max_vectors;
+
+ vectors = ice_ena_msix_range(pf);
+
+ if (vectors < 0)
+ return -ENOMEM;
+
+ if (pci_msix_can_alloc_dyn(pf->pdev))
+ max_vectors = total_vectors;
+ else
+ max_vectors = vectors;
+
+ ice_init_irq_tracker(pf, max_vectors, vectors);
+
+ return 0;
+}
+
+/**
+ * ice_alloc_irq - Allocate new interrupt vector
+ * @pf: board private structure
+ * @dyn_only: force dynamic allocation of the interrupt
+ *
+ * Allocate new interrupt vector for a given owner id.
+ * return struct msi_map with interrupt details and track
+ * allocated interrupt appropriately.
+ *
+ * This function reserves new irq entry from the irq_tracker.
+ * if according to the tracker information all interrupts that
+ * were allocated with ice_pci_alloc_irq_vectors are already used
+ * and dynamically allocated interrupts are supported then new
+ * interrupt will be allocated with pci_msix_alloc_irq_at.
+ *
+ * Some callers may only support dynamically allocated interrupts.
+ * This is indicated with dyn_only flag.
+ *
+ * On failure, return map with negative .index. The caller
+ * is expected to check returned map index.
+ *
+ */
+struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only)
+{
+ int sriov_base_vector = pf->sriov_base_vector;
+ struct msi_map map = { .index = -ENOENT };
+ struct device *dev = ice_pf_to_dev(pf);
+ struct ice_irq_entry *entry;
+
+ entry = ice_get_irq_res(pf, dyn_only);
+ if (!entry)
+ return map;
+
+ /* fail if we're about to violate SRIOV vectors space */
+ if (sriov_base_vector && entry->index >= sriov_base_vector)
+ goto exit_free_res;
+
+ if (pci_msix_can_alloc_dyn(pf->pdev) && entry->dynamic) {
+ map = pci_msix_alloc_irq_at(pf->pdev, entry->index, NULL);
+ if (map.index < 0)
+ goto exit_free_res;
+ dev_dbg(dev, "allocated new irq at index %d\n", map.index);
+ } else {
+ map.index = entry->index;
+ map.virq = pci_irq_vector(pf->pdev, map.index);
+ }
+
+ return map;
+
+exit_free_res:
+ dev_err(dev, "Could not allocate irq at idx %d\n", entry->index);
+ ice_free_irq_res(pf, entry->index);
+ return map;
+}
+
+/**
+ * ice_free_irq - Free interrupt vector
+ * @pf: board private structure
+ * @map: map with interrupt details
+ *
+ * Remove allocated interrupt from the interrupt tracker. If interrupt was
+ * allocated dynamically, free respective interrupt vector.
+ */
+void ice_free_irq(struct ice_pf *pf, struct msi_map map)
+{
+ struct ice_irq_entry *entry;
+
+ entry = xa_load(&pf->irq_tracker.entries, map.index);
+
+ if (!entry) {
+ dev_err(ice_pf_to_dev(pf), "Failed to get MSIX interrupt entry at index %d",
+ map.index);
+ return;
+ }
+
+ dev_dbg(ice_pf_to_dev(pf), "Free irq at index %d\n", map.index);
+
+ if (entry->dynamic)
+ pci_msix_free_irq(pf->pdev, map);
+
+ ice_free_irq_res(pf, map.index);
+}
+
+/**
+ * ice_get_max_used_msix_vector - Get the max used interrupt vector
+ * @pf: board private structure
+ *
+ * Return index of maximum used interrupt vectors with respect to the
+ * beginning of the MSIX table. Take into account that some interrupts
+ * may have been dynamically allocated after MSIX was initially enabled.
+ */
+int ice_get_max_used_msix_vector(struct ice_pf *pf)
+{
+ unsigned long start, index, max_idx;
+ void *entry;
+
+ /* Treat all preallocated interrupts as used */
+ start = pf->irq_tracker.num_static;
+ max_idx = start - 1;
+
+ xa_for_each_start(&pf->irq_tracker.entries, index, entry, start) {
+ if (index > max_idx)
+ max_idx = index;
+ }
+
+ return max_idx;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_irq.h b/drivers/net/ethernet/intel/ice/ice_irq.h
new file mode 100644
index 000000000000..f35efc08575e
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/ice_irq.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2023, Intel Corporation. */
+
+#ifndef _ICE_IRQ_H_
+#define _ICE_IRQ_H_
+
+struct ice_irq_entry {
+ unsigned int index;
+ bool dynamic; /* allocation type flag */
+};
+
+struct ice_irq_tracker {
+ struct xarray entries;
+ u16 num_entries; /* total vectors available */
+ u16 num_static; /* preallocated entries */
+};
+
+int ice_init_interrupt_scheme(struct ice_pf *pf);
+void ice_clear_interrupt_scheme(struct ice_pf *pf);
+
+struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only);
+void ice_free_irq(struct ice_pf *pf, struct msi_map map);
+int ice_get_max_used_msix_vector(struct ice_pf *pf);
+
+#endif
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index ee5b36941ba3..5a7753bda324 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -7,15 +7,6 @@
#include "ice_lag.h"
/**
- * ice_lag_nop_handler - no-op Rx handler to disable LAG
- * @pskb: pointer to skb pointer
- */
-rx_handler_result_t ice_lag_nop_handler(struct sk_buff __always_unused **pskb)
-{
- return RX_HANDLER_PASS;
-}
-
-/**
* ice_lag_set_primary - set PF LAG state as Primary
* @lag: LAG info struct
*/
@@ -158,7 +149,6 @@ ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info)
lag->upper_netdev = upper;
}
- ice_clear_sriov_cap(pf);
ice_clear_rdma_cap(pf);
lag->bonded = true;
@@ -205,7 +195,6 @@ ice_lag_unlink(struct ice_lag *lag,
}
lag->peer_netdev = NULL;
- ice_set_sriov_cap(pf);
ice_set_rdma_cap(pf);
lag->bonded = false;
lag->role = ICE_LAG_NONE;
@@ -229,7 +218,6 @@ static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev)
if (lag->upper_netdev) {
dev_put(lag->upper_netdev);
lag->upper_netdev = NULL;
- ice_set_sriov_cap(pf);
ice_set_rdma_cap(pf);
}
/* perform some cleanup in case we come back */
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.h b/drivers/net/ethernet/intel/ice/ice_lag.h
index 51b5cf467ce2..2c373676c42f 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.h
+++ b/drivers/net/ethernet/intel/ice/ice_lag.h
@@ -25,63 +25,9 @@ struct ice_lag {
struct notifier_block notif_block;
u8 bonded:1; /* currently bonded */
u8 primary:1; /* this is primary */
- u8 handler:1; /* did we register a rx_netdev_handler */
- /* each thing blocking bonding will increment this value by one.
- * If this value is zero, then bonding is allowed.
- */
- u16 dis_lag;
u8 role;
};
int ice_init_lag(struct ice_pf *pf);
void ice_deinit_lag(struct ice_pf *pf);
-rx_handler_result_t ice_lag_nop_handler(struct sk_buff **pskb);
-
-/**
- * ice_disable_lag - increment LAG disable count
- * @lag: LAG struct
- */
-static inline void ice_disable_lag(struct ice_lag *lag)
-{
- /* If LAG this PF is not already disabled, disable it */
- rtnl_lock();
- if (!netdev_is_rx_handler_busy(lag->netdev)) {
- if (!netdev_rx_handler_register(lag->netdev,
- ice_lag_nop_handler,
- NULL))
- lag->handler = true;
- }
- rtnl_unlock();
- lag->dis_lag++;
-}
-
-/**
- * ice_enable_lag - decrement disable count for a PF
- * @lag: LAG struct
- *
- * Decrement the disable counter for a port, and if that count reaches
- * zero, then remove the no-op Rx handler from that netdev
- */
-static inline void ice_enable_lag(struct ice_lag *lag)
-{
- if (lag->dis_lag)
- lag->dis_lag--;
- if (!lag->dis_lag && lag->handler) {
- rtnl_lock();
- netdev_rx_handler_unregister(lag->netdev);
- rtnl_unlock();
- lag->handler = false;
- }
-}
-
-/**
- * ice_is_lag_dis - is LAG disabled
- * @lag: LAG struct
- *
- * Return true if bonding is disabled
- */
-static inline bool ice_is_lag_dis(struct ice_lag *lag)
-{
- return !!(lag->dis_lag);
-}
#endif /* _ICE_LAG_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index 11ae0e41f518..0054d7e64ec3 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -321,31 +321,19 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
- if (vsi->af_xdp_zc_qps) {
- bitmap_free(vsi->af_xdp_zc_qps);
- vsi->af_xdp_zc_qps = NULL;
- }
+ bitmap_free(vsi->af_xdp_zc_qps);
+ vsi->af_xdp_zc_qps = NULL;
/* free the ring and vector containers */
- if (vsi->q_vectors) {
- devm_kfree(dev, vsi->q_vectors);
- vsi->q_vectors = NULL;
- }
- if (vsi->tx_rings) {
- devm_kfree(dev, vsi->tx_rings);
- vsi->tx_rings = NULL;
- }
- if (vsi->rx_rings) {
- devm_kfree(dev, vsi->rx_rings);
- vsi->rx_rings = NULL;
- }
- if (vsi->txq_map) {
- devm_kfree(dev, vsi->txq_map);
- vsi->txq_map = NULL;
- }
- if (vsi->rxq_map) {
- devm_kfree(dev, vsi->rxq_map);
- vsi->rxq_map = NULL;
- }
+ devm_kfree(dev, vsi->q_vectors);
+ vsi->q_vectors = NULL;
+ devm_kfree(dev, vsi->tx_rings);
+ vsi->tx_rings = NULL;
+ devm_kfree(dev, vsi->rx_rings);
+ vsi->rx_rings = NULL;
+ devm_kfree(dev, vsi->txq_map);
+ vsi->txq_map = NULL;
+ devm_kfree(dev, vsi->rxq_map);
+ vsi->rxq_map = NULL;
}
/**
@@ -902,10 +890,8 @@ static void ice_rss_clean(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
- if (vsi->rss_hkey_user)
- devm_kfree(dev, vsi->rss_hkey_user);
- if (vsi->rss_lut_user)
- devm_kfree(dev, vsi->rss_lut_user);
+ devm_kfree(dev, vsi->rss_hkey_user);
+ devm_kfree(dev, vsi->rss_lut_user);
ice_vsi_clean_rss_flow_fld(vsi);
/* remove RSS replay list */
@@ -1371,190 +1357,6 @@ out:
}
/**
- * ice_free_res - free a block of resources
- * @res: pointer to the resource
- * @index: starting index previously returned by ice_get_res
- * @id: identifier to track owner
- *
- * Returns number of resources freed
- */
-int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
-{
- int count = 0;
- int i;
-
- if (!res || index >= res->end)
- return -EINVAL;
-
- id |= ICE_RES_VALID_BIT;
- for (i = index; i < res->end && res->list[i] == id; i++) {
- res->list[i] = 0;
- count++;
- }
-
- return count;
-}
-
-/**
- * ice_search_res - Search the tracker for a block of resources
- * @res: pointer to the resource
- * @needed: size of the block needed
- * @id: identifier to track owner
- *
- * Returns the base item index of the block, or -ENOMEM for error
- */
-static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
-{
- u16 start = 0, end = 0;
-
- if (needed > res->end)
- return -ENOMEM;
-
- id |= ICE_RES_VALID_BIT;
-
- do {
- /* skip already allocated entries */
- if (res->list[end++] & ICE_RES_VALID_BIT) {
- start = end;
- if ((start + needed) > res->end)
- break;
- }
-
- if (end == (start + needed)) {
- int i = start;
-
- /* there was enough, so assign it to the requestor */
- while (i != end)
- res->list[i++] = id;
-
- return start;
- }
- } while (end < res->end);
-
- return -ENOMEM;
-}
-
-/**
- * ice_get_free_res_count - Get free count from a resource tracker
- * @res: Resource tracker instance
- */
-static u16 ice_get_free_res_count(struct ice_res_tracker *res)
-{
- u16 i, count = 0;
-
- for (i = 0; i < res->end; i++)
- if (!(res->list[i] & ICE_RES_VALID_BIT))
- count++;
-
- return count;
-}
-
-/**
- * ice_get_res - get a block of resources
- * @pf: board private structure
- * @res: pointer to the resource
- * @needed: size of the block needed
- * @id: identifier to track owner
- *
- * Returns the base item index of the block, or negative for error
- */
-int
-ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
-{
- if (!res || !pf)
- return -EINVAL;
-
- if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) {
- dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n",
- needed, res->num_entries, id);
- return -EINVAL;
- }
-
- return ice_search_res(res, needed, id);
-}
-
-/**
- * ice_get_vf_ctrl_res - Get VF control VSI resource
- * @pf: pointer to the PF structure
- * @vsi: the VSI to allocate a resource for
- *
- * Look up whether another VF has already allocated the control VSI resource.
- * If so, re-use this resource so that we share it among all VFs.
- *
- * Otherwise, allocate the resource and return it.
- */
-static int ice_get_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
-{
- struct ice_vf *vf;
- unsigned int bkt;
- int base;
-
- rcu_read_lock();
- ice_for_each_vf_rcu(pf, bkt, vf) {
- if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
- base = pf->vsi[vf->ctrl_vsi_idx]->base_vector;
- rcu_read_unlock();
- return base;
- }
- }
- rcu_read_unlock();
-
- return ice_get_res(pf, pf->irq_tracker, vsi->num_q_vectors,
- ICE_RES_VF_CTRL_VEC_ID);
-}
-
-/**
- * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
- * @vsi: ptr to the VSI
- *
- * This should only be called after ice_vsi_alloc_def() which allocates the
- * corresponding SW VSI structure and initializes num_queue_pairs for the
- * newly allocated VSI.
- *
- * Returns 0 on success or negative on failure
- */
-static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
-{
- struct ice_pf *pf = vsi->back;
- struct device *dev;
- u16 num_q_vectors;
- int base;
-
- dev = ice_pf_to_dev(pf);
- /* SRIOV doesn't grab irq_tracker entries for each VSI */
- if (vsi->type == ICE_VSI_VF)
- return 0;
- if (vsi->type == ICE_VSI_CHNL)
- return 0;
-
- if (vsi->base_vector) {
- dev_dbg(dev, "VSI %d has non-zero base vector %d\n",
- vsi->vsi_num, vsi->base_vector);
- return -EEXIST;
- }
-
- num_q_vectors = vsi->num_q_vectors;
- /* reserve slots from OS requested IRQs */
- if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
- base = ice_get_vf_ctrl_res(pf, vsi);
- } else {
- base = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
- vsi->idx);
- }
-
- if (base < 0) {
- dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
- ice_get_free_res_count(pf->irq_tracker),
- ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors);
- return -ENOENT;
- }
- vsi->base_vector = (u16)base;
- pf->num_avail_sw_msix -= num_q_vectors;
-
- return 0;
-}
-
-/**
* ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
* @vsi: the VSI having rings deallocated
*/
@@ -2410,50 +2212,6 @@ static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
}
/**
- * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors
- * @vsi: VSI to set the q_vectors register index on
- */
-static int
-ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
-{
- u16 i;
-
- if (!vsi || !vsi->q_vectors)
- return -EINVAL;
-
- ice_for_each_q_vector(vsi, i) {
- struct ice_q_vector *q_vector = vsi->q_vectors[i];
-
- if (!q_vector) {
- dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n",
- i, vsi->vsi_num);
- goto clear_reg_idx;
- }
-
- if (vsi->type == ICE_VSI_VF) {
- struct ice_vf *vf = vsi->vf;
-
- q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
- } else {
- q_vector->reg_idx =
- q_vector->v_idx + vsi->base_vector;
- }
- }
-
- return 0;
-
-clear_reg_idx:
- ice_for_each_q_vector(vsi, i) {
- struct ice_q_vector *q_vector = vsi->q_vectors[i];
-
- if (q_vector)
- q_vector->reg_idx = 0;
- }
-
- return -EINVAL;
-}
-
-/**
* ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
* @vsi: the VSI being configured
* @tx: bool to determine Tx or Rx rule
@@ -2611,37 +2369,6 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
vsi->agg_node->num_vsis);
}
-/**
- * ice_free_vf_ctrl_res - Free the VF control VSI resource
- * @pf: pointer to PF structure
- * @vsi: the VSI to free resources for
- *
- * Check if the VF control VSI resource is still in use. If no VF is using it
- * any more, release the VSI resource. Otherwise, leave it to be cleaned up
- * once no other VF uses it.
- */
-static void ice_free_vf_ctrl_res(struct ice_pf *pf, struct ice_vsi *vsi)
-{
- struct ice_vf *vf;
- unsigned int bkt;
-
- rcu_read_lock();
- ice_for_each_vf_rcu(pf, bkt, vf) {
- if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
- rcu_read_unlock();
- return;
- }
- }
- rcu_read_unlock();
-
- /* No other VFs left that have control VSI. It is now safe to reclaim
- * SW interrupts back to the common pool.
- */
- ice_free_res(pf->irq_tracker, vsi->base_vector,
- ICE_RES_VF_CTRL_VEC_ID);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
-}
-
static int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
{
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
@@ -2728,14 +2455,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
if (ret)
goto unroll_vsi_init;
- ret = ice_vsi_setup_vector_base(vsi);
- if (ret)
- goto unroll_alloc_q_vector;
-
- ret = ice_vsi_set_q_vectors_reg_idx(vsi);
- if (ret)
- goto unroll_vector_base;
-
ret = ice_vsi_alloc_rings(vsi);
if (ret)
goto unroll_vector_base;
@@ -2788,10 +2507,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
if (ret)
goto unroll_alloc_q_vector;
- ret = ice_vsi_set_q_vectors_reg_idx(vsi);
- if (ret)
- goto unroll_vector_base;
-
ret = ice_vsi_alloc_ring_stats(vsi);
if (ret)
goto unroll_vector_base;
@@ -2827,8 +2542,6 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
unroll_vector_base:
/* reclaim SW interrupts back to the common pool */
- ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
unroll_alloc_q_vector:
ice_vsi_free_q_vectors(vsi);
unroll_vsi_init:
@@ -2920,14 +2633,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
* many interrupts each VF needs. SR-IOV MSIX resources are also
* cleared in the same manner.
*/
- if (vsi->type == ICE_VSI_CTRL && vsi->vf) {
- ice_free_vf_ctrl_res(pf, vsi);
- } else if (vsi->type != ICE_VSI_VF) {
- /* reclaim SW interrupts back to the common pool */
- ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
- pf->num_avail_sw_msix += vsi->num_q_vectors;
- vsi->base_vector = 0;
- }
if (vsi->type == ICE_VSI_VF &&
vsi->agg_node && vsi->agg_node->valid)
@@ -2993,8 +2698,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params)
return vsi;
err_vsi_cfg:
- if (params->type == ICE_VSI_VF)
- ice_enable_lag(pf->lag);
ice_vsi_free(vsi);
return NULL;
@@ -3044,7 +2747,6 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)
void ice_vsi_free_irq(struct ice_vsi *vsi)
{
struct ice_pf *pf = vsi->back;
- int base = vsi->base_vector;
int i;
if (!vsi->q_vectors || !vsi->irqs_ready)
@@ -3058,10 +2760,9 @@ void ice_vsi_free_irq(struct ice_vsi *vsi)
ice_free_cpu_rx_rmap(vsi);
ice_for_each_q_vector(vsi, i) {
- u16 vector = i + base;
int irq_num;
- irq_num = pf->msix_entries[vector].vector;
+ irq_num = vsi->q_vectors[i]->irq.virq;
/* free only the irqs that were actually requested */
if (!vsi->q_vectors[i] ||
@@ -3193,7 +2894,6 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
*/
void ice_vsi_dis_irq(struct ice_vsi *vsi)
{
- int base = vsi->base_vector;
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
u32 val;
@@ -3240,7 +2940,7 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
return;
ice_for_each_q_vector(vsi, i)
- synchronize_irq(pf->msix_entries[i + base].vector);
+ synchronize_irq(vsi->q_vectors[i]->irq.virq);
}
/**
@@ -3272,39 +2972,12 @@ int ice_vsi_release(struct ice_vsi *vsi)
return -ENODEV;
pf = vsi->back;
- /* do not unregister while driver is in the reset recovery pending
- * state. Since reset/rebuild happens through PF service task workqueue,
- * it's not a good idea to unregister netdev that is associated to the
- * PF that is running the work queue items currently. This is done to
- * avoid check_flush_dependency() warning on this wq
- */
- if (vsi->netdev && !ice_is_reset_in_progress(pf->state) &&
- (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) {
- unregister_netdev(vsi->netdev);
- clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
- }
-
- if (vsi->type == ICE_VSI_PF)
- ice_devlink_destroy_pf_port(pf);
-
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
ice_rss_clean(vsi);
ice_vsi_close(vsi);
ice_vsi_decfg(vsi);
- if (vsi->netdev) {
- if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) {
- unregister_netdev(vsi->netdev);
- clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
- }
- if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) {
- free_netdev(vsi->netdev);
- vsi->netdev = NULL;
- clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
- }
- }
-
/* retain SW VSI data structure since it is needed to unregister and
* free VSI netdev when PF is not in reset recovery pending state,\
* for ex: during rmmod.
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index 75221478f2dc..e985766e6bb5 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -104,11 +104,6 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked);
void ice_vsi_decfg(struct ice_vsi *vsi);
void ice_dis_vsi(struct ice_vsi *vsi, bool locked);
-int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id);
-
-int
-ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id);
-
int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 42c318ceff61..c2cdc79308dc 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -1346,6 +1346,7 @@ int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout,
static void ice_aq_check_events(struct ice_pf *pf, u16 opcode,
struct ice_rq_event_info *event)
{
+ struct ice_rq_event_info *task_ev;
struct ice_aq_task *task;
bool found = false;
@@ -1354,15 +1355,15 @@ static void ice_aq_check_events(struct ice_pf *pf, u16 opcode,
if (task->state || task->opcode != opcode)
continue;
- memcpy(&task->event->desc, &event->desc, sizeof(event->desc));
- task->event->msg_len = event->msg_len;
+ task_ev = task->event;
+ memcpy(&task_ev->desc, &event->desc, sizeof(event->desc));
+ task_ev->msg_len = event->msg_len;
/* Only copy the data buffer if a destination was set */
- if (task->event->msg_buf &&
- task->event->buf_len > event->buf_len) {
- memcpy(task->event->msg_buf, event->msg_buf,
+ if (task_ev->msg_buf && task_ev->buf_len >= event->buf_len) {
+ memcpy(task_ev->msg_buf, event->msg_buf,
event->buf_len);
- task->event->buf_len = event->buf_len;
+ task_ev->buf_len = event->buf_len;
}
task->state = ICE_AQ_TASK_COMPLETE;
@@ -2490,7 +2491,6 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
{
int q_vectors = vsi->num_q_vectors;
struct ice_pf *pf = vsi->back;
- int base = vsi->base_vector;
struct device *dev;
int rx_int_idx = 0;
int tx_int_idx = 0;
@@ -2501,7 +2501,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
for (vector = 0; vector < q_vectors; vector++) {
struct ice_q_vector *q_vector = vsi->q_vectors[vector];
- irq_num = pf->msix_entries[base + vector].vector;
+ irq_num = q_vector->irq.virq;
if (q_vector->tx.tx_ring && q_vector->rx.rx_ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -2555,9 +2555,8 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
return 0;
free_q_irqs:
- while (vector) {
- vector--;
- irq_num = pf->msix_entries[base + vector].vector;
+ while (vector--) {
+ irq_num = vsi->q_vectors[vector]->irq.virq;
if (!IS_ENABLED(CONFIG_RFS_ACCEL))
irq_set_affinity_notifier(irq_num, NULL);
irq_set_affinity_hint(irq_num, NULL);
@@ -2635,11 +2634,11 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)
int i;
old_prog = xchg(&vsi->xdp_prog, prog);
- if (old_prog)
- bpf_prog_put(old_prog);
-
ice_for_each_rxq(vsi, i)
WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
+
+ if (old_prog)
+ bpf_prog_put(old_prog);
}
/**
@@ -2924,6 +2923,12 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
}
}
+ /* hot swap progs and avoid toggling link */
+ if (ice_is_xdp_ena_vsi(vsi) == !!prog) {
+ ice_vsi_assign_bpf_prog(vsi, prog);
+ return 0;
+ }
+
/* need to stop netdev while setting up the program for Rx rings */
if (if_running && !test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
ret = ice_down(vsi);
@@ -2956,13 +2961,6 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
xdp_ring_err = ice_realloc_zc_buf(vsi, false);
if (xdp_ring_err)
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed");
- } else {
- /* safe to call even when prog == vsi->xdp_prog as
- * dev_xdp_install in net/core/dev.c incremented prog's
- * refcount so corresponding bpf_prog_put won't cause
- * underflow
- */
- ice_vsi_assign_bpf_prog(vsi, prog);
}
if (if_running)
@@ -3047,7 +3045,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
wr32(hw, PFINT_OICR_ENA, val);
/* SW_ITR_IDX = 0, but don't change INTENA */
- wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
}
@@ -3060,7 +3058,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
{
struct ice_pf *pf = (struct ice_pf *)data;
struct ice_hw *hw = &pf->hw;
- irqreturn_t ret = IRQ_NONE;
struct device *dev;
u32 oicr, ena_mask;
@@ -3142,19 +3139,24 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
if (oicr & PFINT_OICR_TSYN_TX_M) {
ena_mask &= ~PFINT_OICR_TSYN_TX_M;
if (!hw->reset_ongoing)
- ret = IRQ_WAKE_THREAD;
+ set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);
}
if (oicr & PFINT_OICR_TSYN_EVNT_M) {
u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx));
- /* Save EVENTs from GTSYN register */
- pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M |
- GLTSYN_STAT_EVENT1_M |
- GLTSYN_STAT_EVENT2_M);
ena_mask &= ~PFINT_OICR_TSYN_EVNT_M;
- kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work);
+
+ if (hw->func_caps.ts_func_info.src_tmr_owned) {
+ /* Save EVENTs from GLTSYN register */
+ pf->ptp.ext_ts_irq |= gltsyn_stat &
+ (GLTSYN_STAT_EVENT0_M |
+ GLTSYN_STAT_EVENT1_M |
+ GLTSYN_STAT_EVENT2_M);
+
+ set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread);
+ }
}
#define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M)
@@ -3174,16 +3176,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
if (oicr & (PFINT_OICR_PCI_EXCEPTION_M |
PFINT_OICR_ECC_ERR_M)) {
set_bit(ICE_PFR_REQ, pf->state);
- ice_service_task_schedule(pf);
}
}
- if (!ret)
- ret = IRQ_HANDLED;
- ice_service_task_schedule(pf);
- ice_irq_dynamic_ena(hw, NULL, NULL);
-
- return ret;
+ return IRQ_WAKE_THREAD;
}
/**
@@ -3194,12 +3190,29 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data)
{
struct ice_pf *pf = data;
+ struct ice_hw *hw;
+
+ hw = &pf->hw;
if (ice_is_reset_in_progress(pf->state))
return IRQ_HANDLED;
- while (!ice_ptp_process_ts(pf))
- usleep_range(50, 100);
+ ice_service_task_schedule(pf);
+
+ if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread))
+ ice_ptp_extts_event(pf);
+
+ if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) {
+ /* Process outstanding Tx timestamps. If there is more work,
+ * re-arm the interrupt to trigger again.
+ */
+ if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) {
+ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+ ice_flush(hw);
+ }
+ }
+
+ ice_irq_dynamic_ena(hw, NULL, NULL);
return IRQ_HANDLED;
}
@@ -3234,6 +3247,7 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
*/
static void ice_free_irq_msix_misc(struct ice_pf *pf)
{
+ int misc_irq_num = pf->oicr_irq.virq;
struct ice_hw *hw = &pf->hw;
ice_dis_ctrlq_interrupts(hw);
@@ -3242,14 +3256,10 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
wr32(hw, PFINT_OICR_ENA, 0);
ice_flush(hw);
- if (pf->msix_entries) {
- synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
- devm_free_irq(ice_pf_to_dev(pf),
- pf->msix_entries[pf->oicr_idx].vector, pf);
- }
+ synchronize_irq(misc_irq_num);
+ devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf);
- pf->num_avail_sw_msix += 1;
- ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);
+ ice_free_irq(pf, pf->oicr_irq);
}
/**
@@ -3295,7 +3305,8 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
{
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
- int oicr_idx, err = 0;
+ struct msi_map oicr_irq;
+ int err = 0;
if (!pf->int_name[0])
snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
@@ -3309,30 +3320,26 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
goto skip_req_irq;
/* reserve one vector in irq_tracker for misc interrupts */
- oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
- if (oicr_idx < 0)
- return oicr_idx;
-
- pf->num_avail_sw_msix -= 1;
- pf->oicr_idx = (u16)oicr_idx;
-
- err = devm_request_threaded_irq(dev,
- pf->msix_entries[pf->oicr_idx].vector,
- ice_misc_intr, ice_misc_intr_thread_fn,
- 0, pf->int_name, pf);
+ oicr_irq = ice_alloc_irq(pf, false);
+ if (oicr_irq.index < 0)
+ return oicr_irq.index;
+
+ pf->oicr_irq = oicr_irq;
+ err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr,
+ ice_misc_intr_thread_fn, 0,
+ pf->int_name, pf);
if (err) {
dev_err(dev, "devm_request_threaded_irq for %s failed: %d\n",
pf->int_name, err);
- ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
- pf->num_avail_sw_msix += 1;
+ ice_free_irq(pf, pf->oicr_irq);
return err;
}
skip_req_irq:
ice_ena_misc_vector(pf);
- ice_ena_ctrlq_interrupts(hw, pf->oicr_idx);
- wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),
+ ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index);
+ wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index),
ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);
ice_flush(hw);
@@ -3901,224 +3908,6 @@ static int ice_init_pf(struct ice_pf *pf)
}
/**
- * ice_reduce_msix_usage - Reduce usage of MSI-X vectors
- * @pf: board private structure
- * @v_remain: number of remaining MSI-X vectors to be distributed
- *
- * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled.
- * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of
- * remaining vectors.
- */
-static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain)
-{
- int v_rdma;
-
- if (!ice_is_rdma_ena(pf)) {
- pf->num_lan_msix = v_remain;
- return;
- }
-
- /* RDMA needs at least 1 interrupt in addition to AEQ MSIX */
- v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1;
-
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) {
- dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n");
- clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
-
- pf->num_rdma_msix = 0;
- pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
- } else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) ||
- (v_remain - v_rdma < v_rdma)) {
- /* Support minimum RDMA and give remaining vectors to LAN MSIX */
- pf->num_rdma_msix = ICE_MIN_RDMA_MSIX;
- pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX;
- } else {
- /* Split remaining MSIX with RDMA after accounting for AEQ MSIX
- */
- pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 +
- ICE_RDMA_NUM_AEQ_MSIX;
- pf->num_lan_msix = v_remain - pf->num_rdma_msix;
- }
-}
-
-/**
- * ice_ena_msix_range - Request a range of MSIX vectors from the OS
- * @pf: board private structure
- *
- * Compute the number of MSIX vectors wanted and request from the OS. Adjust
- * device usage if there are not enough vectors. Return the number of vectors
- * reserved or negative on failure.
- */
-static int ice_ena_msix_range(struct ice_pf *pf)
-{
- int num_cpus, hw_num_msix, v_other, v_wanted, v_actual;
- struct device *dev = ice_pf_to_dev(pf);
- int err, i;
-
- hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors;
- num_cpus = num_online_cpus();
-
- /* LAN miscellaneous handler */
- v_other = ICE_MIN_LAN_OICR_MSIX;
-
- /* Flow Director */
- if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
- v_other += ICE_FDIR_MSIX;
-
- /* switchdev */
- v_other += ICE_ESWITCH_MSIX;
-
- v_wanted = v_other;
-
- /* LAN traffic */
- pf->num_lan_msix = num_cpus;
- v_wanted += pf->num_lan_msix;
-
- /* RDMA auxiliary driver */
- if (ice_is_rdma_ena(pf)) {
- pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX;
- v_wanted += pf->num_rdma_msix;
- }
-
- if (v_wanted > hw_num_msix) {
- int v_remain;
-
- dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n",
- v_wanted, hw_num_msix);
-
- if (hw_num_msix < ICE_MIN_MSIX) {
- err = -ERANGE;
- goto exit_err;
- }
-
- v_remain = hw_num_msix - v_other;
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX) {
- v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX;
- v_remain = ICE_MIN_LAN_TXRX_MSIX;
- }
-
- ice_reduce_msix_usage(pf, v_remain);
- v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other;
-
- dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n",
- pf->num_lan_msix);
- if (ice_is_rdma_ena(pf))
- dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n",
- pf->num_rdma_msix);
- }
-
- pf->msix_entries = devm_kcalloc(dev, v_wanted,
- sizeof(*pf->msix_entries), GFP_KERNEL);
- if (!pf->msix_entries) {
- err = -ENOMEM;
- goto exit_err;
- }
-
- for (i = 0; i < v_wanted; i++)
- pf->msix_entries[i].entry = i;
-
- /* actually reserve the vectors */
- v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries,
- ICE_MIN_MSIX, v_wanted);
- if (v_actual < 0) {
- dev_err(dev, "unable to reserve MSI-X vectors\n");
- err = v_actual;
- goto msix_err;
- }
-
- if (v_actual < v_wanted) {
- dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n",
- v_wanted, v_actual);
-
- if (v_actual < ICE_MIN_MSIX) {
- /* error if we can't get minimum vectors */
- pci_disable_msix(pf->pdev);
- err = -ERANGE;
- goto msix_err;
- } else {
- int v_remain = v_actual - v_other;
-
- if (v_remain < ICE_MIN_LAN_TXRX_MSIX)
- v_remain = ICE_MIN_LAN_TXRX_MSIX;
-
- ice_reduce_msix_usage(pf, v_remain);
-
- dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n",
- pf->num_lan_msix);
-
- if (ice_is_rdma_ena(pf))
- dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n",
- pf->num_rdma_msix);
- }
- }
-
- return v_actual;
-
-msix_err:
- devm_kfree(dev, pf->msix_entries);
-
-exit_err:
- pf->num_rdma_msix = 0;
- pf->num_lan_msix = 0;
- return err;
-}
-
-/**
- * ice_dis_msix - Disable MSI-X interrupt setup in OS
- * @pf: board private structure
- */
-static void ice_dis_msix(struct ice_pf *pf)
-{
- pci_disable_msix(pf->pdev);
- devm_kfree(ice_pf_to_dev(pf), pf->msix_entries);
- pf->msix_entries = NULL;
-}
-
-/**
- * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
- * @pf: board private structure
- */
-static void ice_clear_interrupt_scheme(struct ice_pf *pf)
-{
- ice_dis_msix(pf);
-
- if (pf->irq_tracker) {
- devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker);
- pf->irq_tracker = NULL;
- }
-}
-
-/**
- * ice_init_interrupt_scheme - Determine proper interrupt scheme
- * @pf: board private structure to initialize
- */
-static int ice_init_interrupt_scheme(struct ice_pf *pf)
-{
- int vectors;
-
- vectors = ice_ena_msix_range(pf);
-
- if (vectors < 0)
- return vectors;
-
- /* set up vector assignment tracking */
- pf->irq_tracker = devm_kzalloc(ice_pf_to_dev(pf),
- struct_size(pf->irq_tracker, list, vectors),
- GFP_KERNEL);
- if (!pf->irq_tracker) {
- ice_dis_msix(pf);
- return -ENOMEM;
- }
-
- /* populate SW interrupts pool with number of OS granted IRQs. */
- pf->num_avail_sw_msix = (u16)vectors;
- pf->irq_tracker->num_entries = (u16)vectors;
- pf->irq_tracker->end = pf->irq_tracker->num_entries;
-
- return 0;
-}
-
-/**
* ice_is_wol_supported - check if WoL is supported
* @hw: pointer to hardware info
*
@@ -4642,9 +4431,9 @@ static int ice_start_eth(struct ice_vsi *vsi)
if (err)
return err;
- rtnl_lock();
err = ice_vsi_open(vsi);
- rtnl_unlock();
+ if (err)
+ ice_fltr_remove_all(vsi);
return err;
}
@@ -5107,6 +4896,7 @@ int ice_load(struct ice_pf *pf)
params = ice_vsi_to_params(vsi);
params.flags = ICE_VSI_FLAG_INIT;
+ rtnl_lock();
err = ice_vsi_cfg(vsi, &params);
if (err)
goto err_vsi_cfg;
@@ -5114,6 +4904,7 @@ int ice_load(struct ice_pf *pf)
err = ice_start_eth(ice_get_main_vsi(pf));
if (err)
goto err_start_eth;
+ rtnl_unlock();
err = ice_init_rdma(pf);
if (err)
@@ -5128,9 +4919,11 @@ int ice_load(struct ice_pf *pf)
err_init_rdma:
ice_vsi_close(ice_get_main_vsi(pf));
+ rtnl_lock();
err_start_eth:
ice_vsi_decfg(ice_get_main_vsi(pf));
err_vsi_cfg:
+ rtnl_unlock();
ice_deinit_dev(pf);
return err;
}
@@ -5143,8 +4936,10 @@ void ice_unload(struct ice_pf *pf)
{
ice_deinit_features(pf);
ice_deinit_rdma(pf);
+ rtnl_lock();
ice_stop_eth(ice_get_main_vsi(pf));
ice_vsi_decfg(ice_get_main_vsi(pf));
+ rtnl_unlock();
ice_deinit_dev(pf);
}
@@ -5835,11 +5630,6 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
if (!is_valid_ether_addr(mac))
return -EADDRNOTAVAIL;
- if (ether_addr_equal(netdev->dev_addr, mac)) {
- netdev_dbg(netdev, "already using mac %pM\n", mac);
- return 0;
- }
-
if (test_bit(ICE_DOWN, pf->state) ||
ice_is_reset_in_progress(pf->state)) {
netdev_err(netdev, "can't set mac %pM. device not ready\n",
@@ -5956,6 +5746,13 @@ ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
q_handle = vsi->tx_rings[queue_index]->q_handle;
tc = ice_dcb_get_tc(vsi, queue_index);
+ vsi = ice_locate_vsi_using_queue(vsi, queue_index);
+ if (!vsi) {
+ netdev_err(netdev, "Invalid VSI for given queue %d\n",
+ queue_index);
+ return -EINVAL;
+ }
+
/* Set BW back to default, when user set maxrate to 0 */
if (!maxrate)
status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc,
@@ -7629,21 +7426,9 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
}
netdev->mtu = (unsigned int)new_mtu;
-
- /* if VSI is up, bring it down and then back up */
- if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
- err = ice_down(vsi);
- if (err) {
- netdev_err(netdev, "change MTU if_down err %d\n", err);
- return err;
- }
-
- err = ice_up(vsi);
- if (err) {
- netdev_err(netdev, "change MTU if_up err %d\n", err);
- return err;
- }
- }
+ err = ice_down_up(vsi);
+ if (err)
+ return err;
netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);
set_bit(ICE_FLAG_MTU_CHANGED, pf->flags);
@@ -8101,10 +7886,10 @@ static int
ice_validate_mqprio_qopt(struct ice_vsi *vsi,
struct tc_mqprio_qopt_offload *mqprio_qopt)
{
- u64 sum_max_rate = 0, sum_min_rate = 0;
int non_power_of_2_qcount = 0;
struct ice_pf *pf = vsi->back;
int max_rss_q_cnt = 0;
+ u64 sum_min_rate = 0;
struct device *dev;
int i, speed;
u8 num_tc;
@@ -8120,6 +7905,7 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
dev = ice_pf_to_dev(pf);
vsi->ch_rss_size = 0;
num_tc = mqprio_qopt->qopt.num_tc;
+ speed = ice_get_link_speed_kbps(vsi);
for (i = 0; num_tc; i++) {
int qcount = mqprio_qopt->qopt.count[i];
@@ -8160,7 +7946,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
*/
max_rate = mqprio_qopt->max_rate[i];
max_rate = div_u64(max_rate, ICE_BW_KBPS_DIVISOR);
- sum_max_rate += max_rate;
/* min_rate is minimum guaranteed rate and it can't be zero */
min_rate = mqprio_qopt->min_rate[i];
@@ -8173,6 +7958,12 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
return -EINVAL;
}
+ if (max_rate && max_rate > speed) {
+ dev_err(dev, "TC%d: max_rate(%llu Kbps) > link speed of %u Kbps\n",
+ i, max_rate, speed);
+ return -EINVAL;
+ }
+
iter_div_u64_rem(min_rate, ICE_MIN_BW_LIMIT, &rem);
if (rem) {
dev_err(dev, "TC%d: Min Rate not multiple of %u Kbps",
@@ -8210,12 +8001,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
(mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i]))
return -EINVAL;
- speed = ice_get_link_speed_kbps(vsi);
- if (sum_max_rate && sum_max_rate > (u64)speed) {
- dev_err(dev, "Invalid max Tx rate(%llu) Kbps > speed(%u) Kbps specified\n",
- sum_max_rate, speed);
- return -EINVAL;
- }
if (sum_min_rate && sum_min_rate > (u64)speed) {
dev_err(dev, "Invalid min Tx rate(%llu) Kbps > speed (%u) Kbps specified\n",
sum_min_rate, speed);
@@ -9029,6 +8814,7 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_pf *pf = np->vsi->back;
+ bool locked = false;
int err;
switch (type) {
@@ -9038,10 +8824,32 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
ice_setup_tc_block_cb,
np, np, true);
case TC_SETUP_QDISC_MQPRIO:
+ if (ice_is_eswitch_mode_switchdev(pf)) {
+ netdev_err(netdev, "TC MQPRIO offload not supported, switchdev is enabled\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (pf->adev) {
+ mutex_lock(&pf->adev_mutex);
+ device_lock(&pf->adev->dev);
+ locked = true;
+ if (pf->adev->dev.driver) {
+ netdev_err(netdev, "Cannot change qdisc when RDMA is active\n");
+ err = -EBUSY;
+ goto adev_unlock;
+ }
+ }
+
/* setup traffic classifier for receive side */
mutex_lock(&pf->tc_mutex);
err = ice_setup_tc_mqprio_qdisc(netdev, type_data);
mutex_unlock(&pf->tc_mutex);
+
+adev_unlock:
+ if (locked) {
+ device_unlock(&pf->adev->dev);
+ mutex_unlock(&pf->adev_mutex);
+ }
return err;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h
index 02a4e1cf624e..6a9364761165 100644
--- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h
@@ -47,6 +47,7 @@ enum ice_protocol_type {
ICE_L2TPV3,
ICE_VLAN_EX,
ICE_VLAN_IN,
+ ICE_HW_METADATA,
ICE_VXLAN_GPE,
ICE_SCTP_IL,
ICE_PROTOCOL_LAST
@@ -115,17 +116,7 @@ enum ice_prot_id {
#define ICE_L2TPV3_HW 104
#define ICE_UDP_OF_HW 52 /* UDP Tunnels */
-#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */
-#define ICE_MDID_SIZE 2
-
-#define ICE_TUN_FLAG_MDID 21
-#define ICE_TUN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_TUN_FLAG_MDID)
-#define ICE_TUN_FLAG_MASK 0xFF
-
-#define ICE_VLAN_FLAG_MDID 20
-#define ICE_VLAN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_VLAN_FLAG_MDID)
-#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000
#define ICE_TUN_FLAG_FV_IND 2
@@ -230,6 +221,191 @@ struct ice_nvgre_hdr {
__be32 tni_flow;
};
+/* Metadata information
+ *
+ * Not all MDIDs can be used by switch block. It depends on package version.
+ *
+ * MDID 16 (Rx offset)
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | A | B | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = Source port where the transaction came from (3b).
+ *
+ * B = Destination TC of the packet. The TC is relative to a port (5b).
+ *
+ * MDID 17
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | PTYPE | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * PTYPE = Encodes the packet type (10b).
+ *
+ * MDID 18
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Packet length | R |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Packet length = Length of the packet in bytes
+ * (packet always carriers CRC) (14b).
+ * R = Reserved (2b).
+ *
+ * MDID 19
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Source VSI | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Source VSI = Source VSI of packet loopbacked in switch (for egress) (10b).
+ */
+#define ICE_MDID_SOURCE_VSI_MASK GENMASK(9, 0)
+
+/*
+ * MDID 20
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F|R|R|G|H|I|J|K|L|M|N|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = DSI - set for DSI RX pkts.
+ * B = ipsec_decrypted - invalid on NIC.
+ * C = marker - this is a marker packet.
+ * D = from_network - for TX sets to 0
+ * for RX:
+ * * 1 - packet is from external link
+ * * 0 - packet source is from internal
+ * E = source_interface_is_rx - reflect the physical interface from where the
+ * packet was received:
+ * * 1 - Rx
+ * * 0 - Tx
+ * F = from_mng - The bit signals that the packet's origin is the management.
+ * G = ucast - Outer L2 MAC address is unicast.
+ * H = mcast - Outer L2 MAC address is multicast.
+ * I = bcast - Outer L2 MAC address is broadcast.
+ * J = second_outer_mac_present - 2 outer MAC headers are present in the packet.
+ * K = STAG or BVLAN - Outer L2 header has STAG (ethernet type 0x88a8) or
+ * BVLAN (ethernet type 0x88a8).
+ * L = ITAG - Outer L2 header has ITAG *ethernet type 0x88e7)
+ * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100)
+ * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100)
+ */
+#define ICE_PKT_VLAN_STAG BIT(12)
+#define ICE_PKT_VLAN_ITAG BIT(13)
+#define ICE_PKT_VLAN_EVLAN (BIT(14) | BIT(15))
+#define ICE_PKT_VLAN_MASK (ICE_PKT_VLAN_STAG | ICE_PKT_VLAN_ITAG | \
+ ICE_PKT_VLAN_EVLAN)
+/* MDID 21
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F|G|H|I|J|R|R|K|L|M|N|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = VLAN (0x8100) - Outer L2 header has VLAN (ethernet type 0x8100)
+ * B = NSHoE - Outer L2 header has NSH (ethernet type 0x894f)
+ * C = MPLS (0x8847) - There is at least 1 MPLS tag in the outer header
+ * (ethernet type 0x8847)
+ * D = MPLS (0x8848) - There is at least 1 MPLS tag in the outer header
+ * (ethernet type 0x8848)
+ * E = multi MPLS - There is more than a single MPLS tag in the outer header
+ * F = inner MPLS - There is inner MPLS tag in the packet
+ * G = tunneled MAC - Set if the packet includes a tunneled MAC
+ * H = tunneled VLAN - Same as VLAN, but for a tunneled header
+ * I = pkt_is_frag - Packet is fragmented (ipv4 or ipv6)
+ * J = ipv6_ext - The packet has routing or destination ipv6 extension in inner
+ * or outer ipv6 headers
+ * K = RoCE - UDP packet detected as RoCEv2
+ * L = UDP_XSUM_0 - Set to 1 if L4 checksum is 0 in a UDP packet
+ * M = ESP - This is a ESP packet
+ * N = NAT_ESP - This is a ESP packet encapsulated in UDP NAT
+ */
+#define ICE_PKT_TUNNEL_MAC BIT(6)
+#define ICE_PKT_TUNNEL_VLAN BIT(7)
+#define ICE_PKT_TUNNEL_MASK (ICE_PKT_TUNNEL_MAC | ICE_PKT_TUNNEL_VLAN)
+
+/* MDID 22
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D|E|F| G |H|I|J| K |L|M|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = fin - fin flag in tcp header
+ * B = sync - sync flag in tcp header
+ * C = rst - rst flag in tcp header
+ * D = psh - psh flag in tcp header
+ * E = ack - ack flag in tcp header
+ * F = urg - urg flag in tcp header
+ * G = tunnel type (3b) - Flags used to decode tunnel type:
+ * * b000 - not a VXLAN/Geneve/GRE tunnel
+ * * b001 - VXLAN-GPE
+ * * b010 - VXLAN (non-GPE)
+ * * b011 - Geneve
+ * * b100 - GRE (no key, no xsum)
+ * * b101 - GREK (key, no xsum)
+ * * b110 - GREC (no key, xsum)
+ * * b111 - GREKC (key, xsum)
+ * H = UDP_GRE - Packet is UDP (VXLAN or VLAN_GPE or Geneve or MPLSoUDP or GRE)
+ * tunnel
+ * I = OAM - VXLAN/Geneve/tunneled NSH packet with the OAM bit set
+ * J = tunneled NSH - Packet has NSHoGRE or NSHoUDP
+ * K = switch (2b) - Direction on switch
+ * * b00 - normal
+ * * b01 - TX force only LAN
+ * * b10 - TX disable LAN
+ * * b11 - direct to VSI
+ * L = swpe - Represents SWPE bit in TX command
+ * M = sw_cmd - Switch command
+ *
+ * MDID 23
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |A|B|C|D| R |E|F|R|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * A = MAC error - Produced by MAC according to L2 error conditions
+ * B = PPRS no offload - FIFO overflow in PPRS or any problematic condition in
+ * PPRS ANA
+ * C = abort - Set when malicious packet is detected
+ * D = partial analysis - ANA's analysing got cut in the middle
+ * (header > 504B etc.)
+ * E = FLM - Flow director hit indication
+ * F = FDLONG - Flow direector long bucket indication
+ *
+ */
+#define ICE_MDID_SIZE 2
+#define ICE_META_DATA_ID_HW 255
+
+enum ice_hw_metadata_id {
+ ICE_SOURCE_PORT_MDID = 16,
+ ICE_PTYPE_MDID = 17,
+ ICE_PACKET_LENGTH_MDID = 18,
+ ICE_SOURCE_VSI_MDID = 19,
+ ICE_PKT_VLAN_MDID = 20,
+ ICE_PKT_TUNNEL_MDID = 21,
+ ICE_PKT_TCP_MDID = 22,
+ ICE_PKT_ERROR_MDID = 23,
+};
+
+enum ice_hw_metadata_offset {
+ ICE_SOURCE_PORT_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_PORT_MDID,
+ ICE_PTYPE_MDID_OFFSET = ICE_MDID_SIZE * ICE_PTYPE_MDID,
+ ICE_PACKET_LENGTH_MDID_OFFSET = ICE_MDID_SIZE * ICE_PACKET_LENGTH_MDID,
+ ICE_SOURCE_VSI_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_VSI_MDID,
+ ICE_PKT_VLAN_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_VLAN_MDID,
+ ICE_PKT_TUNNEL_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TUNNEL_MDID,
+ ICE_PKT_TCP_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TCP_MDID,
+ ICE_PKT_ERROR_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_ERROR_MDID,
+};
+
+enum ice_pkt_flags {
+ ICE_PKT_FLAGS_VLAN = 0,
+ ICE_PKT_FLAGS_TUNNEL = 1,
+ ICE_PKT_FLAGS_TCP = 2,
+ ICE_PKT_FLAGS_ERROR = 3,
+};
+
+struct ice_hw_metadata {
+ __be16 source_port;
+ __be16 ptype;
+ __be16 packet_length;
+ __be16 source_vsi;
+ __be16 flags[4];
+};
+
union ice_prot_hdr {
struct ice_ether_hdr eth_hdr;
struct ice_ethtype_hdr ethertype;
@@ -243,6 +419,7 @@ union ice_prot_hdr {
struct ice_udp_gtp_hdr gtp_hdr;
struct ice_pppoe_hdr pppoe_hdr;
struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr;
+ struct ice_hw_metadata metadata;
};
/* This is mapping table entry that maps every word within a given protocol
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index ac6f06f9a2ed..81d96a40d5a7 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -617,7 +617,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
}
/**
- * ice_ptp_tx_tstamp - Process Tx timestamps for a port
+ * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port
* @tx: the PTP Tx timestamp tracker
*
* Process timestamps captured by the PHY associated with this port. To do
@@ -633,15 +633,6 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
* 6) extend the 40 bit timestamp value to get a 64 bit timestamp value
* 7) send this 64 bit timestamp to the stack
*
- * Returns true if all timestamps were handled, and false if any slots remain
- * without a timestamp.
- *
- * After looping, if we still have waiting SKBs, return false. This may cause
- * us effectively poll even when not strictly necessary. We do this because
- * it's possible a new timestamp was requested around the same time as the
- * interrupt. In some cases hardware might not interrupt us again when the
- * timestamp is captured.
- *
* Note that we do not hold the tracking lock while reading the Tx timestamp.
* This is because reading the timestamp requires taking a mutex that might
* sleep.
@@ -673,10 +664,9 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx)
* the packet will never be sent by hardware and discard it without reading
* the timestamp register.
*/
-static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
+static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx)
{
struct ice_ptp_port *ptp_port;
- bool more_timestamps;
struct ice_pf *pf;
struct ice_hw *hw;
u64 tstamp_ready;
@@ -685,7 +675,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
u8 idx;
if (!tx->init)
- return true;
+ return;
ptp_port = container_of(tx, struct ice_ptp_port, tx);
pf = ptp_port_to_pf(ptp_port);
@@ -694,7 +684,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
/* Read the Tx ready status first */
err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
if (err)
- return false;
+ return;
/* Drop packets if the link went down */
link_up = ptp_port->link_up;
@@ -782,15 +772,34 @@ skip_ts_read:
skb_tstamp_tx(skb, &shhwtstamps);
dev_kfree_skb_any(skb);
}
+}
- /* Check if we still have work to do. If so, re-queue this task to
- * poll for remaining timestamps.
- */
+/**
+ * ice_ptp_tx_tstamp - Process Tx timestamps for this function.
+ * @tx: Tx tracking structure to initialize
+ *
+ * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete
+ * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise.
+ */
+static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx)
+{
+ bool more_timestamps;
+
+ if (!tx->init)
+ return ICE_TX_TSTAMP_WORK_DONE;
+
+ /* Process the Tx timestamp tracker */
+ ice_ptp_process_tx_tstamp(tx);
+
+ /* Check if there are outstanding Tx timestamps */
spin_lock(&tx->lock);
more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len);
spin_unlock(&tx->lock);
- return !more_timestamps;
+ if (more_timestamps)
+ return ICE_TX_TSTAMP_WORK_PENDING;
+
+ return ICE_TX_TSTAMP_WORK_DONE;
}
/**
@@ -911,7 +920,7 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
spin_unlock(&tx->lock);
/* wait for potentially outstanding interrupt to complete */
- synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
+ synchronize_irq(pf->oicr_irq.virq);
ice_ptp_flush_tx_tracker(pf, tx);
@@ -1458,15 +1467,11 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
}
/**
- * ice_ptp_extts_work - Workqueue task function
- * @work: external timestamp work structure
- *
- * Service for PTP external clock event
+ * ice_ptp_extts_event - Process PTP external clock event
+ * @pf: Board private structure
*/
-static void ice_ptp_extts_work(struct kthread_work *work)
+void ice_ptp_extts_event(struct ice_pf *pf)
{
- struct ice_ptp *ptp = container_of(work, struct ice_ptp, extts_work);
- struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp);
struct ptp_clock_event event;
struct ice_hw *hw = &pf->hw;
u8 chan, tmr_idx;
@@ -2430,9 +2435,10 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
* ice_ptp_process_ts - Process the PTP Tx timestamps
* @pf: Board private structure
*
- * Returns true if timestamps are processed.
+ * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx
+ * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise.
*/
-bool ice_ptp_process_ts(struct ice_pf *pf)
+enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf)
{
return ice_ptp_tx_tstamp(&pf->ptp.port.tx);
}
@@ -2558,7 +2564,6 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf)
ice_ptp_cfg_timestamp(pf, false);
kthread_cancel_delayed_work_sync(&ptp->work);
- kthread_cancel_work_sync(&ptp->extts_work);
if (test_bit(ICE_PFR_REQ, pf->state))
return;
@@ -2656,7 +2661,6 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
/* Initialize work functions */
kthread_init_delayed_work(&ptp->work, ice_ptp_periodic_work);
- kthread_init_work(&ptp->extts_work, ice_ptp_extts_work);
/* Allocate a kworker for handling work required for the ports
* connected to the PTP hardware clock.
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 9cda2f43e0e5..995a57019ba7 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -109,6 +109,16 @@ struct ice_tx_tstamp {
};
/**
+ * enum ice_tx_tstamp_work - Status of Tx timestamp work function
+ * @ICE_TX_TSTAMP_WORK_DONE: Tx timestamp processing is complete
+ * @ICE_TX_TSTAMP_WORK_PENDING: More Tx timestamps are pending
+ */
+enum ice_tx_tstamp_work {
+ ICE_TX_TSTAMP_WORK_DONE = 0,
+ ICE_TX_TSTAMP_WORK_PENDING,
+};
+
+/**
* struct ice_ptp_tx - Tracking structure for all Tx timestamp requests on a port
* @lock: lock to prevent concurrent access to fields of this struct
* @tstamps: array of len to store outstanding requests
@@ -169,7 +179,6 @@ struct ice_ptp_port {
* struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
* @port: data for the PHY port initialization procedure
* @work: delayed work function for periodic tasks
- * @extts_work: work function for handling external Tx timestamps
* @cached_phc_time: a cached copy of the PHC time for timestamp extension
* @cached_phc_jiffies: jiffies when cached_phc_time was last updated
* @ext_ts_chan: the external timestamp channel in use
@@ -190,7 +199,6 @@ struct ice_ptp_port {
struct ice_ptp {
struct ice_ptp_port port;
struct kthread_delayed_work work;
- struct kthread_work extts_work;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
u8 ext_ts_chan;
@@ -256,8 +264,9 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena);
int ice_get_ptp_clock_index(struct ice_pf *pf);
+void ice_ptp_extts_event(struct ice_pf *pf);
s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
-bool ice_ptp_process_ts(struct ice_pf *pf);
+enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf);
void
ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring,
@@ -284,6 +293,7 @@ static inline int ice_get_ptp_clock_index(struct ice_pf *pf)
return -1;
}
+static inline void ice_ptp_extts_event(struct ice_pf *pf) { }
static inline s8
ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
{
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index a38614d21ea8..de1d83300481 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -131,6 +131,8 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
case READ_TIME:
cmd_val |= GLTSYN_CMD_READ_TIME;
break;
+ case ICE_PTP_NOP:
+ break;
}
wr32(hw, GLTSYN_CMD, cmd_val);
@@ -1226,18 +1228,18 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts)
}
/**
- * ice_ptp_one_port_cmd - Prepare a single PHY port for a timer command
+ * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command
* @hw: pointer to HW struct
* @port: Port to which cmd has to be sent
* @cmd: Command to be sent to the port
*
* Prepare the requested port for an upcoming timer sync command.
*
- * Note there is no equivalent of this operation on E810, as that device
- * always handles all external PHYs internally.
+ * Do not use this function directly. If you want to configure exactly one
+ * port, use ice_ptp_one_port_cmd() instead.
*/
static int
-ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
+ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
{
u32 cmd_val, val;
u8 tmr_idx;
@@ -1261,6 +1263,8 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
case ADJ_TIME_AT_TIME:
cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME;
break;
+ case ICE_PTP_NOP:
+ break;
}
/* Tx case */
@@ -1307,6 +1311,39 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
}
/**
+ * ice_ptp_one_port_cmd - Prepare one port for a timer command
+ * @hw: pointer to the HW struct
+ * @configured_port: the port to configure with configured_cmd
+ * @configured_cmd: timer command to prepare on the configured_port
+ *
+ * Prepare the configured_port for the configured_cmd, and prepare all other
+ * ports for ICE_PTP_NOP. This causes the configured_port to execute the
+ * desired command while all other ports perform no operation.
+ */
+static int
+ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port,
+ enum ice_ptp_tmr_cmd configured_cmd)
+{
+ u8 port;
+
+ for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
+ enum ice_ptp_tmr_cmd cmd;
+ int err;
+
+ if (port == configured_port)
+ cmd = configured_cmd;
+ else
+ cmd = ICE_PTP_NOP;
+
+ err = ice_ptp_write_port_cmd_e822(hw, port, cmd);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
* ice_ptp_port_cmd_e822 - Prepare all ports for a timer command
* @hw: pointer to the HW struct
* @cmd: timer command to prepare
@@ -1322,7 +1359,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
int err;
- err = ice_ptp_one_port_cmd(hw, port, cmd);
+ err = ice_ptp_write_port_cmd_e822(hw, port, cmd);
if (err)
return err;
}
@@ -2252,6 +2289,9 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
if (err)
goto err_unlock;
+ /* Do not perform any action on the main timer */
+ ice_ptp_src_cmd(hw, ICE_PTP_NOP);
+
/* Issue the sync to activate the time adjustment */
ice_ptp_exec_tmr_cmd(hw);
@@ -2372,6 +2412,9 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port)
if (err)
return err;
+ /* Do not perform any action on the main timer */
+ ice_ptp_src_cmd(hw, ICE_PTP_NOP);
+
ice_ptp_exec_tmr_cmd(hw);
err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
@@ -2847,6 +2890,8 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
case ADJ_TIME_AT_TIME:
cmd_val = GLTSYN_CMD_ADJ_INIT_TIME;
break;
+ case ICE_PTP_NOP:
+ return 0;
}
/* Read, modify, write */
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index 3b68cb91bd81..096685237ca6 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -9,7 +9,8 @@ enum ice_ptp_tmr_cmd {
INIT_INCVAL,
ADJ_TIME,
ADJ_TIME_AT_TIME,
- READ_TIME
+ READ_TIME,
+ ICE_PTP_NOP,
};
enum ice_ptp_serdes {
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index fd1f8b0ad0ab..e30e12321abd 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -298,14 +298,6 @@ static int ice_repr_add(struct ice_vf *vf)
if (!repr)
return -ENOMEM;
-#ifdef CONFIG_ICE_SWITCHDEV
- repr->mac_rule = kzalloc(sizeof(*repr->mac_rule), GFP_KERNEL);
- if (!repr->mac_rule) {
- err = -ENOMEM;
- goto err_alloc_rule;
- }
-#endif
-
repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv));
if (!repr->netdev) {
err = -ENOMEM;
@@ -351,11 +343,6 @@ err_alloc_q_vector:
free_netdev(repr->netdev);
repr->netdev = NULL;
err_alloc:
-#ifdef CONFIG_ICE_SWITCHDEV
- kfree(repr->mac_rule);
- repr->mac_rule = NULL;
-err_alloc_rule:
-#endif
kfree(repr);
vf->repr = NULL;
return err;
@@ -376,10 +363,6 @@ static void ice_repr_rem(struct ice_vf *vf)
ice_devlink_destroy_vf_port(vf);
free_netdev(vf->repr->netdev);
vf->repr->netdev = NULL;
-#ifdef CONFIG_ICE_SWITCHDEV
- kfree(vf->repr->mac_rule);
- vf->repr->mac_rule = NULL;
-#endif
kfree(vf->repr);
vf->repr = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h
index 378a45bfa256..9c2a6f496b3b 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.h
+++ b/drivers/net/ethernet/intel/ice/ice_repr.h
@@ -13,9 +13,8 @@ struct ice_repr {
struct net_device *netdev;
struct metadata_dst *dst;
#ifdef CONFIG_ICE_SWITCHDEV
- /* info about slow path MAC rule */
- struct ice_rule_query_data *mac_rule;
- u8 rule_added;
+ /* info about slow path rule */
+ struct ice_rule_query_data sp_rule;
#endif
};
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
index b7682de0ae05..b664d60fd037 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.c
+++ b/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -358,10 +358,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
node->sibling;
}
- /* leaf nodes have no children */
- if (node->children)
- devm_kfree(ice_hw_to_dev(hw), node->children);
-
+ devm_kfree(ice_hw_to_dev(hw), node->children);
kfree(node->name);
xa_erase(&pi->sched_node_ids, node->id);
devm_kfree(ice_hw_to_dev(hw), node);
@@ -859,10 +856,8 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
if (!hw)
return;
- if (hw->layer_info) {
- devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
- hw->layer_info = NULL;
- }
+ devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
+ hw->layer_info = NULL;
ice_sched_clear_port(hw->port_info);
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 588ad8696756..31314e7540f8 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -135,18 +135,9 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)
*/
static int ice_sriov_free_msix_res(struct ice_pf *pf)
{
- struct ice_res_tracker *res;
-
if (!pf)
return -EINVAL;
- res = pf->irq_tracker;
- if (!res)
- return -EINVAL;
-
- /* give back irq_tracker resources used */
- WARN_ON(pf->sriov_base_vector < res->num_entries);
-
pf->sriov_base_vector = 0;
return 0;
@@ -410,29 +401,6 @@ int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)
}
/**
- * ice_get_max_valid_res_idx - Get the max valid resource index
- * @res: pointer to the resource to find the max valid index for
- *
- * Start from the end of the ice_res_tracker and return right when we find the
- * first res->list entry with the ICE_RES_VALID_BIT set. This function is only
- * valid for SR-IOV because it is the only consumer that manipulates the
- * res->end and this is always called when res->end is set to res->num_entries.
- */
-static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)
-{
- int i;
-
- if (!res)
- return -EINVAL;
-
- for (i = res->num_entries - 1; i >= 0; i--)
- if (res->list[i] & ICE_RES_VALID_BIT)
- return i;
-
- return 0;
-}
-
-/**
* ice_sriov_set_msix_res - Set any used MSIX resources
* @pf: pointer to PF structure
* @num_msix_needed: number of MSIX vectors needed for all SR-IOV VFs
@@ -450,7 +418,7 @@ static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)
static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)
{
u16 total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
- int vectors_used = pf->irq_tracker->num_entries;
+ int vectors_used = ice_get_max_used_msix_vector(pf);
int sriov_base_vector;
sriov_base_vector = total_vectors - num_msix_needed;
@@ -490,7 +458,7 @@ static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)
*/
static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
{
- int max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);
+ int vectors_used = ice_get_max_used_msix_vector(pf);
u16 num_msix_per_vf, num_txq, num_rxq, avail_qs;
int msix_avail_per_vf, msix_avail_for_sriov;
struct device *dev = ice_pf_to_dev(pf);
@@ -501,12 +469,9 @@ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
if (!num_vfs)
return -EINVAL;
- if (max_valid_res_idx < 0)
- return -ENOSPC;
-
/* determine MSI-X resources per VF */
msix_avail_for_sriov = pf->hw.func_caps.common_cap.num_msix_vectors -
- pf->irq_tracker->num_entries;
+ vectors_used;
msix_avail_per_vf = msix_avail_for_sriov / num_vfs;
if (msix_avail_per_vf >= ICE_NUM_VF_MSIX_MED) {
num_msix_per_vf = ICE_NUM_VF_MSIX_MED;
@@ -871,7 +836,7 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs)
int ret;
/* Disable global interrupt 0 so we don't try to handle the VFLR. */
- wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
+ wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);
set_bit(ICE_OICR_INTR_DIS, pf->state);
ice_flush(hw);
@@ -940,14 +905,13 @@ err_unroll_intr:
*/
static int ice_pci_sriov_ena(struct ice_pf *pf, int num_vfs)
{
- int pre_existing_vfs = pci_num_vf(pf->pdev);
struct device *dev = ice_pf_to_dev(pf);
int err;
- if (pre_existing_vfs && pre_existing_vfs != num_vfs)
+ if (!num_vfs) {
ice_free_vfs(pf);
- else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
return 0;
+ }
if (num_vfs > pf->vfs.num_supported) {
dev_err(dev, "Can't enable %d VFs, max VFs supported is %d\n",
@@ -1014,8 +978,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (!num_vfs) {
if (!pci_vfs_assigned(pdev)) {
ice_free_vfs(pf);
- if (pf->lag)
- ice_enable_lag(pf->lag);
return 0;
}
@@ -1027,8 +989,6 @@ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (err)
return err;
- if (pf->lag)
- ice_disable_lag(pf->lag);
return num_vfs;
}
@@ -1171,7 +1131,7 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
if (!vf)
return -EINVAL;
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1286,7 +1246,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
goto out_put_vf;
}
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1340,7 +1300,7 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
return -EOPNOTSUPP;
}
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
@@ -1653,7 +1613,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
if (!vf)
return -EINVAL;
- ret = ice_check_vf_ready_for_reset(vf);
+ ret = ice_check_vf_ready_for_cfg(vf);
if (ret)
goto out_put_vf;
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index 46b36851af46..6db4ca7978cb 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -1636,21 +1636,16 @@ ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
*/
static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
{
- struct ice_vsi_ctx *vsi;
+ struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle);
u8 i;
- vsi = ice_get_vsi_ctx(hw, vsi_handle);
if (!vsi)
return;
ice_for_each_traffic_class(i) {
- if (vsi->lan_q_ctx[i]) {
- devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
- vsi->lan_q_ctx[i] = NULL;
- }
- if (vsi->rdma_q_ctx[i]) {
- devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
- vsi->rdma_q_ctx[i] = NULL;
- }
+ devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
+ vsi->lan_q_ctx[i] = NULL;
+ devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
+ vsi->rdma_q_ctx[i] = NULL;
}
}
@@ -4540,6 +4535,11 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
return status;
}
+#define ICE_PROTOCOL_ENTRY(id, ...) { \
+ .prot_type = id, \
+ .offs = {__VA_ARGS__}, \
+}
+
/* This is mapping table entry that maps every word within a given protocol
* structure to the real byte offset as per the specification of that
* protocol header.
@@ -4550,29 +4550,38 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
* structure is added to that union.
*/
static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
- { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } },
- { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } },
- { ICE_ETYPE_OL, { 0 } },
- { ICE_ETYPE_IL, { 0 } },
- { ICE_VLAN_OFOS, { 2, 0 } },
- { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
- { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
- { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
- 26, 28, 30, 32, 34, 36, 38 } },
- { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
- 26, 28, 30, 32, 34, 36, 38 } },
- { ICE_TCP_IL, { 0, 2 } },
- { ICE_UDP_OF, { 0, 2 } },
- { ICE_UDP_ILOS, { 0, 2 } },
- { ICE_VXLAN, { 8, 10, 12, 14 } },
- { ICE_GENEVE, { 8, 10, 12, 14 } },
- { ICE_NVGRE, { 0, 2, 4, 6 } },
- { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } },
- { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
- { ICE_PPPOE, { 0, 2, 4, 6 } },
- { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } },
- { ICE_VLAN_EX, { 2, 0 } },
- { ICE_VLAN_IN, { 2, 0 } },
+ ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12),
+ ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12),
+ ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0),
+ ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
+ ICE_PROTOCOL_ENTRY(ICE_IPV4_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18),
+ ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 26, 28, 30, 32, 34, 36, 38),
+ ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38),
+ ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2),
+ ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6),
+ ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22),
+ ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14),
+ ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6),
+ ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0),
+ ICE_PROTOCOL_ENTRY(ICE_HW_METADATA,
+ ICE_SOURCE_PORT_MDID_OFFSET,
+ ICE_PTYPE_MDID_OFFSET,
+ ICE_PACKET_LENGTH_MDID_OFFSET,
+ ICE_SOURCE_VSI_MDID_OFFSET,
+ ICE_PKT_VLAN_MDID_OFFSET,
+ ICE_PKT_TUNNEL_MDID_OFFSET,
+ ICE_PKT_TCP_MDID_OFFSET,
+ ICE_PKT_ERROR_MDID_OFFSET),
};
static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
@@ -4597,6 +4606,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
{ ICE_L2TPV3, ICE_L2TPV3_HW },
{ ICE_VLAN_EX, ICE_VLAN_OF_HW },
{ ICE_VLAN_IN, ICE_VLAN_OL_HW },
+ { ICE_HW_METADATA, ICE_META_DATA_ID_HW },
};
/**
@@ -5255,71 +5265,6 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
return status;
}
-/**
- * ice_tun_type_match_word - determine if tun type needs a match mask
- * @tun_type: tunnel type
- * @mask: mask to be used for the tunnel
- */
-static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
-{
- switch (tun_type) {
- case ICE_SW_TUN_GENEVE:
- case ICE_SW_TUN_VXLAN:
- case ICE_SW_TUN_NVGRE:
- case ICE_SW_TUN_GTPU:
- case ICE_SW_TUN_GTPC:
- *mask = ICE_TUN_FLAG_MASK;
- return true;
-
- default:
- *mask = 0;
- return false;
- }
-}
-
-/**
- * ice_add_special_words - Add words that are not protocols, such as metadata
- * @rinfo: other information regarding the rule e.g. priority and action info
- * @lkup_exts: lookup word structure
- * @dvm_ena: is double VLAN mode enabled
- */
-static int
-ice_add_special_words(struct ice_adv_rule_info *rinfo,
- struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena)
-{
- u16 mask;
-
- /* If this is a tunneled packet, then add recipe index to match the
- * tunnel bit in the packet metadata flags.
- */
- if (ice_tun_type_match_word(rinfo->tun_type, &mask)) {
- if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
- u8 word = lkup_exts->n_val_words++;
-
- lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
- lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
- lkup_exts->field_mask[word] = mask;
- } else {
- return -ENOSPC;
- }
- }
-
- if (rinfo->vlan_type != 0 && dvm_ena) {
- if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
- u8 word = lkup_exts->n_val_words++;
-
- lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
- lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF;
- lkup_exts->field_mask[word] =
- ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK;
- } else {
- return -ENOSPC;
- }
- }
-
- return 0;
-}
-
/* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
* @hw: pointer to hardware structure
* @rinfo: other information regarding the rule e.g. priority and action info
@@ -5433,13 +5378,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (status)
goto err_unroll;
- /* Create any special protocol/offset pairs, such as looking at tunnel
- * bits by extracting metadata
- */
- status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw));
- if (status)
- goto err_unroll;
-
/* Group match words into recipes using preferred recipe grouping
* criteria.
*/
@@ -5525,9 +5463,7 @@ err_unroll:
devm_kfree(ice_hw_to_dev(hw), fvit);
}
- if (rm->root_buf)
- devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
-
+ devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
kfree(rm);
err_free_lkup_exts:
@@ -5725,6 +5661,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
* was already checked when search for the dummy packet
*/
type = lkups[i].type;
+ /* metadata isn't present in the packet */
+ if (type == ICE_HW_METADATA)
+ continue;
+
for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
if (type == offsets[j].type) {
offset = offsets[j].offset;
@@ -5860,16 +5800,21 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
/**
* ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type
+ * @hw: pointer to hw structure
* @vlan_type: VLAN tag type
* @pkt: dummy packet to fill in
* @offsets: offset info for the dummy packet
*/
static int
-ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
+ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt,
const struct ice_dummy_pkt_offsets *offsets)
{
u16 i;
+ /* Check if there is something to do */
+ if (!vlan_type || !ice_is_dvm_ena(hw))
+ return 0;
+
/* Find VLAN header and insert VLAN TPID */
for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
if (offsets[i].type == ICE_VLAN_OFOS ||
@@ -5888,6 +5833,15 @@ ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt,
return -EIO;
}
+static bool ice_rules_equal(const struct ice_adv_rule_info *first,
+ const struct ice_adv_rule_info *second)
+{
+ return first->sw_act.flag == second->sw_act.flag &&
+ first->tun_type == second->tun_type &&
+ first->vlan_type == second->vlan_type &&
+ first->src_vsi == second->src_vsi;
+}
+
/**
* ice_find_adv_rule_entry - Search a rule entry
* @hw: pointer to the hardware structure
@@ -5921,9 +5875,7 @@ ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
lkups_matched = false;
break;
}
- if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
- rinfo->tun_type == list_itr->rule_info.tun_type &&
- rinfo->vlan_type == list_itr->rule_info.vlan_type &&
+ if (ice_rules_equal(rinfo, &list_itr->rule_info) &&
lkups_matched)
return list_itr;
}
@@ -6039,6 +5991,26 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw,
return status;
}
+void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] =
+ cpu_to_be16(ICE_PKT_TUNNEL_MASK);
+}
+
+void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] =
+ cpu_to_be16(ICE_PKT_VLAN_MASK);
+}
+
+void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup)
+{
+ lkup->type = ICE_HW_METADATA;
+ lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK);
+}
+
/**
* ice_add_adv_rule - helper function to create an advanced switch rule
* @hw: pointer to the hardware structure
@@ -6120,7 +6092,10 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
rinfo->sw_act.fwd_id.hw_vsi_id =
ice_get_hw_vsi_num(hw, vsi_handle);
- if (rinfo->sw_act.flag & ICE_FLTR_TX)
+
+ if (rinfo->src_vsi)
+ rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi);
+ else
rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
@@ -6189,19 +6164,20 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
goto err_ice_add_adv_rule;
}
- /* set the rule LOOKUP type based on caller specified 'Rx'
- * instead of hardcoding it to be either LOOKUP_TX/RX
+ /* If there is no matching criteria for direction there
+ * is only one difference between Rx and Tx:
+ * - get switch id base on VSI number from source field (Tx)
+ * - get switch id base on port number (Rx)
*
- * for 'Rx' set the source to be the port number
- * for 'Tx' set the source to be the source HW VSI number (determined
- * by caller)
+ * If matching on direction metadata is chose rule direction is
+ * extracted from type value set here.
*/
- if (rinfo->rx) {
- s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
- s_rule->src = cpu_to_le16(hw->port_info->lport);
- } else {
+ if (rinfo->sw_act.flag & ICE_FLTR_TX) {
s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
s_rule->src = cpu_to_le16(rinfo->sw_act.src);
+ } else {
+ s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
+ s_rule->src = cpu_to_le16(hw->port_info->lport);
}
s_rule->recipe_id = cpu_to_le16(rid);
@@ -6211,22 +6187,16 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
if (status)
goto err_ice_add_adv_rule;
- if (rinfo->tun_type != ICE_NON_TUN &&
- rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) {
- status = ice_fill_adv_packet_tun(hw, rinfo->tun_type,
- s_rule->hdr_data,
- profile->offsets);
- if (status)
- goto err_ice_add_adv_rule;
- }
+ status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data,
+ profile->offsets);
+ if (status)
+ goto err_ice_add_adv_rule;
- if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) {
- status = ice_fill_adv_packet_vlan(rinfo->vlan_type,
- s_rule->hdr_data,
- profile->offsets);
- if (status)
- goto err_ice_add_adv_rule;
- }
+ status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type,
+ s_rule->hdr_data,
+ profile->offsets);
+ if (status)
+ goto err_ice_add_adv_rule;
status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
@@ -6469,13 +6439,6 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
return -EIO;
}
- /* Create any special protocol/offset pairs, such as looking at tunnel
- * bits by extracting metadata
- */
- status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw));
- if (status)
- return status;
-
rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
/* If did not find a recipe that match the existing criteria */
if (rid == ICE_MAX_NUM_RECIPES)
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h
index 68d8e8a6a189..c84b56fe84a5 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.h
+++ b/drivers/net/ethernet/intel/ice/ice_switch.h
@@ -10,7 +10,6 @@
#define ICE_DFLT_VSI_INVAL 0xff
#define ICE_FLTR_RX BIT(0)
#define ICE_FLTR_TX BIT(1)
-#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
#define ICE_VSI_INVAL_ID 0xffff
#define ICE_INVAL_Q_HANDLE 0xFFFF
@@ -187,12 +186,13 @@ struct ice_adv_rule_flags_info {
};
struct ice_adv_rule_info {
+ /* Store metadata values in rule info */
enum ice_sw_tunnel_type tun_type;
- struct ice_sw_act_ctrl sw_act;
- u32 priority;
- u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */
- u16 fltr_rule_id;
u16 vlan_type;
+ u16 fltr_rule_id;
+ u32 priority;
+ u16 src_vsi;
+ struct ice_sw_act_ctrl sw_act;
struct ice_adv_rule_flags_info flags_info;
};
@@ -342,6 +342,9 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
u16 counter_id);
/* Switch/bridge related commands */
+void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup);
+void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup);
+void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup);
int
ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
index d1a31f236d26..4a34ef5f58d3 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -54,6 +54,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO))
lkups_cnt++;
+ /* is VLAN TPID specified */
+ if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID)
+ lkups_cnt++;
+
/* is CVLAN specified? */
if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO))
lkups_cnt++;
@@ -80,6 +84,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
ICE_TC_FLWR_FIELD_SRC_L4_PORT))
lkups_cnt++;
+ /* matching for tunneled packets in metadata */
+ if (fltr->tunnel_type != TNL_LAST)
+ lkups_cnt++;
+
return lkups_cnt;
}
@@ -320,6 +328,10 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
i++;
}
+ /* always fill matching on tunneled packets in metadata */
+ ice_rule_add_tunnel_metadata(&list[i]);
+ i++;
+
return i;
}
@@ -390,10 +402,6 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
/* copy VLAN info */
if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) {
- vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
- rule_info->vlan_type =
- ice_check_supported_vlan_tpid(vlan_tpid);
-
if (flags & ICE_TC_FLWR_FIELD_CVLAN)
list[i].type = ICE_VLAN_EX;
else
@@ -418,6 +426,15 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
i++;
}
+ if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) {
+ vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid);
+ rule_info->vlan_type =
+ ice_check_supported_vlan_tpid(vlan_tpid);
+
+ ice_rule_add_vlan_metadata(&list[i]);
+ i++;
+ }
+
if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) {
list[i].type = ICE_VLAN_IN;
@@ -698,12 +715,10 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
if (fltr->direction == ICE_ESWITCH_FLTR_INGRESS) {
rule_info.sw_act.flag |= ICE_FLTR_RX;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
rule_info.flags_info.act = ICE_SINGLE_ACT_LB_ENABLE;
} else {
rule_info.sw_act.flag |= ICE_FLTR_TX;
rule_info.sw_act.src = vsi->idx;
- rule_info.rx = false;
rule_info.flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE;
}
@@ -735,17 +750,16 @@ exit:
/**
* ice_locate_vsi_using_queue - locate VSI using queue (forward to queue action)
* @vsi: Pointer to VSI
- * @tc_fltr: Pointer to tc_flower_filter
+ * @queue: Queue index
*
- * Locate the VSI using specified queue. When ADQ is not enabled, always
- * return input VSI, otherwise locate corresponding VSI based on per channel
- * offset and qcount
+ * Locate the VSI using specified "queue". When ADQ is not enabled,
+ * always return input VSI, otherwise locate corresponding
+ * VSI based on per channel "offset" and "qcount"
*/
-static struct ice_vsi *
-ice_locate_vsi_using_queue(struct ice_vsi *vsi,
- struct ice_tc_flower_fltr *tc_fltr)
+struct ice_vsi *
+ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue)
{
- int num_tc, tc, queue;
+ int num_tc, tc;
/* if ADQ is not active, passed VSI is the candidate VSI */
if (!ice_is_adq_active(vsi->back))
@@ -755,7 +769,6 @@ ice_locate_vsi_using_queue(struct ice_vsi *vsi,
* upon queue number)
*/
num_tc = vsi->mqprio_qopt.qopt.num_tc;
- queue = tc_fltr->action.fwd.q.queue;
for (tc = 0; tc < num_tc; tc++) {
int qcount = vsi->mqprio_qopt.qopt.count[tc];
@@ -797,6 +810,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
struct ice_pf *pf = vsi->back;
struct device *dev;
u32 tc_class;
+ int q;
dev = ice_pf_to_dev(pf);
@@ -825,7 +839,8 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
/* Determine destination VSI even though the action is
* FWD_TO_QUEUE, because QUEUE is associated with VSI
*/
- dest_vsi = tc_fltr->dest_vsi;
+ q = tc_fltr->action.fwd.q.queue;
+ dest_vsi = ice_locate_vsi_using_queue(vsi, q);
break;
default:
dev_err(dev,
@@ -910,7 +925,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
dev_dbg(dev, "add switch rule for TC:%u vsi_idx:%u, lkups_cnt:%u\n",
tc_fltr->action.fwd.tc.tc_class,
rule_info.sw_act.vsi_handle, lkups_cnt);
@@ -921,7 +935,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
dev_dbg(dev, "add switch rule action to forward to queue:%u (HW queue %u), lkups_cnt:%u\n",
tc_fltr->action.fwd.q.queue,
tc_fltr->action.fwd.q.hw_queue, lkups_cnt);
@@ -929,7 +942,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
case ICE_DROP_PACKET:
rule_info.sw_act.flag |= ICE_FLTR_RX;
rule_info.sw_act.src = hw->pf_id;
- rule_info.rx = true;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
break;
default:
@@ -1460,8 +1472,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
VLAN_PRIO_MASK);
}
- if (match.mask->vlan_tpid)
+ if (match.mask->vlan_tpid) {
headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid;
+ fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_TPID;
+ }
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
@@ -1702,7 +1716,7 @@ ice_tc_forward_to_queue(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr,
/* If ADQ is configured, and the queue belongs to ADQ VSI, then prepare
* ADQ switch filter
*/
- ch_vsi = ice_locate_vsi_using_queue(vsi, fltr);
+ ch_vsi = ice_locate_vsi_using_queue(vsi, fltr->action.fwd.q.queue);
if (!ch_vsi)
return -EINVAL;
fltr->dest_vsi = ch_vsi;
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.h b/drivers/net/ethernet/intel/ice/ice_tc_lib.h
index 8d5e22ac7023..65d387163a46 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.h
@@ -33,6 +33,7 @@
#define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26)
#define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27)
#define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28)
+#define ICE_TC_FLWR_FIELD_VLAN_TPID BIT(29)
#define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF
@@ -203,6 +204,7 @@ static inline int ice_chnl_dmac_fltr_cnt(struct ice_pf *pf)
return pf->num_dmac_chnl_fltrs;
}
+struct ice_vsi *ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue);
int
ice_add_cls_flower(struct net_device *netdev, struct ice_vsi *vsi,
struct flow_cls_offload *cls_flower);
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index bf74a2f3a4f8..ea3310be8354 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -186,25 +186,6 @@ int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
}
/**
- * ice_check_vf_ready_for_reset - check if VF is ready to be reset
- * @vf: VF to check if it's ready to be reset
- *
- * The purpose of this function is to ensure that the VF is not in reset,
- * disabled, and is both initialized and active, thus enabling us to safely
- * initialize another reset.
- */
-int ice_check_vf_ready_for_reset(struct ice_vf *vf)
-{
- int ret;
-
- ret = ice_check_vf_ready_for_cfg(vf);
- if (!ret && !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
- ret = -EAGAIN;
-
- return ret;
-}
-
-/**
* ice_trigger_vf_reset - Reset a VF on HW
* @vf: pointer to the VF structure
* @is_vflr: true if VFLR was issued, false if not
@@ -631,11 +612,17 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
return 0;
}
+ if (flags & ICE_VF_RESET_LOCK)
+ mutex_lock(&vf->cfg_lock);
+ else
+ lockdep_assert_held(&vf->cfg_lock);
+
if (ice_is_vf_disabled(vf)) {
vsi = ice_get_vf_vsi(vf);
if (!vsi) {
dev_dbg(dev, "VF is already removed\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto out_unlock;
}
ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id);
@@ -644,14 +631,9 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
dev_dbg(dev, "VF is already disabled, there is no need for resetting it, telling VM, all is fine %d\n",
vf->vf_id);
- return 0;
+ goto out_unlock;
}
- if (flags & ICE_VF_RESET_LOCK)
- mutex_lock(&vf->cfg_lock);
- else
- lockdep_assert_held(&vf->cfg_lock);
-
/* Set VF disable bit state here, before triggering reset */
set_bit(ICE_VF_STATE_DIS, vf->vf_states);
ice_trigger_vf_reset(vf, flags & ICE_VF_RESET_VFLR, false);
@@ -689,8 +671,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
*/
ice_vf_clear_all_promisc_modes(vf, vsi);
- ice_eswitch_del_vf_mac_rule(vf);
-
ice_vf_fdir_exit(vf);
ice_vf_fdir_init(vf);
/* clean VF control VSI when resetting VF since it should be setup
@@ -716,7 +696,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
}
ice_eswitch_update_repr(vsi);
- ice_eswitch_replay_vf_mac_rule(vf);
/* if the VF has been reset allow it to come up again */
ice_mbx_clear_malvf(&vf->mbx_info);
@@ -1329,3 +1308,35 @@ void ice_vf_set_initialized(struct ice_vf *vf)
set_bit(ICE_VF_STATE_INIT, vf->vf_states);
memset(&vf->vlan_v2_caps, 0, sizeof(vf->vlan_v2_caps));
}
+
+/**
+ * ice_get_vf_ctrl_vsi - Get first VF control VSI pointer
+ * @pf: the PF private structure
+ * @vsi: pointer to the VSI
+ *
+ * Return first found VF control VSI other than the vsi
+ * passed by parameter. This function is used to determine
+ * whether new resources have to be allocated for control VSI
+ * or they can be shared with existing one.
+ *
+ * Return found VF control VSI pointer other itself. Return
+ * NULL Otherwise.
+ *
+ */
+struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
+{
+ struct ice_vsi *ctrl_vsi = NULL;
+ struct ice_vf *vf;
+ unsigned int bkt;
+
+ rcu_read_lock();
+ ice_for_each_vf_rcu(pf, bkt, vf) {
+ if (vf != vsi->vf && vf->ctrl_vsi_idx != ICE_NO_VSI) {
+ ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];
+ break;
+ }
+ }
+
+ rcu_read_unlock();
+ return ctrl_vsi;
+}
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
index a38ef00a3679..48fea6fa0362 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
@@ -215,7 +215,6 @@ u16 ice_get_num_vfs(struct ice_pf *pf);
struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
bool ice_is_vf_disabled(struct ice_vf *vf);
int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
-int ice_check_vf_ready_for_reset(struct ice_vf *vf);
void ice_set_vf_state_dis(struct ice_vf *vf);
bool ice_is_any_vf_in_unicast_promisc(struct ice_pf *pf);
void
@@ -227,6 +226,7 @@ int
ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m);
int ice_reset_vf(struct ice_vf *vf, u32 flags);
void ice_reset_all_vfs(struct ice_pf *pf);
+struct ice_vsi *ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi);
#else /* CONFIG_PCI_IOV */
static inline struct ice_vf *ice_get_vf_by_id(struct ice_pf *pf, u16 vf_id)
{
@@ -291,6 +291,12 @@ static inline int ice_reset_vf(struct ice_vf *vf, u32 flags)
static inline void ice_reset_all_vfs(struct ice_pf *pf)
{
}
+
+static inline struct ice_vsi *
+ice_get_vf_ctrl_vsi(struct ice_pf *pf, struct ice_vsi *vsi)
+{
+ return NULL;
+}
#endif /* !CONFIG_PCI_IOV */
#endif /* _ICE_VF_LIB_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
index f4a524f80b11..dcf628b1fccd 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
@@ -3730,7 +3730,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
for (i = 0; i < al->num_elements; i++) {
u8 *mac_addr = al->list[i].addr;
- int result;
if (!is_unicast_ether_addr(mac_addr) ||
ether_addr_equal(mac_addr, vf->hw_lan_addr))
@@ -3742,13 +3741,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
goto handle_mac_exit;
}
- result = ice_eswitch_add_vf_mac_rule(pf, vf, mac_addr);
- if (result) {
- dev_err(ice_pf_to_dev(pf), "Failed to add MAC %pM for VF %d\n, error %d\n",
- mac_addr, vf->vf_id, result);
- goto handle_mac_exit;
- }
-
ice_vfhw_mac_add(vf, &al->list[i]);
vf->num_mac++;
break;
@@ -3955,7 +3947,6 @@ error_handler:
ice_vc_notify_vf_link_state(vf);
break;
case VIRTCHNL_OP_RESET_VF:
- clear_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
ops->reset_vf(vf);
break;
case VIRTCHNL_OP_ADD_ETH_ADDR:
diff --git a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
index bcda2e004807..1279c1ffe31c 100644
--- a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
+++ b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c
@@ -219,7 +219,7 @@ static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = {
.rid = ICE_SW_LKUP_VLAN,
.fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX,
.ignore_valid = false,
- .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK,
+ .mask = ICE_PKT_VLAN_MASK,
.mask_valid = true,
.lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX,
},
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index d1e489da7363..a7fe2b4ce655 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -90,7 +90,6 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
{
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
- int base = vsi->base_vector;
u16 reg;
u32 val;
@@ -103,11 +102,9 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
wr32(hw, QINT_RQCTL(reg), val);
if (q_vector) {
- u16 v_idx = q_vector->v_idx;
-
wr32(hw, GLINT_DYN_CTL(q_vector->reg_idx), 0);
ice_flush(hw);
- synchronize_irq(pf->msix_entries[v_idx + base].vector);
+ synchronize_irq(q_vector->irq.virq);
}
}
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 015b78144114..a2b759531cb7 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -34,11 +34,11 @@ struct igb_adapter;
/* TX/RX descriptor defines */
#define IGB_DEFAULT_TXD 256
#define IGB_DEFAULT_TX_WORK 128
-#define IGB_MIN_TXD 80
+#define IGB_MIN_TXD 64
#define IGB_MAX_TXD 4096
#define IGB_DEFAULT_RXD 256
-#define IGB_MIN_RXD 80
+#define IGB_MIN_RXD 64
#define IGB_MAX_RXD 4096
#define IGB_DEFAULT_ITR 3 /* dynamic */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index bb3db387d49c..12f106b3a878 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -183,11 +183,13 @@ static int igb_resume(struct device *);
static int igb_runtime_suspend(struct device *dev);
static int igb_runtime_resume(struct device *dev);
static int igb_runtime_idle(struct device *dev);
+#ifdef CONFIG_PM
static const struct dev_pm_ops igb_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume)
SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume,
igb_runtime_idle)
};
+#endif
static void igb_shutdown(struct pci_dev *);
static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
#ifdef CONFIG_IGB_DCA
@@ -3825,8 +3827,11 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)
}
/* only call pci_enable_sriov() if no VFs are allocated already */
- if (!old_vfs)
+ if (!old_vfs) {
err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
+ if (err)
+ goto err_out;
+ }
goto out;
@@ -3931,8 +3936,9 @@ static void igb_probe_vfs(struct igb_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
- /* Virtualization features not supported on i210 family. */
- if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
+ /* Virtualization features not supported on i210 and 82580 family. */
+ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211) ||
+ (hw->mac.type == e1000_82580))
return;
/* Of the below we really only want the effect of getting
@@ -4812,6 +4818,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
struct igb_ring *rx_ring)
{
+#if (PAGE_SIZE < 8192)
+ struct e1000_hw *hw = &adapter->hw;
+#endif
+
/* set build_skb and buffer size flags */
clear_ring_build_skb_enabled(rx_ring);
clear_ring_uses_large_buffer(rx_ring);
@@ -4822,10 +4832,9 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
set_ring_build_skb_enabled(rx_ring);
#if (PAGE_SIZE < 8192)
- if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB)
- return;
-
- set_ring_uses_large_buffer(rx_ring);
+ if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB ||
+ rd32(E1000_RCTL) & E1000_RCTL_SBP)
+ set_ring_uses_large_buffer(rx_ring);
#endif
}
@@ -9585,6 +9594,11 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
+ if (state == pci_channel_io_normal) {
+ dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n");
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ }
+
netif_device_detach(netdev);
if (state == pci_channel_io_perm_failure)
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 405886ee5261..319c544b9f04 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -1385,18 +1385,6 @@ void igb_ptp_init(struct igb_adapter *adapter)
return;
}
- spin_lock_init(&adapter->tmreg_lock);
- INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
-
- if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
- INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
- igb_ptp_overflow_check);
-
- adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
- adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
-
- igb_ptp_reset(adapter);
-
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
&adapter->pdev->dev);
if (IS_ERR(adapter->ptp_clock)) {
@@ -1406,6 +1394,18 @@ void igb_ptp_init(struct igb_adapter *adapter)
dev_info(&adapter->pdev->dev, "added PHC on %s\n",
adapter->netdev->name);
adapter->ptp_flags |= IGB_PTP_ENABLED;
+
+ spin_lock_init(&adapter->tmreg_lock);
+ INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
+
+ if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
+ INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
+ igb_ptp_overflow_check);
+
+ adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+ adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+
+ igb_ptp_reset(adapter);
}
}
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index 57d39ee00b58..7b83678ba83a 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -39,11 +39,11 @@ enum latency_range {
/* Tx/Rx descriptor defines */
#define IGBVF_DEFAULT_TXD 256
#define IGBVF_MAX_TXD 4096
-#define IGBVF_MIN_TXD 80
+#define IGBVF_MIN_TXD 64
#define IGBVF_DEFAULT_RXD 256
#define IGBVF_MAX_RXD 4096
-#define IGBVF_MIN_RXD 80
+#define IGBVF_MIN_RXD 64
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 34aebf00a512..b4077c3f62ed 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -13,6 +13,8 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <linux/net_tstamp.h>
+#include <linux/bitfield.h>
+#include <linux/hrtimer.h>
#include "igc_hw.h"
@@ -100,6 +102,8 @@ struct igc_ring {
u32 start_time;
u32 end_time;
u32 max_sdu;
+ bool oper_gate_closed; /* Operating gate. True if the TX Queue is closed */
+ bool admin_gate_closed; /* Future gate. True if the TX Queue will be closed */
/* CBS parameters */
bool cbs_enable; /* indicates if CBS is enabled */
@@ -159,6 +163,7 @@ struct igc_adapter {
struct timer_list watchdog_timer;
struct timer_list dma_err_timer;
struct timer_list phy_info_timer;
+ struct hrtimer hrtimer;
u32 wol;
u32 en_mng_pt;
@@ -183,10 +188,17 @@ struct igc_adapter {
u32 max_frame_size;
u32 min_frame_size;
+ int tc_setup_type;
ktime_t base_time;
ktime_t cycle_time;
- bool qbv_enable;
+ bool taprio_offload_enable;
u32 qbv_config_change_errors;
+ bool qbv_transition;
+ unsigned int qbv_count;
+ /* Access to oper_gate_closed, admin_gate_closed and qbv_transition
+ * are protected by the qbv_tx_lock.
+ */
+ spinlock_t qbv_tx_lock;
/* OS defined structs */
struct pci_dev *pdev;
@@ -228,7 +240,10 @@ struct igc_adapter {
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
- struct work_struct ptp_tx_work;
+ /* Access to ptp_tx_skb and ptp_tx_start are protected by the
+ * ptp_tx_lock.
+ */
+ spinlock_t ptp_tx_lock;
struct sk_buff *ptp_tx_skb;
struct hwtstamp_config tstamp_config;
unsigned long ptp_tx_start;
@@ -311,6 +326,33 @@ extern char igc_driver_name[];
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
+/* RX-desc Write-Back format RSS Type's */
+enum igc_rss_type_num {
+ IGC_RSS_TYPE_NO_HASH = 0,
+ IGC_RSS_TYPE_HASH_TCP_IPV4 = 1,
+ IGC_RSS_TYPE_HASH_IPV4 = 2,
+ IGC_RSS_TYPE_HASH_TCP_IPV6 = 3,
+ IGC_RSS_TYPE_HASH_IPV6_EX = 4,
+ IGC_RSS_TYPE_HASH_IPV6 = 5,
+ IGC_RSS_TYPE_HASH_TCP_IPV6_EX = 6,
+ IGC_RSS_TYPE_HASH_UDP_IPV4 = 7,
+ IGC_RSS_TYPE_HASH_UDP_IPV6 = 8,
+ IGC_RSS_TYPE_HASH_UDP_IPV6_EX = 9,
+ IGC_RSS_TYPE_MAX = 10,
+};
+#define IGC_RSS_TYPE_MAX_TABLE 16
+#define IGC_RSS_TYPE_MASK GENMASK(3,0) /* 4-bits (3:0) = mask 0x0F */
+
+/* igc_rss_type - Rx descriptor RSS type field */
+static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc)
+{
+ /* RSS Type 4-bits (3:0) number: 0-9 (above 9 is reserved)
+ * Accessing the same bits via u16 (wb.lower.lo_dword.hs_rss.pkt_info)
+ * is slightly slower than via u32 (wb.lower.lo_dword.data)
+ */
+ return le32_get_bits(rx_desc->wb.lower.lo_dword.data, IGC_RSS_TYPE_MASK);
+}
+
/* Interrupt defines */
#define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_4K_ITR 980
@@ -326,11 +368,11 @@ extern char igc_driver_name[];
/* TX/RX descriptor defines */
#define IGC_DEFAULT_TXD 256
#define IGC_DEFAULT_TX_WORK 128
-#define IGC_MIN_TXD 80
+#define IGC_MIN_TXD 64
#define IGC_MAX_TXD 4096
#define IGC_DEFAULT_RXD 256
-#define IGC_MIN_RXD 80
+#define IGC_MIN_RXD 64
#define IGC_MAX_RXD 4096
/* Supported Rx Buffer Sizes */
@@ -401,7 +443,6 @@ enum igc_state_t {
__IGC_TESTING,
__IGC_RESETTING,
__IGC_DOWN,
- __IGC_PTP_TX_IN_PROGRESS,
};
enum igc_tx_flags {
@@ -471,6 +512,13 @@ struct igc_rx_buffer {
};
};
+/* context wrapper around xdp_buff to provide access to descriptor metadata */
+struct igc_xdp_buff {
+ struct xdp_buff xdp;
+ union igc_adv_rx_desc *rx_desc;
+ ktime_t rx_ts; /* data indication bit IGC_RXDADV_STAT_TSIP */
+};
+
struct igc_q_vector {
struct igc_adapter *adapter; /* backlink */
void __iomem *itr_register;
@@ -578,6 +626,7 @@ enum igc_ring_flags_t {
IGC_RING_FLAG_TX_CTX_IDX,
IGC_RING_FLAG_TX_DETECT_HANG,
IGC_RING_FLAG_AF_XDP_ZC,
+ IGC_RING_FLAG_TX_HWTSTAMP,
};
#define ring_uses_large_buffer(ring) \
@@ -634,6 +683,7 @@ int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
void igc_ptp_tx_hang(struct igc_adapter *adapter);
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
+void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter);
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
index 44a507029946..2f780cc90883 100644
--- a/drivers/net/ethernet/intel/igc/igc_defines.h
+++ b/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -546,7 +546,7 @@
#define IGC_PTM_CTRL_START_NOW BIT(29) /* Start PTM Now */
#define IGC_PTM_CTRL_EN BIT(30) /* Enable PTM */
#define IGC_PTM_CTRL_TRIG BIT(31) /* PTM Cycle trigger */
-#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x2f) << 2)
+#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x3f) << 2)
#define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8)
#define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 0e2cb00622d1..93bce729be76 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1708,6 +1708,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
/* twisted pair */
cmd->base.port = PORT_TP;
cmd->base.phy_address = hw->phy.addr;
+ ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+ ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
/* advertising link modes */
if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index fa764190f270..6f557e843e49 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -316,6 +316,33 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter)
igc_clean_tx_ring(adapter->tx_ring[i]);
}
+static void igc_disable_tx_ring_hw(struct igc_ring *ring)
+{
+ struct igc_hw *hw = &ring->q_vector->adapter->hw;
+ u8 idx = ring->reg_idx;
+ u32 txdctl;
+
+ txdctl = rd32(IGC_TXDCTL(idx));
+ txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
+ txdctl |= IGC_TXDCTL_SWFLUSH;
+ wr32(IGC_TXDCTL(idx), txdctl);
+}
+
+/**
+ * igc_disable_all_tx_rings_hw - Disable all transmit queue operation
+ * @adapter: board private structure
+ */
+static void igc_disable_all_tx_rings_hw(struct igc_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ igc_disable_tx_ring_hw(tx_ring);
+ }
+}
+
/**
* igc_setup_tx_resources - allocate Tx resources (Descriptors)
* @tx_ring: tx descriptor ring (for a specific queue) to setup
@@ -711,7 +738,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
/* disable the queue */
wr32(IGC_TXDCTL(reg_idx), 0);
wrfl();
- mdelay(10);
wr32(IGC_TDLEN(reg_idx),
ring->count * sizeof(union igc_adv_tx_desc));
@@ -1017,7 +1043,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
ktime_t base_time = adapter->base_time;
ktime_t now = ktime_get_clocktai();
ktime_t baset_est, end_of_cycle;
- u32 launchtime;
+ s32 launchtime;
s64 n;
n = div64_s64(ktime_sub_ns(now, base_time), cycle_time);
@@ -1030,7 +1056,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
*first_flag = true;
ring->last_ff_cycle = baset_est;
- if (ktime_compare(txtime, ring->last_tx_cycle) > 0)
+ if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0)
*insert_empty = true;
}
}
@@ -1573,26 +1599,24 @@ done:
first->bytecount = skb->len;
first->gso_segs = 1;
- if (tx_ring->max_sdu > 0) {
- u32 max_sdu = 0;
-
- max_sdu = tx_ring->max_sdu +
- (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0);
+ if (adapter->qbv_transition || tx_ring->oper_gate_closed)
+ goto out_drop;
- if (first->bytecount > max_sdu) {
- adapter->stats.txdrop++;
- goto out_drop;
- }
+ if (tx_ring->max_sdu > 0 && first->bytecount > tx_ring->max_sdu) {
+ adapter->stats.txdrop++;
+ goto out_drop;
}
- if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
/* FIXME: add support for retrieving timestamps from
* the other timer registers before skipping the
* timestamping request.
*/
- if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
- !test_and_set_bit_lock(__IGC_PTP_TX_IN_PROGRESS,
- &adapter->state)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
+ if (!adapter->ptp_tx_skb) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= IGC_TX_FLAGS_TSTAMP;
@@ -1601,6 +1625,8 @@ done:
} else {
adapter->tx_hwtstamp_skipped++;
}
+
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
if (skb_vlan_tag_present(skb)) {
@@ -1697,14 +1723,36 @@ static void igc_rx_checksum(struct igc_ring *ring,
le32_to_cpu(rx_desc->wb.upper.status_error));
}
+/* Mapping HW RSS Type to enum pkt_hash_types */
+static const enum pkt_hash_types igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = {
+ [IGC_RSS_TYPE_NO_HASH] = PKT_HASH_TYPE_L2,
+ [IGC_RSS_TYPE_HASH_TCP_IPV4] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_IPV4] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_IPV6_EX] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_IPV6] = PKT_HASH_TYPE_L3,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV4] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6] = PKT_HASH_TYPE_L4,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = PKT_HASH_TYPE_L4,
+ [10] = PKT_HASH_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */
+ [11] = PKT_HASH_TYPE_NONE, /* keep array sized for SW bit-mask */
+ [12] = PKT_HASH_TYPE_NONE, /* to handle future HW revisons */
+ [13] = PKT_HASH_TYPE_NONE,
+ [14] = PKT_HASH_TYPE_NONE,
+ [15] = PKT_HASH_TYPE_NONE,
+};
+
static inline void igc_rx_hash(struct igc_ring *ring,
union igc_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- if (ring->netdev->features & NETIF_F_RXHASH)
- skb_set_hash(skb,
- le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
- PKT_HASH_TYPE_L3);
+ if (ring->netdev->features & NETIF_F_RXHASH) {
+ u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+ u32 rss_type = igc_rss_type(rx_desc);
+
+ skb_set_hash(skb, rss_hash, igc_rss_type_table[rss_type]);
+ }
}
static void igc_rx_vlan(struct igc_ring *rx_ring,
@@ -2221,6 +2269,8 @@ static bool igc_alloc_rx_buffers_zc(struct igc_ring *ring, u16 count)
if (!count)
return ok;
+ XSK_CHECK_PRIV_TYPE(struct igc_xdp_buff);
+
desc = IGC_RX_DESC(ring, i);
bi = &ring->rx_buffer_info[i];
i -= ring->count;
@@ -2394,6 +2444,8 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp)
nq = txring_txq(ring);
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
res = igc_xdp_init_tx_descriptor(ring, xdpf);
__netif_tx_unlock(nq);
return res;
@@ -2505,8 +2557,8 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
union igc_adv_rx_desc *rx_desc;
struct igc_rx_buffer *rx_buffer;
unsigned int size, truesize;
+ struct igc_xdp_buff ctx;
ktime_t timestamp = 0;
- struct xdp_buff xdp;
int pkt_offset = 0;
void *pktbuf;
@@ -2535,18 +2587,20 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
pktbuf);
+ ctx.rx_ts = timestamp;
pkt_offset = IGC_TS_HDR_LEN;
size -= IGC_TS_HDR_LEN;
}
if (!skb) {
- xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq);
- xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring),
+ xdp_init_buff(&ctx.xdp, truesize, &rx_ring->xdp_rxq);
+ xdp_prepare_buff(&ctx.xdp, pktbuf - igc_rx_offset(rx_ring),
igc_rx_offset(rx_ring) + pkt_offset,
size, true);
- xdp_buff_clear_frags_flag(&xdp);
+ xdp_buff_clear_frags_flag(&ctx.xdp);
+ ctx.rx_desc = rx_desc;
- skb = igc_xdp_run_prog(adapter, &xdp);
+ skb = igc_xdp_run_prog(adapter, &ctx.xdp);
}
if (IS_ERR(skb)) {
@@ -2568,9 +2622,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
} else if (skb)
igc_add_rx_frag(rx_ring, rx_buffer, skb, size);
else if (ring_uses_build_skb(rx_ring))
- skb = igc_build_skb(rx_ring, rx_buffer, &xdp);
+ skb = igc_build_skb(rx_ring, rx_buffer, &ctx.xdp);
else
- skb = igc_construct_skb(rx_ring, rx_buffer, &xdp,
+ skb = igc_construct_skb(rx_ring, rx_buffer, &ctx.xdp,
timestamp);
/* exit if we failed to retrieve a buffer */
@@ -2671,6 +2725,15 @@ static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector,
napi_gro_receive(&q_vector->napi, skb);
}
+static struct igc_xdp_buff *xsk_buff_to_igc_ctx(struct xdp_buff *xdp)
+{
+ /* xdp_buff pointer used by ZC code path is alloc as xdp_buff_xsk. The
+ * igc_xdp_buff shares its layout with xdp_buff_xsk and private
+ * igc_xdp_buff fields fall into xdp_buff_xsk->cb
+ */
+ return (struct igc_xdp_buff *)xdp;
+}
+
static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
{
struct igc_adapter *adapter = q_vector->adapter;
@@ -2689,6 +2752,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
while (likely(total_packets < budget)) {
union igc_adv_rx_desc *desc;
struct igc_rx_buffer *bi;
+ struct igc_xdp_buff *ctx;
ktime_t timestamp = 0;
unsigned int size;
int res;
@@ -2706,9 +2770,13 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget)
bi = &ring->rx_buffer_info[ntc];
+ ctx = xsk_buff_to_igc_ctx(bi->xdp);
+ ctx->rx_desc = desc;
+
if (igc_test_staterr(desc, IGC_RXDADV_STAT_TSIP)) {
timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
bi->xdp->data);
+ ctx->rx_ts = timestamp;
bi->xdp->data += IGC_TS_HDR_LEN;
@@ -2787,15 +2855,18 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
struct netdev_queue *nq = txring_txq(ring);
union igc_adv_tx_desc *tx_desc = NULL;
int cpu = smp_processor_id();
- u16 ntu = ring->next_to_use;
struct xdp_desc xdp_desc;
- u16 budget;
+ u16 budget, ntu;
if (!netif_carrier_ok(ring->netdev))
return;
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
+
+ ntu = ring->next_to_use;
budget = igc_desc_unused(ring);
while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
@@ -2963,8 +3034,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
time_after(jiffies, tx_buffer->time_stamp +
(adapter->tx_timeout_factor * HZ)) &&
!(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) &&
- (rd32(IGC_TDH(tx_ring->reg_idx)) !=
- readl(tx_ring->tail))) {
+ (rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) &&
+ !tx_ring->oper_gate_closed) {
/* detected Tx unit hang */
netdev_err(tx_ring->netdev,
"Detected Tx Unit Hang\n"
@@ -4730,6 +4801,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
adapter->nfc_rule_count = 0;
spin_lock_init(&adapter->stats64_lock);
+ spin_lock_init(&adapter->qbv_tx_lock);
/* Assume MSI-X interrupts, will be checked during IRQ allocation */
adapter->flags |= IGC_FLAG_HAS_MSIX;
@@ -5014,6 +5086,7 @@ void igc_down(struct igc_adapter *adapter)
/* clear VLAN promisc flag so VFTA will be updated if necessary */
adapter->flags &= ~IGC_FLAG_VLAN_PROMISC;
+ igc_disable_all_tx_rings_hw(adapter);
igc_clean_all_tx_rings(adapter);
igc_clean_all_rx_rings(adapter);
}
@@ -5219,7 +5292,7 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
if (tsicr & IGC_TSICR_TXTS) {
/* retrieve hardware timestamp */
- schedule_work(&adapter->ptp_tx_work);
+ igc_ptp_tx_tstamp_event(adapter);
ack |= IGC_TSICR_TXTS;
}
@@ -6047,13 +6120,16 @@ static int igc_tsn_enable_launchtime(struct igc_adapter *adapter,
return igc_tsn_offload_apply(adapter);
}
-static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+static int igc_qbv_clear_schedule(struct igc_adapter *adapter)
{
+ unsigned long flags;
int i;
adapter->base_time = 0;
adapter->cycle_time = NSEC_PER_SEC;
+ adapter->taprio_offload_enable = false;
adapter->qbv_config_change_errors = 0;
+ adapter->qbv_count = 0;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
@@ -6063,6 +6139,26 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
ring->max_sdu = 0;
}
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
+ adapter->qbv_transition = false;
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ ring->oper_gate_closed = false;
+ ring->admin_gate_closed = false;
+ }
+
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
+ return 0;
+}
+
+static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+{
+ igc_qbv_clear_schedule(adapter);
+
return 0;
}
@@ -6072,18 +6168,21 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
bool queue_configured[IGC_MAX_TX_QUEUES] = { };
struct igc_hw *hw = &adapter->hw;
u32 start_time = 0, end_time = 0;
+ struct timespec64 now;
+ unsigned long flags;
size_t n;
int i;
- adapter->qbv_enable = qopt->enable;
-
- if (!qopt->enable)
+ if (qopt->cmd == TAPRIO_CMD_DESTROY)
return igc_tsn_clear_schedule(adapter);
+ if (qopt->cmd != TAPRIO_CMD_REPLACE)
+ return -EOPNOTSUPP;
+
if (qopt->base_time < 0)
return -ERANGE;
- if (igc_is_device_id_i225(hw) && adapter->base_time)
+ if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable)
return -EALREADY;
if (!validate_schedule(adapter, qopt))
@@ -6091,6 +6190,9 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
adapter->cycle_time = qopt->cycle_time;
adapter->base_time = qopt->base_time;
+ adapter->taprio_offload_enable = true;
+
+ igc_ptp_read(adapter, &now);
for (n = 0; n < qopt->num_entries; n++) {
struct tc_taprio_sched_entry *e = &qopt->entries[n];
@@ -6126,30 +6228,49 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
ring->start_time = start_time;
ring->end_time = end_time;
- queue_configured[i] = true;
+ if (ring->start_time >= adapter->cycle_time)
+ queue_configured[i] = false;
+ else
+ queue_configured[i] = true;
}
start_time += e->interval;
}
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
/* Check whether a queue gets configured.
* If not, set the start and end time to be end time.
*/
for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ if (!is_base_time_past(qopt->base_time, &now)) {
+ ring->admin_gate_closed = false;
+ } else {
+ ring->oper_gate_closed = false;
+ ring->admin_gate_closed = false;
+ }
+
if (!queue_configured[i]) {
- struct igc_ring *ring = adapter->tx_ring[i];
+ if (!is_base_time_past(qopt->base_time, &now))
+ ring->admin_gate_closed = true;
+ else
+ ring->oper_gate_closed = true;
ring->start_time = end_time;
ring->end_time = end_time;
}
}
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
struct net_device *dev = adapter->netdev;
if (qopt->max_sdu[i])
- ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len;
+ ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len - ETH_TLEN;
else
ring->max_sdu = 0;
}
@@ -6269,6 +6390,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
{
struct igc_adapter *adapter = netdev_priv(dev);
+ adapter->tc_setup_type = type;
+
switch (type) {
case TC_QUERY_CAPS:
return igc_tc_query_caps(adapter, type_data);
@@ -6321,6 +6444,9 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames,
__netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
+
drops = 0;
for (i = 0; i < num_frames; i++) {
int err;
@@ -6461,6 +6587,85 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
return value;
}
+/* Mapping HW RSS Type to enum xdp_rss_hash_type */
+static enum xdp_rss_hash_type igc_xdp_rss_type[IGC_RSS_TYPE_MAX_TABLE] = {
+ [IGC_RSS_TYPE_NO_HASH] = XDP_RSS_TYPE_L2,
+ [IGC_RSS_TYPE_HASH_TCP_IPV4] = XDP_RSS_TYPE_L4_IPV4_TCP,
+ [IGC_RSS_TYPE_HASH_IPV4] = XDP_RSS_TYPE_L3_IPV4,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6] = XDP_RSS_TYPE_L4_IPV6_TCP,
+ [IGC_RSS_TYPE_HASH_IPV6_EX] = XDP_RSS_TYPE_L3_IPV6_EX,
+ [IGC_RSS_TYPE_HASH_IPV6] = XDP_RSS_TYPE_L3_IPV6,
+ [IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_TCP_EX,
+ [IGC_RSS_TYPE_HASH_UDP_IPV4] = XDP_RSS_TYPE_L4_IPV4_UDP,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6] = XDP_RSS_TYPE_L4_IPV6_UDP,
+ [IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = XDP_RSS_TYPE_L4_IPV6_UDP_EX,
+ [10] = XDP_RSS_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */
+ [11] = XDP_RSS_TYPE_NONE, /* keep array sized for SW bit-mask */
+ [12] = XDP_RSS_TYPE_NONE, /* to handle future HW revisons */
+ [13] = XDP_RSS_TYPE_NONE,
+ [14] = XDP_RSS_TYPE_NONE,
+ [15] = XDP_RSS_TYPE_NONE,
+};
+
+static int igc_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
+ enum xdp_rss_hash_type *rss_type)
+{
+ const struct igc_xdp_buff *ctx = (void *)_ctx;
+
+ if (!(ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))
+ return -ENODATA;
+
+ *hash = le32_to_cpu(ctx->rx_desc->wb.lower.hi_dword.rss);
+ *rss_type = igc_xdp_rss_type[igc_rss_type(ctx->rx_desc)];
+
+ return 0;
+}
+
+static int igc_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp)
+{
+ const struct igc_xdp_buff *ctx = (void *)_ctx;
+
+ if (igc_test_staterr(ctx->rx_desc, IGC_RXDADV_STAT_TSIP)) {
+ *timestamp = ctx->rx_ts;
+
+ return 0;
+ }
+
+ return -ENODATA;
+}
+
+static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
+ .xmo_rx_hash = igc_xdp_rx_hash,
+ .xmo_rx_timestamp = igc_xdp_rx_timestamp,
+};
+
+static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
+{
+ struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
+ hrtimer);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
+
+ adapter->qbv_transition = true;
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ if (tx_ring->admin_gate_closed) {
+ tx_ring->admin_gate_closed = false;
+ tx_ring->oper_gate_closed = true;
+ } else {
+ tx_ring->oper_gate_closed = false;
+ }
+ }
+ adapter->qbv_transition = false;
+
+ spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
/**
* igc_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -6534,6 +6739,7 @@ static int igc_probe(struct pci_dev *pdev,
hw->hw_addr = adapter->io_addr;
netdev->netdev_ops = &igc_netdev_ops;
+ netdev->xdp_metadata_ops = &igc_xdp_metadata_ops;
igc_ethtool_set_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
@@ -6561,6 +6767,7 @@ static int igc_probe(struct pci_dev *pdev,
netdev->features |= NETIF_F_TSO;
netdev->features |= NETIF_F_TSO6;
netdev->features |= NETIF_F_TSO_ECN;
+ netdev->features |= NETIF_F_RXHASH;
netdev->features |= NETIF_F_RXCSUM;
netdev->features |= NETIF_F_HW_CSUM;
netdev->features |= NETIF_F_SCTP_CRC;
@@ -6637,6 +6844,9 @@ static int igc_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, igc_reset_task);
INIT_WORK(&adapter->watchdog_task, igc_watchdog_task);
+ hrtimer_init(&adapter->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ adapter->hrtimer.function = &igc_qbv_scheduling_timer;
+
/* Initialize link properties that are user-changeable */
adapter->fc_autoneg = true;
hw->mac.autoneg = true;
@@ -6740,6 +6950,7 @@ static void igc_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->reset_task);
cancel_work_sync(&adapter->watchdog_task);
+ hrtimer_cancel(&adapter->hrtimer);
/* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
@@ -7137,18 +7348,6 @@ void igc_enable_rx_ring(struct igc_ring *ring)
igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
}
-static void igc_disable_tx_ring_hw(struct igc_ring *ring)
-{
- struct igc_hw *hw = &ring->q_vector->adapter->hw;
- u8 idx = ring->reg_idx;
- u32 txdctl;
-
- txdctl = rd32(IGC_TXDCTL(idx));
- txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
- txdctl |= IGC_TXDCTL_SWFLUSH;
- wr32(IGC_TXDCTL(idx), txdctl);
-}
-
void igc_disable_tx_ring(struct igc_ring *ring)
{
igc_disable_tx_ring_hw(ring);
diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 4e10ced736db..f0b979a70655 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
tsim &= ~IGC_TSICR_TT0;
}
if (on) {
+ struct timespec64 safe_start;
int i = rq->perout.index;
igc_pin_perout(igc, i, pin, use_freq);
- igc->perout[i].start.tv_sec = rq->perout.start.sec;
+ igc_ptp_read(igc, &safe_start);
+
+ /* PPS output start time is triggered by Target time(TT)
+ * register. Programming any past time value into TT
+ * register will cause PPS to never start. Need to make
+ * sure we program the TT register a time ahead in
+ * future. There isn't a stringent need to fire PPS out
+ * right away. Adding +2 seconds should take care of
+ * corner cases. Let's say if the SYSTIML is close to
+ * wrap up and the timer keeps ticking as we program the
+ * register, adding +2seconds is safe bet.
+ */
+ safe_start.tv_sec += 2;
+
+ if (rq->perout.start.sec < safe_start.tv_sec)
+ igc->perout[i].start.tv_sec = safe_start.tv_sec;
+ else
+ igc->perout[i].start.tv_sec = rq->perout.start.sec;
igc->perout[i].start.tv_nsec = rq->perout.start.nsec;
igc->perout[i].period.tv_sec = ts.tv_sec;
igc->perout[i].period.tv_nsec = ts.tv_nsec;
- wr32(trgttimh, rq->perout.start.sec);
+ wr32(trgttimh, (u32)igc->perout[i].start.tv_sec);
/* For now, always select timer 0 as source. */
- wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0);
+ wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec |
+ IGC_TT_IO_TIMER_SEL_SYSTIM0));
if (use_freq)
wr32(freqout, ns);
tsauxc |= tsauxc_mask;
@@ -536,9 +555,34 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
wr32(IGC_TSYNCRXCTL, val);
}
+static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
+
+ dev_kfree_skb_any(adapter->ptp_tx_skb);
+ adapter->ptp_tx_skb = NULL;
+
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
+}
+
static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
+ int i;
+
+ /* Clear the flags first to avoid new packets to be enqueued
+ * for TX timestamping.
+ */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ clear_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
+ }
+
+ /* Now we can clean the pending TX timestamp requests. */
+ igc_ptp_clear_tx_tstamp(adapter);
wr32(IGC_TSYNCTXCTL, 0);
}
@@ -546,12 +590,23 @@ static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
+ int i;
wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG);
/* Read TXSTMP registers to discard any timestamp previously stored. */
rd32(IGC_TXSTMPL);
rd32(IGC_TXSTMPH);
+
+ /* The hardware is ready to accept TX timestamp requests,
+ * notify the transmit path.
+ */
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+ set_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
+ }
+
}
/**
@@ -603,6 +658,7 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
return 0;
}
+/* Requires adapter->ptp_tx_lock held by caller. */
static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
@@ -610,7 +666,6 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
dev_kfree_skb_any(adapter->ptp_tx_skb);
adapter->ptp_tx_skb = NULL;
adapter->tx_hwtstamp_timeouts++;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
/* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
rd32(IGC_TXSTMPH);
netdev_warn(adapter->netdev, "Tx timestamp timeout\n");
@@ -618,20 +673,20 @@ static void igc_ptp_tx_timeout(struct igc_adapter *adapter)
void igc_ptp_tx_hang(struct igc_adapter *adapter)
{
- bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
- IGC_PTP_TX_TIMEOUT);
+ unsigned long flags;
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
- return;
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
- /* If we haven't received a timestamp within the timeout, it is
- * reasonable to assume that it will never occur, so we can unlock the
- * timestamp bit when this occurs.
- */
- if (timeout) {
- cancel_work_sync(&adapter->ptp_tx_work);
- igc_ptp_tx_timeout(adapter);
- }
+ if (!adapter->ptp_tx_skb)
+ goto unlock;
+
+ if (time_is_after_jiffies(adapter->ptp_tx_start + IGC_PTP_TX_TIMEOUT))
+ goto unlock;
+
+ igc_ptp_tx_timeout(adapter);
+
+unlock:
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
/**
@@ -641,20 +696,57 @@ void igc_ptp_tx_hang(struct igc_adapter *adapter)
* If we were asked to do hardware stamping and such a time stamp is
* available, then it must have been for this skb here because we only
* allow only one such packet into the queue.
+ *
+ * Context: Expects adapter->ptp_tx_lock to be held by caller.
*/
static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
{
struct sk_buff *skb = adapter->ptp_tx_skb;
struct skb_shared_hwtstamps shhwtstamps;
struct igc_hw *hw = &adapter->hw;
+ u32 tsynctxctl;
int adjust = 0;
u64 regval;
if (WARN_ON_ONCE(!skb))
return;
- regval = rd32(IGC_TXSTMPL);
- regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ tsynctxctl = rd32(IGC_TSYNCTXCTL);
+ tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0;
+ if (tsynctxctl) {
+ regval = rd32(IGC_TXSTMPL);
+ regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ } else {
+ /* There's a bug in the hardware that could cause
+ * missing interrupts for TX timestamping. The issue
+ * is that for new interrupts to be triggered, the
+ * IGC_TXSTMPH_0 register must be read.
+ *
+ * To avoid discarding a valid timestamp that just
+ * happened at the "wrong" time, we need to confirm
+ * that there was no timestamp captured, we do that by
+ * assuming that no two timestamps in sequence have
+ * the same nanosecond value.
+ *
+ * So, we read the "low" register, read the "high"
+ * register (to latch a new timestamp) and read the
+ * "low" register again, if "old" and "new" versions
+ * of the "low" register are different, a valid
+ * timestamp was captured, we can read the "high"
+ * register again.
+ */
+ u32 txstmpl_old, txstmpl_new;
+
+ txstmpl_old = rd32(IGC_TXSTMPL);
+ rd32(IGC_TXSTMPH);
+ txstmpl_new = rd32(IGC_TXSTMPL);
+
+ if (txstmpl_old == txstmpl_new)
+ return;
+
+ regval = txstmpl_new;
+ regval |= (u64)rd32(IGC_TXSTMPH) << 32;
+ }
if (igc_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval))
return;
@@ -676,13 +768,7 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
shhwtstamps.hwtstamp =
ktime_add_ns(shhwtstamps.hwtstamp, adjust);
- /* Clear the lock early before calling skb_tstamp_tx so that
- * applications are not woken up before the lock bit is clear. We use
- * a copy of the skb pointer to ensure other threads can't change it
- * while we're notifying the stack.
- */
adapter->ptp_tx_skb = NULL;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
/* Notify the stack and free the skb after we've unlocked */
skb_tstamp_tx(skb, &shhwtstamps);
@@ -690,27 +776,25 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
}
/**
- * igc_ptp_tx_work
- * @work: pointer to work struct
+ * igc_ptp_tx_tstamp_event
+ * @adapter: board private structure
*
- * This work function polls the TSYNCTXCTL valid bit to determine when a
- * timestamp has been taken for the current stored skb.
+ * Called when a TX timestamp interrupt happens to retrieve the
+ * timestamp and send it up to the socket.
*/
-static void igc_ptp_tx_work(struct work_struct *work)
+void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter)
{
- struct igc_adapter *adapter = container_of(work, struct igc_adapter,
- ptp_tx_work);
- struct igc_hw *hw = &adapter->hw;
- u32 tsynctxctl;
+ unsigned long flags;
- if (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))
- return;
+ spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
- tsynctxctl = rd32(IGC_TSYNCTXCTL);
- if (WARN_ON_ONCE(!(tsynctxctl & IGC_TSYNCTXCTL_TXTT_0)))
- return;
+ if (!adapter->ptp_tx_skb)
+ goto unlock;
igc_ptp_tx_hwtstamp(adapter);
+
+unlock:
+ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
}
/**
@@ -959,8 +1043,8 @@ void igc_ptp_init(struct igc_adapter *adapter)
return;
}
+ spin_lock_init(&adapter->ptp_tx_lock);
spin_lock_init(&adapter->tmreg_lock);
- INIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);
adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
@@ -1020,10 +1104,7 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
return;
- cancel_work_sync(&adapter->ptp_tx_work);
- dev_kfree_skb_any(adapter->ptp_tx_skb);
- adapter->ptp_tx_skb = NULL;
- clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
+ igc_ptp_clear_tx_tstamp(adapter);
if (pci_device_is_present(adapter->pdev)) {
igc_ptp_time_save(adapter);
diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c
index 94a2b0dfb54d..a9c08321aca9 100644
--- a/drivers/net/ethernet/intel/igc/igc_tsn.c
+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
@@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
{
unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
- if (adapter->qbv_enable)
+ if (adapter->taprio_offload_enable)
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_any_launchtime(adapter))
@@ -114,7 +114,6 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
- bool tsn_mode_reconfig = false;
u32 tqavctrl, baset_l, baset_h;
u32 sec, nsec, cycle;
ktime_t base_time, systim;
@@ -133,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
wr32(IGC_STQT(i), ring->start_time);
wr32(IGC_ENDQT(i), ring->end_time);
- txqctl |= IGC_TXQCTL_STRICT_CYCLE |
- IGC_TXQCTL_STRICT_END;
+ if (adapter->taprio_offload_enable) {
+ /* If taprio_offload_enable is set we are in "taprio"
+ * mode and we need to be strict about the
+ * cycles: only transmit a packet if it can be
+ * completed during that cycle.
+ *
+ * If taprio_offload_enable is NOT true when
+ * enabling TSN offload, the cycle should have
+ * no external effects, but is only used internally
+ * to adapt the base time register after a second
+ * has passed.
+ *
+ * Enabling strict mode in this case would
+ * unnecessarily prevent the transmission of
+ * certain packets (i.e. at the boundary of a
+ * second) and thus interfere with the launchtime
+ * feature that promises transmission at a
+ * certain point in time.
+ */
+ txqctl |= IGC_TXQCTL_STRICT_CYCLE |
+ IGC_TXQCTL_STRICT_END;
+ }
if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
@@ -228,11 +247,10 @@ skip_cbs:
tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
- if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
- tsn_mode_reconfig = true;
-
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
+ adapter->qbv_count++;
+
cycle = adapter->cycle_time;
base_time = adapter->base_time;
@@ -249,17 +267,29 @@ skip_cbs:
* Gate Control List (GCL) is running.
*/
if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
- tsn_mode_reconfig)
+ (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
+ (adapter->qbv_count > 1))
adapter->qbv_config_change_errors++;
} else {
- /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
- * has to be configured before the cycle time and base time.
- * Tx won't hang if there is a GCL is already running,
- * so in this case we don't need to set FutScdDis.
- */
- if (igc_is_device_id_i226(hw) &&
- !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
- tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+ if (igc_is_device_id_i226(hw)) {
+ ktime_t adjust_time, expires_time;
+
+ /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+ * has to be configured before the cycle time and base time.
+ * Tx won't hang if a GCL is already running,
+ * so in this case we don't need to set FutScdDis.
+ */
+ if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
+ tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+
+ nsec = rd32(IGC_SYSTIML);
+ sec = rd32(IGC_SYSTIMH);
+ systim = ktime_set(sec, nsec);
+
+ adjust_time = adapter->base_time;
+ expires_time = ktime_sub_ns(adjust_time, systim);
+ hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
+ }
}
wr32(IGC_TQAVCTRL, tqavctrl);
@@ -305,7 +335,11 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
- if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
+ /* Per I225/6 HW Design Section 7.5.2.1, transmit mode
+ * cannot be changed dynamically. Require reset the adapter.
+ */
+ if (netif_running(adapter->netdev) &&
+ (igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
schedule_work(&adapter->reset_task);
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1726297f2e0d..8eb9839a3ca6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8479,7 +8479,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
struct ixgbe_adapter *adapter = q_vector->adapter;
if (unlikely(skb_tail_pointer(skb) < hdr.network +
- VXLAN_HEADROOM))
+ vxlan_headroom(0)))
return;
/* verify the port is recognized as VXLAN */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 0310af851086..9339edbd9082 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -979,6 +979,7 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
+ u32 aflags = adapter->flags;
bool is_l2 = false;
u32 regval;
@@ -996,20 +997,20 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
case HWTSTAMP_FILTER_NONE:
tsync_rx_ctl = 0;
tsync_rx_mtrl = 0;
- adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
- IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+ aflags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+ IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
break;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG;
- adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
- IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+ aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+ IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
break;
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
- adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
- IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+ aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+ IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
break;
case HWTSTAMP_FILTER_PTP_V2_EVENT:
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -1023,8 +1024,8 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
is_l2 = true;
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
- adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
- IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+ aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+ IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
case HWTSTAMP_FILTER_NTP_ALL:
@@ -1035,7 +1036,7 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
if (hw->mac.type >= ixgbe_mac_X550) {
tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_ALL;
config->rx_filter = HWTSTAMP_FILTER_ALL;
- adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+ aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
break;
}
fallthrough;
@@ -1046,8 +1047,6 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
* Delay_Req messages and hardware does not support
* timestamping all packets => return error
*/
- adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
- IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
config->rx_filter = HWTSTAMP_FILTER_NONE;
return -ERANGE;
}
@@ -1079,8 +1078,8 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
IXGBE_TSYNCRXCTL_TYPE_ALL |
IXGBE_TSYNCRXCTL_TSIP_UT_EN;
config->rx_filter = HWTSTAMP_FILTER_ALL;
- adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
- adapter->flags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
+ aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+ aflags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
is_l2 = true;
break;
default:
@@ -1113,6 +1112,9 @@ static int ixgbe_ptp_set_timestamp_mode(struct ixgbe_adapter *adapter,
IXGBE_WRITE_FLUSH(hw);
+ /* configure adapter flags only when HW is actually configured */
+ adapter->flags = aflags;
+
/* clear TX/RX time stamp registers, just to be sure */
ixgbe_ptp_clear_tx_timestamp(adapter);
IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 2b9335cb4bb3..8537578e1cf1 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev)
else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
eth_hw_addr_random(dev);
- clk = devm_clk_get_optional(&pdev->dev, "mdioclk");
+ clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk");
if (IS_ERR(clk))
return PTR_ERR(clk);
if (clk) {
- clk_prepare_enable(clk);
lp->mii_clock_freq = clk_get_rate(clk);
} else {
lp->mii_clock_freq = 200000000; /* max possible input clk */
diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c
index 35f24e0f0934..ffa96059079c 100644
--- a/drivers/net/ethernet/litex/litex_liteeth.c
+++ b/drivers/net/ethernet/litex/litex_liteeth.c
@@ -78,8 +78,7 @@ static int liteeth_rx(struct net_device *netdev)
memcpy_fromio(data, priv->rx_base + rx_slot * priv->slot_size, len);
skb->protocol = eth_type_trans(skb, netdev);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += len;
+ dev_sw_netstats_rx_add(netdev, len);
return netif_rx(skb);
@@ -185,8 +184,7 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb,
litex_write16(priv->base + LITEETH_READER_LENGTH, skb->len);
litex_write8(priv->base + LITEETH_READER_START, 1);
- netdev->stats.tx_bytes += skb->len;
- netdev->stats.tx_packets++;
+ dev_sw_netstats_tx_add(netdev, 1, skb->len);
priv->tx_slot = (priv->tx_slot + 1) % priv->num_tx_slots;
dev_kfree_skb_any(skb);
@@ -194,9 +192,17 @@ static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static void
+liteeth_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
+{
+ netdev_stats_to_stats64(stats, &netdev->stats);
+ dev_fetch_sw_netstats(stats, netdev->tstats);
+}
+
static const struct net_device_ops liteeth_netdev_ops = {
.ndo_open = liteeth_open,
.ndo_stop = liteeth_stop,
+ .ndo_get_stats64 = liteeth_get_stats64,
.ndo_start_xmit = liteeth_start_xmit,
};
@@ -242,6 +248,11 @@ static int liteeth_probe(struct platform_device *pdev)
priv->netdev = netdev;
priv->dev = &pdev->dev;
+ netdev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+ struct pcpu_sw_netstats);
+ if (!netdev->tstats)
+ return -ENOMEM;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 2cad76d0a50e..acf4f6ba73a6 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -344,6 +344,15 @@
#define MVNETA_MAX_SKB_DESCS (MVNETA_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
+/* The size of a TSO header page */
+#define MVNETA_TSO_PAGE_SIZE (2 * PAGE_SIZE)
+
+/* Number of TSO headers per page. This should be a power of 2 */
+#define MVNETA_TSO_PER_PAGE (MVNETA_TSO_PAGE_SIZE / TSO_HEADER_SIZE)
+
+/* Maximum number of TSO header pages */
+#define MVNETA_MAX_TSO_PAGES (MVNETA_MAX_TXD / MVNETA_TSO_PER_PAGE)
+
/* descriptor aligned size */
#define MVNETA_DESC_ALIGNED_SIZE 32
@@ -364,10 +373,6 @@
MVNETA_SKB_HEADROOM))
#define MVNETA_MAX_RX_BUF_SIZE (PAGE_SIZE - MVNETA_SKB_PAD)
-#define IS_TSO_HEADER(txq, addr) \
- ((addr >= txq->tso_hdrs_phys) && \
- (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
-
#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
@@ -638,6 +643,7 @@ struct mvneta_rx_desc {
#endif
enum mvneta_tx_buf_type {
+ MVNETA_TYPE_TSO,
MVNETA_TYPE_SKB,
MVNETA_TYPE_XDP_TX,
MVNETA_TYPE_XDP_NDO,
@@ -690,10 +696,10 @@ struct mvneta_tx_queue {
int next_desc_to_proc;
/* DMA buffers for TSO headers */
- char *tso_hdrs;
+ char *tso_hdrs[MVNETA_MAX_TSO_PAGES];
/* DMA address of TSO headers */
- dma_addr_t tso_hdrs_phys;
+ dma_addr_t tso_hdrs_phys[MVNETA_MAX_TSO_PAGES];
/* Affinity mask for CPUs*/
cpumask_t affinity_mask;
@@ -1505,7 +1511,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
*/
if (txq_number == 1)
txq_map = (cpu == pp->rxq_def) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ MVNETA_CPU_TXQ_ACCESS(0) : 0;
} else {
txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -1878,12 +1884,13 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
mvneta_txq_inc_get(txq);
- if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr) &&
- buf->type != MVNETA_TYPE_XDP_TX)
+ if (buf->type == MVNETA_TYPE_XDP_NDO ||
+ buf->type == MVNETA_TYPE_SKB)
dma_unmap_single(pp->dev->dev.parent,
tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
- if (buf->type == MVNETA_TYPE_SKB && buf->skb) {
+ if ((buf->type == MVNETA_TYPE_TSO ||
+ buf->type == MVNETA_TYPE_SKB) && buf->skb) {
bytes_compl += buf->skb->len;
pkts_compl++;
dev_kfree_skb_any(buf->skb);
@@ -2369,9 +2376,8 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,
if (data_len > 0 && sinfo->nr_frags < MAX_SKB_FRAGS) {
skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags++];
- skb_frag_off_set(frag, pp->rx_offset_correction);
- skb_frag_size_set(frag, data_len);
- __skb_frag_set_page(frag, page);
+ skb_frag_fill_page_desc(frag, page,
+ pp->rx_offset_correction, data_len);
if (!xdp_buff_has_frags(xdp)) {
sinfo->xdp_frags_size = *size;
@@ -2661,20 +2667,72 @@ err_drop_frame:
return rx_done;
}
-static inline void
-mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq)
+static void mvneta_free_tso_hdrs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq)
+{
+ struct device *dev = pp->dev->dev.parent;
+ int i;
+
+ for (i = 0; i < MVNETA_MAX_TSO_PAGES; i++) {
+ if (txq->tso_hdrs[i]) {
+ dma_free_coherent(dev, MVNETA_TSO_PAGE_SIZE,
+ txq->tso_hdrs[i],
+ txq->tso_hdrs_phys[i]);
+ txq->tso_hdrs[i] = NULL;
+ }
+ }
+}
+
+static int mvneta_alloc_tso_hdrs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq)
+{
+ struct device *dev = pp->dev->dev.parent;
+ int i, num;
+
+ num = DIV_ROUND_UP(txq->size, MVNETA_TSO_PER_PAGE);
+ for (i = 0; i < num; i++) {
+ txq->tso_hdrs[i] = dma_alloc_coherent(dev, MVNETA_TSO_PAGE_SIZE,
+ &txq->tso_hdrs_phys[i],
+ GFP_KERNEL);
+ if (!txq->tso_hdrs[i]) {
+ mvneta_free_tso_hdrs(pp, txq);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static char *mvneta_get_tso_hdr(struct mvneta_tx_queue *txq, dma_addr_t *dma)
+{
+ int index, offset;
+
+ index = txq->txq_put_index / MVNETA_TSO_PER_PAGE;
+ offset = (txq->txq_put_index % MVNETA_TSO_PER_PAGE) * TSO_HEADER_SIZE;
+
+ *dma = txq->tso_hdrs_phys[index] + offset;
+
+ return txq->tso_hdrs[index] + offset;
+}
+
+static void mvneta_tso_put_hdr(struct sk_buff *skb, struct mvneta_tx_queue *txq,
+ struct tso_t *tso, int size, bool is_last)
{
struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
int hdr_len = skb_tcp_all_headers(skb);
struct mvneta_tx_desc *tx_desc;
+ dma_addr_t hdr_phys;
+ char *hdr;
+
+ hdr = mvneta_get_tso_hdr(txq, &hdr_phys);
+ tso_build_hdr(skb, hdr, tso, size, is_last);
tx_desc = mvneta_txq_next_desc_get(txq);
tx_desc->data_size = hdr_len;
tx_desc->command = mvneta_skb_tx_csum(skb);
tx_desc->command |= MVNETA_TXD_F_DESC;
- tx_desc->buf_phys_addr = txq->tso_hdrs_phys +
- txq->txq_put_index * TSO_HEADER_SIZE;
- buf->type = MVNETA_TYPE_SKB;
+ tx_desc->buf_phys_addr = hdr_phys;
+ buf->type = MVNETA_TYPE_TSO;
buf->skb = NULL;
mvneta_txq_inc_put(txq);
@@ -2714,14 +2772,41 @@ mvneta_tso_put_data(struct net_device *dev, struct mvneta_tx_queue *txq,
return 0;
}
+static void mvneta_release_descs(struct mvneta_port *pp,
+ struct mvneta_tx_queue *txq,
+ int first, int num)
+{
+ int desc_idx, i;
+
+ desc_idx = first + num;
+ if (desc_idx >= txq->size)
+ desc_idx -= txq->size;
+
+ for (i = num; i >= 0; i--) {
+ struct mvneta_tx_desc *tx_desc = txq->descs + desc_idx;
+ struct mvneta_tx_buf *buf = &txq->buf[desc_idx];
+
+ if (buf->type == MVNETA_TYPE_SKB)
+ dma_unmap_single(pp->dev->dev.parent,
+ tx_desc->buf_phys_addr,
+ tx_desc->data_size,
+ DMA_TO_DEVICE);
+
+ mvneta_txq_desc_put(txq);
+
+ if (desc_idx == 0)
+ desc_idx = txq->size;
+ desc_idx -= 1;
+ }
+}
+
static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
struct mvneta_tx_queue *txq)
{
int hdr_len, total_len, data_left;
- int desc_count = 0;
+ int first_desc, desc_count = 0;
struct mvneta_port *pp = netdev_priv(dev);
struct tso_t tso;
- int i;
/* Count needed descriptors */
if ((txq->count + tso_count_descs(skb)) >= txq->size)
@@ -2732,22 +2817,19 @@ static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
return 0;
}
+ first_desc = txq->txq_put_index;
+
/* Initialize the TSO handler, and prepare the first payload */
hdr_len = tso_start(skb, &tso);
total_len = skb->len - hdr_len;
while (total_len > 0) {
- char *hdr;
-
data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
total_len -= data_left;
desc_count++;
/* prepare packet headers: MAC + IP + TCP */
- hdr = txq->tso_hdrs + txq->txq_put_index * TSO_HEADER_SIZE;
- tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-
- mvneta_tso_put_hdr(skb, txq);
+ mvneta_tso_put_hdr(skb, txq, &tso, data_left, total_len == 0);
while (data_left > 0) {
int size;
@@ -2772,15 +2854,7 @@ err_release:
/* Release all used data descriptors; header descriptors must not
* be DMA-unmapped.
*/
- for (i = desc_count - 1; i >= 0; i--) {
- struct mvneta_tx_desc *tx_desc = txq->descs + i;
- if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
- dma_unmap_single(pp->dev->dev.parent,
- tx_desc->buf_phys_addr,
- tx_desc->data_size,
- DMA_TO_DEVICE);
- mvneta_txq_desc_put(txq);
- }
+ mvneta_release_descs(pp, txq, first_desc, desc_count - 1);
return 0;
}
@@ -2790,6 +2864,7 @@ static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
{
struct mvneta_tx_desc *tx_desc;
int i, nr_frags = skb_shinfo(skb)->nr_frags;
+ int first_desc = txq->txq_put_index;
for (i = 0; i < nr_frags; i++) {
struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
@@ -2828,15 +2903,7 @@ error:
/* Release all descriptors that were used to map fragments of
* this packet, as well as the corresponding DMA mappings
*/
- for (i = i - 1; i >= 0; i--) {
- tx_desc = txq->descs + i;
- dma_unmap_single(pp->dev->dev.parent,
- tx_desc->buf_phys_addr,
- tx_desc->data_size,
- DMA_TO_DEVICE);
- mvneta_txq_desc_put(txq);
- }
-
+ mvneta_release_descs(pp, txq, first_desc, i - 1);
return -ENOMEM;
}
@@ -3457,7 +3524,7 @@ static void mvneta_rxq_deinit(struct mvneta_port *pp,
static int mvneta_txq_sw_init(struct mvneta_port *pp,
struct mvneta_tx_queue *txq)
{
- int cpu;
+ int cpu, err;
txq->size = pp->tx_ring_size;
@@ -3482,11 +3549,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
return -ENOMEM;
/* Allocate DMA buffers for TSO MAC/IP/TCP headers */
- txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent,
- txq->size * TSO_HEADER_SIZE,
- &txq->tso_hdrs_phys, GFP_KERNEL);
- if (!txq->tso_hdrs)
- return -ENOMEM;
+ err = mvneta_alloc_tso_hdrs(pp, txq);
+ if (err)
+ return err;
/* Setup XPS mapping */
if (pp->neta_armada3700)
@@ -3538,10 +3603,7 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
kfree(txq->buf);
- if (txq->tso_hdrs)
- dma_free_coherent(pp->dev->dev.parent,
- txq->size * TSO_HEADER_SIZE,
- txq->tso_hdrs, txq->tso_hdrs_phys);
+ mvneta_free_tso_hdrs(pp, txq);
if (txq->descs)
dma_free_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE,
@@ -3550,7 +3612,6 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
netdev_tx_reset_queue(nq);
txq->buf = NULL;
- txq->tso_hdrs = NULL;
txq->descs = NULL;
txq->last_desc = 0;
txq->next_desc_to_proc = 0;
@@ -3941,8 +4002,8 @@ static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mvneta_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode, phy_interface_t interface,
+static int mvneta_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
@@ -3955,7 +4016,7 @@ static int mvneta_pcs_config(struct phylink_pcs *pcs,
MVNETA_GMAC_AN_FLOW_CTRL_EN |
MVNETA_GMAC_AN_DUPLEX_EN;
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
mask |= MVNETA_GMAC_CONFIG_MII_SPEED |
MVNETA_GMAC_CONFIG_GMII_SPEED |
MVNETA_GMAC_CONFIG_FULL_DUPLEX;
@@ -4295,7 +4356,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp)
*/
if (txq_number == 1)
txq_map = (cpu == elected_cpu) ?
- MVNETA_CPU_TXQ_ACCESS(1) : 0;
+ MVNETA_CPU_TXQ_ACCESS(0) : 0;
else
txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -5457,6 +5518,7 @@ static int mvneta_probe(struct platform_device *pdev)
clk_prepare_enable(pp->clk_bus);
pp->phylink_pcs.ops = &mvneta_phylink_pcs_ops;
+ pp->phylink_pcs.neg_mode = true;
pp->phylink_config.dev = &dev->dev;
pp->phylink_config.type = PHYLINK_NETDEV;
@@ -5821,6 +5883,8 @@ static int __init mvneta_driver_init(void)
{
int ret;
+ BUILD_BUG_ON_NOT_POWER_OF_2(MVNETA_TSO_PER_PAGE);
+
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "net/mvneta:online",
mvneta_cpu_online,
mvneta_cpu_down_prepare);
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index adc953611913..0129afa1210e 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -5586,6 +5586,11 @@ static int mvpp2_ethtool_get_rxnfc(struct net_device *dev,
break;
case ETHTOOL_GRXCLSRLALL:
for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
+ if (loc == info->rule_cnt) {
+ ret = -EMSGSIZE;
+ break;
+ }
+
if (port->rfs_rules[i])
rules[loc++] = i;
}
@@ -6168,8 +6173,7 @@ static void mvpp2_xlg_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_RX;
}
-static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int mvpp2_xlg_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -6232,7 +6236,7 @@ static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
state->pause |= MLO_PAUSE_TX;
}
-static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -6246,7 +6250,7 @@ static int mvpp2_gmac_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
MVPP2_GMAC_FLOW_CTRL_AUTONEG |
MVPP2_GMAC_AN_DUPLEX_EN;
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
mask |= MVPP2_GMAC_CONFIG_MII_SPEED |
MVPP2_GMAC_CONFIG_GMII_SPEED |
MVPP2_GMAC_CONFIG_FULL_DUPLEX;
@@ -6649,8 +6653,9 @@ static void mvpp2_acpi_start(struct mvpp2_port *port)
mvpp2_mac_prepare(&port->phylink_config, MLO_AN_INBAND,
port->phy_interface);
mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
- pcs->ops->pcs_config(pcs, MLO_AN_INBAND, port->phy_interface,
- state.advertising, false);
+ pcs->ops->pcs_config(pcs, PHYLINK_PCS_NEG_INBAND_ENABLED,
+ port->phy_interface, state.advertising,
+ false);
mvpp2_mac_finish(&port->phylink_config, MLO_AN_INBAND,
port->phy_interface);
mvpp2_mac_link_up(&port->phylink_config, NULL,
@@ -6896,7 +6901,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
dev->dev.of_node = port_node;
port->pcs_gmac.ops = &mvpp2_phylink_gmac_pcs_ops;
+ port->pcs_gmac.neg_mode = true;
port->pcs_xlg.ops = &mvpp2_phylink_xlg_pcs_ops;
+ port->pcs_xlg.neg_mode = true;
if (!mvpp2_use_acpi_compat_mode(port_fwnode)) {
port->phylink_config.dev = &dev->dev;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
index 035ead7935c7..dab61cc1acb5 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
@@ -98,6 +98,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
+ mutex_init(&mbox->h2fq_lock);
+ mutex_init(&mbox->f2hq_lock);
+
mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
index 1cc6af2feb38..565320ec24f8 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
@@ -55,7 +55,7 @@ static int octep_send_mbox_req(struct octep_device *oct,
list_add_tail(&d->list, &oct->ctrl_req_wait_list);
ret = wait_event_interruptible_timeout(oct->ctrl_req_wait_q,
(d->done != 0),
- jiffies + msecs_to_jiffies(500));
+ msecs_to_jiffies(500));
list_del(&d->list);
if (ret == 0 || ret == 1)
return -EAGAIN;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 43eb6e871351..4424de2ffd70 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -1038,6 +1038,10 @@ static void octep_device_cleanup(struct octep_device *oct)
{
int i;
+ oct->poll_non_ioq_intr = false;
+ cancel_delayed_work_sync(&oct->intr_poll_task);
+ cancel_work_sync(&oct->ctrl_mbox_task);
+
dev_info(&oct->pdev->dev, "Cleaning up Octeon Device ...\n");
for (i = 0; i < OCTEP_MAX_VF; i++) {
@@ -1200,14 +1204,11 @@ static void octep_remove(struct pci_dev *pdev)
if (!oct)
return;
- cancel_work_sync(&oct->tx_timeout_task);
- cancel_work_sync(&oct->ctrl_mbox_task);
netdev = oct->netdev;
if (netdev->reg_state == NETREG_REGISTERED)
unregister_netdev(netdev);
- oct->poll_non_ioq_intr = false;
- cancel_delayed_work_sync(&oct->intr_poll_task);
+ cancel_work_sync(&oct->tx_timeout_task);
octep_device_cleanup(oct);
pci_release_mem_regions(pdev);
free_netdev(netdev);
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
index 392d9b0da0d7..3c43f8078528 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
@@ -158,7 +158,7 @@ static int octep_setup_oq(struct octep_device *oct, int q_no)
goto desc_dma_alloc_err;
}
- oq->buff_info = vzalloc(oq->max_count * OCTEP_OQ_RECVBUF_SIZE);
+ oq->buff_info = vcalloc(oq->max_count, OCTEP_OQ_RECVBUF_SIZE);
if (unlikely(!oq->buff_info)) {
dev_err(&oct->pdev->dev,
"Failed to allocate buffer info for OQ-%d\n", q_no);
diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig
index 993ac180a5db..a32d85d6f599 100644
--- a/drivers/net/ethernet/marvell/octeontx2/Kconfig
+++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig
@@ -32,6 +32,7 @@ config OCTEONTX2_PF
tristate "Marvell OcteonTX2 NIC Physical Function driver"
select OCTEONTX2_MBOX
select NET_DEVLINK
+ select PAGE_POOL
depends on (64BIT && COMPILE_TEST) || ARM64
select DIMLIB
depends on PCI
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index bd77152bb8d7..592037f4e55b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -169,6 +169,9 @@ void cgx_lmac_write(int cgx_id, int lmac_id, u64 offset, u64 val)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+ /* Software must not access disabled LMAC registers */
+ if (!is_lmac_valid(cgx_dev, lmac_id))
+ return;
cgx_write(cgx_dev, lmac_id, offset, val);
}
@@ -176,6 +179,10 @@ u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
+ /* Software must not access disabled LMAC registers */
+ if (!is_lmac_valid(cgx_dev, lmac_id))
+ return 0;
+
return cgx_read(cgx_dev, lmac_id, offset);
}
@@ -530,14 +537,15 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
int cgx_lmac_internal_loopback(void *cgxd, int lmac_id, bool enable)
{
struct cgx *cgx = cgxd;
- u8 lmac_type;
+ struct lmac *lmac;
u64 cfg;
if (!is_lmac_valid(cgx, lmac_id))
return -ENODEV;
- lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac_id);
- if (lmac_type == LMAC_MODE_SGMII || lmac_type == LMAC_MODE_QSGMII) {
+ lmac = lmac_pdata(lmac_id, cgx);
+ if (lmac->lmac_type == LMAC_MODE_SGMII ||
+ lmac->lmac_type == LMAC_MODE_QSGMII) {
cfg = cgx_read(cgx, lmac_id, CGXX_GMP_PCS_MRX_CTL);
if (enable)
cfg |= CGXX_GMP_PCS_MRX_CTL_LBK;
@@ -1556,6 +1564,23 @@ int cgx_lmac_linkup_start(void *cgxd)
return 0;
}
+int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
+
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
+ /* Resetting PFC related CSRs */
+ cfg = 0xff;
+ cgx_write(cgxd, lmac_id, CGXX_CMRX_RX_LOGL_XON, cfg);
+
+ if (pf_req_flr)
+ cgx_lmac_internal_loopback(cgxd, lmac_id, false);
+ return 0;
+}
+
static int cgx_configure_interrupt(struct cgx *cgx, struct lmac *lmac,
int cnt, bool req_free)
{
@@ -1675,6 +1700,7 @@ static int cgx_lmac_init(struct cgx *cgx)
cgx->lmac_idmap[lmac->lmac_id] = lmac;
set_bit(lmac->lmac_id, &cgx->lmac_bmap);
cgx->mac_ops->mac_pause_frm_config(cgx, lmac->lmac_id, true);
+ lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
}
return cgx_lmac_verify_fwi_version(cgx);
@@ -1771,6 +1797,7 @@ static struct mac_ops cgx_mac_ops = {
.mac_tx_enable = cgx_lmac_tx_enable,
.pfc_config = cgx_lmac_pfc_config,
.mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg,
+ .mac_reset = cgx_lmac_reset,
};
static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
index 5a20d93004c7..574114179688 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
@@ -35,6 +35,7 @@
#define CGXX_CMRX_INT_ENA_W1S 0x058
#define CGXX_CMRX_RX_ID_MAP 0x060
#define CGXX_CMRX_RX_STAT0 0x070
+#define CGXX_CMRX_RX_LOGL_XON 0x100
#define CGXX_CMRX_RX_LMACS 0x128
#define CGXX_CMRX_RX_DMAC_CTL0 (0x1F8 + mac_ops->csr_offset)
#define CGX_DMAC_CTL0_CAM_ENABLE BIT_ULL(3)
@@ -181,4 +182,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
u8 *rx_pause);
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
int pfvf_idx);
+int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
#endif /* CGX_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index 8931864ee110..2436c1ff9ba4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -142,9 +142,16 @@ enum nix_scheduler {
#define TXSCH_RR_QTM_MAX ((1 << 24) - 1)
#define TXSCH_TL1_DFLT_RR_QTM TXSCH_RR_QTM_MAX
-#define TXSCH_TL1_DFLT_RR_PRIO (0x1ull)
+#define TXSCH_TL1_DFLT_RR_PRIO (0x7ull)
#define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */
+/* Don't change the order as on CN10K (except CN10KB)
+ * SMQX_CFG[SDP] value should be 1 for SDP flows.
+ */
+#define SMQ_LINK_TYPE_RPM 0
+#define SMQ_LINK_TYPE_SDP 1
+#define SMQ_LINK_TYPE_LBK 2
+
/* Min/Max packet sizes, excluding FCS */
#define NIC_HW_MIN_FRS 40
#define NIC_HW_MAX_FRS 9212
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
index 39aaf0e4467d..0b4cba03f2e8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
@@ -24,6 +24,7 @@
* @cgx: parent cgx port
* @mcast_filters_count: Number of multicast filters installed
* @lmac_id: lmac port id
+ * @lmac_type: lmac type like SGMII/XAUI
* @cmd_pend: flag set before new command is started
* flag cleared after command response is received
* @name: lmac port name
@@ -43,6 +44,7 @@ struct lmac {
struct cgx *cgx;
u8 mcast_filters_count;
u8 lmac_id;
+ u8 lmac_type;
bool cmd_pend;
char *name;
};
@@ -125,6 +127,7 @@ struct mac_ops {
int (*mac_get_pfc_frm_cfg)(void *cgxd, int lmac_id,
u8 *tx_pause, u8 *rx_pause);
+ int (*mac_reset)(void *cgxd, int lmac_id, u8 pf_req_flr);
/* FEC stats */
int (*get_fec_stats)(void *cgxd, int lmac_id,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 6389ed83637d..eba307eee2b2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp {
*/
};
+#define NIX_FLOW_KEY_TYPE_L3_L4_MASK (~(0xf << 28))
+
struct nix_rss_flowkey_cfg {
struct mbox_msghdr hdr;
int mcam_index; /* MCAM entry index to modify */
@@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg {
#define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21)
#define NIX_FLOW_KEY_TYPE_AH BIT(22)
#define NIX_FLOW_KEY_TYPE_ESP BIT(23)
+#define NIX_FLOW_KEY_TYPE_L4_DST_ONLY BIT(28)
+#define NIX_FLOW_KEY_TYPE_L4_SRC_ONLY BIT(29)
+#define NIX_FLOW_KEY_TYPE_L3_DST_ONLY BIT(30)
+#define NIX_FLOW_KEY_TYPE_L3_SRC_ONLY BIT(31)
u32 flowkey_cfg; /* Flowkey types selected */
u8 group; /* RSS context or group */
};
@@ -1151,6 +1157,7 @@ struct nix_rx_cfg {
struct mbox_msghdr hdr;
#define NIX_RX_OL3_VERIFY BIT(0)
#define NIX_RX_OL4_VERIFY BIT(1)
+#define NIX_RX_DROP_RE BIT(2)
u8 len_verify; /* Outer L3/L4 len check */
#define NIX_RX_CSUM_OL4_VERIFY BIT(0)
u8 csum_verify; /* Outer L4 checksum verification */
@@ -1239,7 +1246,9 @@ struct nix_hw_info {
u16 min_mtu;
u32 rpm_dwrr_mtu;
u32 sdp_dwrr_mtu;
- u64 rsvd[16]; /* Add reserved fields for future expansion */
+ u32 lbk_dwrr_mtu;
+ u32 rsvd32[1];
+ u64 rsvd[15]; /* Add reserved fields for future expansion */
};
struct nix_bandprof_alloc_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
index 3411e2e47d46..0ee420a489fc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
@@ -208,7 +208,7 @@ struct ptp *ptp_get(void)
/* Check driver is bound to PTP block */
if (!ptp)
ptp = ERR_PTR(-EPROBE_DEFER);
- else
+ else if (!IS_ERR(ptp))
pci_dev_get(ptp->pdev);
return ptp;
@@ -388,11 +388,10 @@ static int ptp_extts_on(struct ptp *ptp, int on)
static int ptp_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- struct device *dev = &pdev->dev;
struct ptp *ptp;
int err;
- ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL);
+ ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);
if (!ptp) {
err = -ENOMEM;
goto error;
@@ -428,20 +427,19 @@ static int ptp_probe(struct pci_dev *pdev,
return 0;
error_free:
- devm_kfree(dev, ptp);
+ kfree(ptp);
error:
/* For `ptp_get()` we need to differentiate between the case
* when the core has not tried to probe this device and the case when
- * the probe failed. In the later case we pretend that the
- * initialization was successful and keep the error in
+ * the probe failed. In the later case we keep the error in
* `dev->driver_data`.
*/
pci_set_drvdata(pdev, ERR_PTR(err));
if (!first_ptp_block)
first_ptp_block = ERR_PTR(err);
- return 0;
+ return err;
}
static void ptp_remove(struct pci_dev *pdev)
@@ -449,16 +447,17 @@ static void ptp_remove(struct pci_dev *pdev)
struct ptp *ptp = pci_get_drvdata(pdev);
u64 clock_cfg;
- if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
- hrtimer_cancel(&ptp->hrtimer);
-
if (IS_ERR_OR_NULL(ptp))
return;
+ if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
+ hrtimer_cancel(&ptp->hrtimer);
+
/* Disable PTP clock */
clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
+ kfree(ptp);
}
static const struct pci_device_id ptp_id_table[] = {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
index de0d88dd10d6..af21e2030cff 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
@@ -37,6 +37,7 @@ static struct mac_ops rpm_mac_ops = {
.mac_tx_enable = rpm_lmac_tx_enable,
.pfc_config = rpm_lmac_pfc_config,
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
+ .mac_reset = rpm_lmac_reset,
};
static struct mac_ops rpm2_mac_ops = {
@@ -47,7 +48,7 @@ static struct mac_ops rpm2_mac_ops = {
.int_set_reg = RPM2_CMRX_SW_INT_ENA_W1S,
.irq_offset = 1,
.int_ena_bit = BIT_ULL(0),
- .lmac_fwi = RPM_LMAC_FWI,
+ .lmac_fwi = RPM2_LMAC_FWI,
.non_contiguous_serdes_lane = true,
.rx_stats_cnt = 43,
.tx_stats_cnt = 34,
@@ -68,6 +69,7 @@ static struct mac_ops rpm2_mac_ops = {
.mac_tx_enable = rpm_lmac_tx_enable,
.pfc_config = rpm_lmac_pfc_config,
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
+ .mac_reset = rpm_lmac_reset,
};
bool is_dev_rpm2(void *rpmd)
@@ -353,8 +355,8 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause,
void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
{
+ u64 cfg, pfc_class_mask_cfg;
rpm_t *rpm = rpmd;
- u64 cfg;
/* ALL pause frames received are completely ignored */
cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
@@ -378,9 +380,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL);
/* Disable all PFC classes */
- cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
+ pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
+ RPMX_CMRX_PRT_CBFC_CTL;
+ cfg = rpm_read(rpm, lmac_id, pfc_class_mask_cfg);
cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg);
- rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg);
+ rpm_write(rpm, lmac_id, pfc_class_mask_cfg, cfg);
}
int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat)
@@ -537,14 +541,15 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable)
{
rpm_t *rpm = rpmd;
- u8 lmac_type;
+ struct lmac *lmac;
u64 cfg;
if (!is_lmac_valid(rpm, lmac_id))
return -ENODEV;
- lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id);
- if (lmac_type == LMAC_MODE_QSGMII || lmac_type == LMAC_MODE_SGMII) {
+ lmac = lmac_pdata(lmac_id, rpm);
+ if (lmac->lmac_type == LMAC_MODE_QSGMII ||
+ lmac->lmac_type == LMAC_MODE_SGMII) {
dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n");
return 0;
}
@@ -602,8 +607,11 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
if (!is_lmac_valid(rpm, lmac_id))
return -ENODEV;
+ pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
+ RPMX_CMRX_PRT_CBFC_CTL;
+
cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
- class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
+ class_en = rpm_read(rpm, lmac_id, pfc_class_mask_cfg);
pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en);
if (rx_pause) {
@@ -632,10 +640,6 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE;
rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
-
- pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
- RPMX_CMRX_PRT_CBFC_CTL;
-
rpm_write(rpm, lmac_id, pfc_class_mask_cfg, class_en);
return 0;
@@ -713,3 +717,24 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
return 0;
}
+
+int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)
+{
+ u64 rx_logl_xon, cfg;
+ rpm_t *rpm = rpmd;
+
+ if (!is_lmac_valid(rpm, lmac_id))
+ return -ENODEV;
+
+ /* Resetting PFC related CSRs */
+ rx_logl_xon = is_dev_rpm2(rpm) ? RPM2_CMRX_RX_LOGL_XON :
+ RPMX_CMRX_RX_LOGL_XON;
+ cfg = 0xff;
+
+ rpm_write(rpm, lmac_id, rx_logl_xon, cfg);
+
+ if (pf_req_flr)
+ rpm_lmac_internal_loopback(rpm, lmac_id, false);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
index 22147b4c2137..b79cfbc6f877 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
@@ -74,6 +74,7 @@
#define RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA 0x80A8
#define RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA 0x8108
#define RPM_DEFAULT_PAUSE_TIME 0x7FF
+#define RPMX_CMRX_RX_LOGL_XON 0x4100
#define RPMX_MTI_MAC100X_XIF_MODE 0x8100
#define RPMX_ONESTEP_ENABLE BIT_ULL(5)
@@ -94,7 +95,8 @@
/* CN10KB CSR Declaration */
#define RPM2_CMRX_SW_INT 0x1b0
-#define RPM2_CMRX_SW_INT_ENA_W1S 0x1b8
+#define RPM2_CMRX_SW_INT_ENA_W1S 0x1c8
+#define RPM2_LMAC_FWI 0x12
#define RPM2_CMR_CHAN_MSK_OR 0x3120
#define RPM2_CMR_RX_OVR_BP_EN BIT_ULL(2)
#define RPM2_CMR_RX_OVR_BP_BP BIT_ULL(1)
@@ -131,4 +133,5 @@ int rpm_lmac_get_pfc_frm_cfg(void *rpmd, int lmac_id, u8 *tx_pause,
int rpm2_get_nr_lmacs(void *rpmd);
bool is_dev_rpm2(void *rpmd);
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
+int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
#endif /* RPM_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 9f673bda9dbd..73df2d564545 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -2629,6 +2629,7 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
* Since LF is detached use LF number as -1.
*/
rvu_npc_free_mcam_entries(rvu, pcifunc, -1);
+ rvu_mac_reset(rvu, pcifunc);
mutex_unlock(&rvu->flr_lock);
}
@@ -3044,9 +3045,8 @@ static int rvu_flr_init(struct rvu *rvu)
cfg | BIT_ULL(22));
}
- rvu->flr_wq = alloc_workqueue("rvu_afpf_flr",
- WQ_UNBOUND | WQ_HIGHPRI | WQ_MEM_RECLAIM,
- 1);
+ rvu->flr_wq = alloc_ordered_workqueue("rvu_afpf_flr",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!rvu->flr_wq)
return -ENOMEM;
@@ -3252,7 +3252,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rvu->ptp = ptp_get();
if (IS_ERR(rvu->ptp)) {
err = PTR_ERR(rvu->ptp);
- if (err == -EPROBE_DEFER)
+ if (err)
goto err_release_regions;
rvu->ptp = NULL;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index d655bf04a483..e8e65fd7888d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -23,6 +23,7 @@
#define PCI_DEVID_OCTEONTX2_LBK 0xA061
/* Subsystem Device ID */
+#define PCI_SUBSYS_DEVID_98XX 0xB100
#define PCI_SUBSYS_DEVID_96XX 0xB200
#define PCI_SUBSYS_DEVID_CN10K_A 0xB900
#define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00
@@ -285,6 +286,22 @@ struct nix_mark_format {
u32 *cfg;
};
+/* smq(flush) to tl1 cir/pir info */
+struct nix_smq_tree_ctx {
+ u64 cir_off;
+ u64 cir_val;
+ u64 pir_off;
+ u64 pir_val;
+};
+
+/* smq flush context */
+struct nix_smq_flush_ctx {
+ int smq;
+ u16 tl1_schq;
+ u16 tl2_schq;
+ struct nix_smq_tree_ctx smq_tree_ctx[NIX_TXSCH_LVL_CNT];
+};
+
struct npc_pkind {
struct rsrc_bmap rsrc;
u32 *pfchan_map;
@@ -346,6 +363,7 @@ struct hw_cap {
bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */
bool programmable_chans; /* Channels programmable ? */
bool ipolicer;
+ bool nix_multiple_dwrr_mtu; /* Multiple DWRR_MTU to choose from */
bool npc_hash_extract; /* Hash extract enabled ? */
bool npc_exact_match_enabled; /* Exact match supported ? */
};
@@ -669,6 +687,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan)
return rvu->hw->cpt_chan_base + chan;
}
+static inline bool is_rvu_supports_nix1(struct rvu *rvu)
+{
+ struct pci_dev *pdev = rvu->pdev;
+
+ if (pdev->subsystem_device == PCI_SUBSYS_DEVID_98XX)
+ return true;
+
+ return false;
+}
+
/* Function Prototypes
* RVU
*/
@@ -802,8 +830,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw,
struct nix_cn10k_aq_enq_rsp *aq_rsp,
u16 pcifunc, u8 ctype, u32 qidx);
int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc);
+int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type);
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu);
u32 convert_bytes_to_dwrr_mtu(u32 bytes);
+void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
+ struct nix_txsch *txsch, bool enable);
/* NPC APIs */
void rvu_npc_freemem(struct rvu *rvu);
@@ -864,6 +895,7 @@ int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable);
int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause,
u16 pfc_en);
int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause);
+void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 83b342fa8d75..095b2cc4a699 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -114,7 +114,7 @@ static void rvu_map_cgx_nix_block(struct rvu *rvu, int pf,
p2x = cgx_lmac_get_p2x(cgx_id, lmac_id);
/* Firmware sets P2X_SELECT as either NIX0 or NIX1 */
pfvf->nix_blkaddr = BLKADDR_NIX0;
- if (p2x == CMR_P2X_SEL_NIX1)
+ if (is_rvu_supports_nix1(rvu) && p2x == CMR_P2X_SEL_NIX1)
pfvf->nix_blkaddr = BLKADDR_NIX1;
}
@@ -763,7 +763,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
cgxd = rvu_cgx_pdata(cgx_id, rvu);
mac_ops = get_mac_ops(cgxd);
- mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true);
+ mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, enable);
/* If PTP is enabled then inform NPC that packets to be
* parsed by this PF will have their data shifted by 8 bytes
* and if PTP is disabled then no shift is required
@@ -1250,3 +1250,21 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_cfg(struct rvu *rvu,
mac_ops->mac_get_pfc_frm_cfg(cgxd, lmac_id, &rsp->tx_pause, &rsp->rx_pause);
return err;
}
+
+void rvu_mac_reset(struct rvu *rvu, u16 pcifunc)
+{
+ int pf = rvu_get_pf(pcifunc);
+ struct mac_ops *mac_ops;
+ struct cgx *cgxd;
+ u8 cgx, lmac;
+
+ if (!is_pf_cgxmapped(rvu, pf))
+ return;
+
+ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx, &lmac);
+ cgxd = rvu_cgx_pdata(cgx, rvu);
+ mac_ops = get_mac_ops(cgxd);
+
+ if (mac_ops->mac_reset(cgxd, lmac, !is_vf(pcifunc)))
+ dev_err(rvu->dev, "Failed to reset MAC\n");
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 9533b1d92960..3b26893efdf8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -1222,6 +1222,11 @@ static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype)
for (aura = id; aura < max_id; aura++) {
aq_req.aura_id = aura;
+
+ /* Skip if queue is uninitialized */
+ if (ctype == NPA_AQ_CTYPE_POOL && !test_bit(aura, pfvf->pool_bmap))
+ continue;
+
seq_printf(m, "======%s : %d=======\n",
(ctype == NPA_AQ_CTYPE_AURA) ? "AURA" : "POOL",
aq_req.aura_id);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
index e4407f09c9d3..41df5ac23f92 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,
u64 dwrr_mtu;
dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32);
- rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu);
+ rvu_write64(rvu, BLKADDR_NIX0,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu);
return 0;
}
@@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
if (!rvu->hw->cap.nix_common_dwrr_mtu)
return -EOPNOTSUPP;
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU);
+ dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu);
return 0;
@@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+ RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
};
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
@@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
return -EFAULT;
}
+static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+ u32 percent;
+
+ mcam = &rvu->hw->mcam;
+ percent = (mcam->hprio_count * 100) / mcam->bmap_entries;
+ ctx->val.vu8 = (u8)percent;
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+ u32 percent;
+
+ percent = ctx->val.vu8;
+ mcam = &rvu->hw->mcam;
+ mcam->hprio_count = (mcam->bmap_entries * percent) / 100;
+ mcam->hprio_end = mcam->hprio_count;
+ mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2;
+ mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count;
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,
+ union devlink_param_value val,
+ struct netlink_ext_ack *extack)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+ struct npc_mcam *mcam;
+
+ /* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */
+ if (val.vu8 < 12 || val.vu8 > 100) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "mcam high zone percent must be between 12% to 100%");
+ return -EINVAL;
+ }
+
+ /* Do not allow user to modify the high priority zone entries while mcam entries
+ * have already been assigned.
+ */
+ mcam = &rvu->hw->mcam;
+ if (mcam->bmap_fcnt < mcam->bmap_entries) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "mcam entries have already been assigned, can't resize");
+ return -EPERM;
+ }
+
+ return 0;
+}
+
static const struct devlink_param rvu_af_dl_params[] = {
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
"dwrr_mtu", DEVLINK_PARAM_TYPE_U32,
@@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = {
rvu_af_npc_exact_feature_get,
rvu_af_npc_exact_feature_disable,
rvu_af_npc_exact_feature_validate),
+ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
+ "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ rvu_af_dl_npc_mcam_high_zone_percent_get,
+ rvu_af_dl_npc_mcam_high_zone_percent_set,
+ rvu_af_dl_npc_mcam_high_zone_percent_validate),
};
/* Devlink switch mode */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index f01d057ad025..23c2f2ed2fb8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr)
return NULL;
}
+int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type)
+{
+ if (hw->cap.nix_multiple_dwrr_mtu)
+ return NIX_AF_DWRR_MTUX(smq_link_type);
+
+ if (smq_link_type == SMQ_LINK_TYPE_SDP)
+ return NIX_AF_DWRR_SDP_MTU;
+
+ /* Here it's same reg for RPM and LBK */
+ return NIX_AF_DWRR_RPM_MTU;
+}
+
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu)
{
dwrr_mtu &= 0x1FULL;
@@ -834,6 +846,21 @@ static int nix_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block,
return 0;
}
+static void nix_get_aq_req_smq(struct rvu *rvu, struct nix_aq_enq_req *req,
+ u16 *smq, u16 *smq_mask)
+{
+ struct nix_cn10k_aq_enq_req *aq_req;
+
+ if (!is_rvu_otx2(rvu)) {
+ aq_req = (struct nix_cn10k_aq_enq_req *)req;
+ *smq = aq_req->sq.smq;
+ *smq_mask = aq_req->sq_mask.smq;
+ } else {
+ *smq = req->sq.smq;
+ *smq_mask = req->sq_mask.smq;
+ }
+}
+
static int rvu_nix_blk_aq_enq_inst(struct rvu *rvu, struct nix_hw *nix_hw,
struct nix_aq_enq_req *req,
struct nix_aq_enq_rsp *rsp)
@@ -845,6 +872,7 @@ static int rvu_nix_blk_aq_enq_inst(struct rvu *rvu, struct nix_hw *nix_hw,
struct rvu_block *block;
struct admin_queue *aq;
struct rvu_pfvf *pfvf;
+ u16 smq, smq_mask;
void *ctx, *mask;
bool ena;
u64 cfg;
@@ -916,13 +944,14 @@ static int rvu_nix_blk_aq_enq_inst(struct rvu *rvu, struct nix_hw *nix_hw,
if (rc)
return rc;
+ nix_get_aq_req_smq(rvu, req, &smq, &smq_mask);
/* Check if SQ pointed SMQ belongs to this PF/VF or not */
if (req->ctype == NIX_AQ_CTYPE_SQ &&
((req->op == NIX_AQ_INSTOP_INIT && req->sq.ena) ||
(req->op == NIX_AQ_INSTOP_WRITE &&
- req->sq_mask.ena && req->sq_mask.smq && req->sq.ena))) {
+ req->sq_mask.ena && req->sq.ena && smq_mask))) {
if (!is_valid_txschq(rvu, blkaddr, NIX_TXSCH_LVL_SMQ,
- pcifunc, req->sq.smq))
+ pcifunc, smq))
return NIX_AF_ERR_AQ_ENQUEUE;
}
@@ -1691,6 +1720,42 @@ exit:
return true;
}
+static void nix_reset_tx_schedule(struct rvu *rvu, int blkaddr,
+ int lvl, int schq)
+{
+ u64 tlx_parent = 0, tlx_schedule = 0;
+
+ switch (lvl) {
+ case NIX_TXSCH_LVL_TL2:
+ tlx_parent = NIX_AF_TL2X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL2X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_TL3:
+ tlx_parent = NIX_AF_TL3X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL3X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_TL4:
+ tlx_parent = NIX_AF_TL4X_PARENT(schq);
+ tlx_schedule = NIX_AF_TL4X_SCHEDULE(schq);
+ break;
+ case NIX_TXSCH_LVL_MDQ:
+ /* no need to reset SMQ_CFG as HW clears this CSR
+ * on SMQ flush
+ */
+ tlx_parent = NIX_AF_MDQX_PARENT(schq);
+ tlx_schedule = NIX_AF_MDQX_SCHEDULE(schq);
+ break;
+ default:
+ return;
+ }
+
+ if (tlx_parent)
+ rvu_write64(rvu, blkaddr, tlx_parent, 0x0);
+
+ if (tlx_schedule)
+ rvu_write64(rvu, blkaddr, tlx_schedule, 0x0);
+}
+
/* Disable shaping of pkts by a scheduler queue
* at a given scheduler level.
*/
@@ -2040,6 +2105,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}
for (idx = 0; idx < req->schq[lvl]; idx++) {
@@ -2049,6 +2115,7 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
pfvf_map[schq] = TXSCH_MAP(pcifunc, 0);
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
}
}
@@ -2065,9 +2132,121 @@ exit:
return rc;
}
+static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq,
+ struct nix_smq_flush_ctx *smq_flush_ctx)
+{
+ struct nix_smq_tree_ctx *smq_tree_ctx;
+ u64 parent_off, regval;
+ u16 schq;
+ int lvl;
+
+ smq_flush_ctx->smq = smq;
+
+ schq = smq;
+ for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
+ smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
+ if (lvl == NIX_TXSCH_LVL_TL1) {
+ smq_flush_ctx->tl1_schq = schq;
+ smq_tree_ctx->cir_off = NIX_AF_TL1X_CIR(schq);
+ smq_tree_ctx->pir_off = 0;
+ smq_tree_ctx->pir_val = 0;
+ parent_off = 0;
+ } else if (lvl == NIX_TXSCH_LVL_TL2) {
+ smq_flush_ctx->tl2_schq = schq;
+ smq_tree_ctx->cir_off = NIX_AF_TL2X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL2X_PIR(schq);
+ parent_off = NIX_AF_TL2X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_TL3) {
+ smq_tree_ctx->cir_off = NIX_AF_TL3X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL3X_PIR(schq);
+ parent_off = NIX_AF_TL3X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_TL4) {
+ smq_tree_ctx->cir_off = NIX_AF_TL4X_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_TL4X_PIR(schq);
+ parent_off = NIX_AF_TL4X_PARENT(schq);
+ } else if (lvl == NIX_TXSCH_LVL_MDQ) {
+ smq_tree_ctx->cir_off = NIX_AF_MDQX_CIR(schq);
+ smq_tree_ctx->pir_off = NIX_AF_MDQX_PIR(schq);
+ parent_off = NIX_AF_MDQX_PARENT(schq);
+ }
+ /* save cir/pir register values */
+ smq_tree_ctx->cir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->cir_off);
+ if (smq_tree_ctx->pir_off)
+ smq_tree_ctx->pir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->pir_off);
+
+ /* get parent txsch node */
+ if (parent_off) {
+ regval = rvu_read64(rvu, blkaddr, parent_off);
+ schq = (regval >> 16) & 0x1FF;
+ }
+ }
+}
+
+static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr,
+ struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
+{
+ struct nix_txsch *txsch;
+ struct nix_hw *nix_hw;
+ u64 regoff;
+ int tl2;
+
+ nix_hw = get_nix_hw(rvu->hw, blkaddr);
+ if (!nix_hw)
+ return;
+
+ /* loop through all TL2s with matching PF_FUNC */
+ txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2];
+ for (tl2 = 0; tl2 < txsch->schq.max; tl2++) {
+ /* skip the smq(flush) TL2 */
+ if (tl2 == smq_flush_ctx->tl2_schq)
+ continue;
+ /* skip unused TL2s */
+ if (TXSCH_MAP_FLAGS(txsch->pfvf_map[tl2]) & NIX_TXSCHQ_FREE)
+ continue;
+ /* skip if PF_FUNC doesn't match */
+ if ((TXSCH_MAP_FUNC(txsch->pfvf_map[tl2]) & ~RVU_PFVF_FUNC_MASK) !=
+ (TXSCH_MAP_FUNC(txsch->pfvf_map[smq_flush_ctx->tl2_schq] &
+ ~RVU_PFVF_FUNC_MASK)))
+ continue;
+ /* enable/disable XOFF */
+ regoff = NIX_AF_TL2X_SW_XOFF(tl2);
+ if (enable)
+ rvu_write64(rvu, blkaddr, regoff, 0x1);
+ else
+ rvu_write64(rvu, blkaddr, regoff, 0x0);
+ }
+}
+
+static void nix_smq_flush_enadis_rate(struct rvu *rvu, int blkaddr,
+ struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
+{
+ u64 cir_off, pir_off, cir_val, pir_val;
+ struct nix_smq_tree_ctx *smq_tree_ctx;
+ int lvl;
+
+ for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
+ smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
+ cir_off = smq_tree_ctx->cir_off;
+ cir_val = smq_tree_ctx->cir_val;
+ pir_off = smq_tree_ctx->pir_off;
+ pir_val = smq_tree_ctx->pir_val;
+
+ if (enable) {
+ rvu_write64(rvu, blkaddr, cir_off, cir_val);
+ if (lvl != NIX_TXSCH_LVL_TL1)
+ rvu_write64(rvu, blkaddr, pir_off, pir_val);
+ } else {
+ rvu_write64(rvu, blkaddr, cir_off, 0x0);
+ if (lvl != NIX_TXSCH_LVL_TL1)
+ rvu_write64(rvu, blkaddr, pir_off, 0x0);
+ }
+ }
+}
+
static int nix_smq_flush(struct rvu *rvu, int blkaddr,
int smq, u16 pcifunc, int nixlf)
{
+ struct nix_smq_flush_ctx *smq_flush_ctx;
int pf = rvu_get_pf(pcifunc);
u8 cgx_id = 0, lmac_id = 0;
int err, restore_tx_en = 0;
@@ -2087,6 +2266,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
lmac_id, true);
}
+ /* XOFF all TL2s whose parent TL1 matches SMQ tree TL1 */
+ smq_flush_ctx = kzalloc(sizeof(*smq_flush_ctx), GFP_KERNEL);
+ if (!smq_flush_ctx)
+ return -ENOMEM;
+ nix_smq_flush_fill_ctx(rvu, blkaddr, smq, smq_flush_ctx);
+ nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, true);
+ nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, false);
+
cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq));
/* Do SMQ flush and set enqueue xoff */
cfg |= BIT_ULL(50) | BIT_ULL(49);
@@ -2101,8 +2288,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
err = rvu_poll_reg(rvu, blkaddr,
NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true);
if (err)
- dev_err(rvu->dev,
- "NIXLF%d: SMQ%d flush failed\n", nixlf, smq);
+ dev_info(rvu->dev,
+ "NIXLF%d: SMQ%d flush failed, txlink might be busy\n",
+ nixlf, smq);
+
+ /* clear XOFF on TL2s */
+ nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, true);
+ nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, false);
+ kfree(smq_flush_ctx);
rvu_cgx_enadis_rx_bp(rvu, pf, true);
/* restore cgx tx state */
@@ -2144,6 +2337,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
continue;
nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
}
}
nix_clear_tx_xoff(rvu, blkaddr, NIX_TXSCH_LVL_TL1,
@@ -2182,6 +2376,7 @@ static int nix_txschq_free(struct rvu *rvu, u16 pcifunc)
for (schq = 0; schq < txsch->schq.max; schq++) {
if (TXSCH_MAP_FUNC(txsch->pfvf_map[schq]) != pcifunc)
continue;
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
}
@@ -2241,6 +2436,9 @@ static int nix_txschq_free_one(struct rvu *rvu,
*/
nix_clear_tx_xoff(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_linkcfg(rvu, blkaddr, lvl, schq);
+ nix_reset_tx_shaping(rvu, blkaddr, nixlf, lvl, schq);
+
/* Flush if it is a SMQ. Onus of disabling
* TL2/3 queue links before SMQ flush is on user
*/
@@ -2250,6 +2448,8 @@ static int nix_txschq_free_one(struct rvu *rvu,
goto err;
}
+ nix_reset_tx_schedule(rvu, blkaddr, lvl, schq);
+
/* Free the resource */
rvu_free_rsrc(&txsch->schq, schq);
txsch->pfvf_map[schq] = TXSCH_MAP(0, NIX_TXSCHQ_FREE);
@@ -2404,17 +2604,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw,
return 0;
}
-static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr,
- u16 pcifunc, struct nix_txsch *txsch)
+void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
+ struct nix_txsch *txsch, bool enable)
{
struct rvu_hwinfo *hw = rvu->hw;
int lbk_link_start, lbk_links;
u8 pf = rvu_get_pf(pcifunc);
int schq;
+ u64 cfg;
if (!is_pf_cgxmapped(rvu, pf))
return;
+ cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0;
lbk_link_start = hw->cgx_links;
for (schq = 0; schq < txsch->schq.max; schq++) {
@@ -2428,8 +2630,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr,
rvu_write64(rvu, blkaddr,
NIX_AF_TL3_TL2X_LINKX_CFG(schq,
lbk_link_start +
- lbk_links),
- BIT_ULL(12) | RVU_SWITCH_LBK_CHAN);
+ lbk_links), cfg);
}
}
@@ -2535,8 +2736,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu,
rvu_write64(rvu, blkaddr, reg, regval);
}
- rvu_nix_tx_tl2_cfg(rvu, blkaddr, pcifunc,
- &nix_hw->txsch[NIX_TXSCH_LVL_TL2]);
return 0;
}
@@ -3147,10 +3346,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
}
/* Setup a default value of 8192 as DWRR MTU */
- if (rvu->hw->cap.nix_common_dwrr_mtu) {
- rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU,
+ if (rvu->hw->cap.nix_common_dwrr_mtu ||
+ rvu->hw->cap.nix_multiple_dwrr_mtu) {
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM),
convert_bytes_to_dwrr_mtu(8192));
- rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU,
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK),
+ convert_bytes_to_dwrr_mtu(8192));
+ rvu_write64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP),
convert_bytes_to_dwrr_mtu(8192));
}
@@ -3248,19 +3453,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req,
rsp->min_mtu = NIC_HW_MIN_FRS;
- if (!rvu->hw->cap.nix_common_dwrr_mtu) {
+ if (!rvu->hw->cap.nix_common_dwrr_mtu &&
+ !rvu->hw->cap.nix_multiple_dwrr_mtu) {
/* Return '1' on OTx2 */
rsp->rpm_dwrr_mtu = 1;
rsp->sdp_dwrr_mtu = 1;
+ rsp->lbk_dwrr_mtu = 1;
return 0;
}
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU);
+ /* Return DWRR_MTU for TLx_SCHEDULE[RR_WEIGHT] config */
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
- dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU);
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP));
rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
+ dwrr_mtu = rvu_read64(rvu, blkaddr,
+ nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK));
+ rsp->lbk_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
+
return 0;
}
@@ -3309,6 +3523,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
struct nix_rx_flowkey_alg *field;
struct nix_rx_flowkey_alg tmp;
u32 key_type, valid_key;
+ u32 l3_l4_src_dst;
int l4_key_offset = 0;
if (!alg)
@@ -3336,6 +3551,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
* group_member - Enabled when protocol is part of a group.
*/
+ /* Last 4 bits (31:28) are reserved to specify SRC, DST
+ * selection for L3, L4 i.e IPV[4,6]_SRC, IPV[4,6]_DST,
+ * [TCP,UDP,SCTP]_SRC, [TCP,UDP,SCTP]_DST
+ * 31 => L3_SRC, 30 => L3_DST, 29 => L4_SRC, 28 => L4_DST
+ */
+ l3_l4_src_dst = flow_cfg;
+ /* Reset these 4 bits, so that these won't be part of key */
+ flow_cfg &= NIX_FLOW_KEY_TYPE_L3_L4_MASK;
+
keyoff_marker = 0; max_key_off = 0; group_member = 0;
nr_field = 0; key_off = 0; field_marker = 1;
field = &tmp; max_bit_pos = fls(flow_cfg);
@@ -3373,6 +3597,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
}
field->hdr_offset = 12; /* SIP offset */
field->bytesm1 = 7; /* SIP + DIP, 8 bytes */
+
+ /* Only SIP */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
+ field->bytesm1 = 3; /* SIP, 4 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
+ /* Both SIP + DIP */
+ if (field->bytesm1 == 3) {
+ field->bytesm1 = 7; /* SIP + DIP, 8B */
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 16; /* DIP off */
+ field->bytesm1 = 3; /* DIP, 4 bytes */
+ }
+ }
+
field->ltype_mask = 0xF; /* Match only IPv4 */
keyoff_marker = false;
break;
@@ -3386,6 +3626,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
}
field->hdr_offset = 8; /* SIP offset */
field->bytesm1 = 31; /* SIP + DIP, 32 bytes */
+
+ /* Only SIP */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
+ field->bytesm1 = 15; /* SIP, 16 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
+ /* Both SIP + DIP */
+ if (field->bytesm1 == 15) {
+ /* SIP + DIP, 32 bytes */
+ field->bytesm1 = 31;
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 24; /* DIP off */
+ field->bytesm1 = 15; /* DIP,16 bytes */
+ }
+ }
field->ltype_mask = 0xF; /* Match only IPv6 */
break;
case NIX_FLOW_KEY_TYPE_TCP:
@@ -3401,6 +3657,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->lid = NPC_LID_LH;
field->bytesm1 = 3; /* Sport + Dport, 4 bytes */
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_SRC_ONLY)
+ field->bytesm1 = 1; /* SRC, 2 bytes */
+
+ if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_DST_ONLY) {
+ /* Both SRC + DST */
+ if (field->bytesm1 == 1) {
+ /* SRC + DST, 4 bytes */
+ field->bytesm1 = 3;
+ } else {
+ /* Only DIP */
+ field->hdr_offset = 2; /* DST off */
+ field->bytesm1 = 1; /* DST, 2 bytes */
+ }
+ }
+
/* Enum values for NPC_LID_LD and NPC_LID_LG are same,
* so no need to change the ltype_match, just change
* the lid for inner protocols
@@ -3815,21 +4086,14 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
}
/* install/uninstall promisc entry */
- if (promisc) {
+ if (promisc)
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base,
pfvf->rx_chan_cnt);
-
- if (rvu_npc_exact_has_match_table(rvu))
- rvu_npc_exact_promisc_enable(rvu, pcifunc);
- } else {
+ else
if (!nix_rx_multicast)
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
- if (rvu_npc_exact_has_match_table(rvu))
- rvu_npc_exact_promisc_disable(rvu, pcifunc);
- }
-
return 0;
}
@@ -4023,9 +4287,10 @@ rx_frscfg:
if (link < 0)
return NIX_AF_ERR_RX_LINK_INVALID;
- nix_find_link_frs(rvu, req, pcifunc);
linkcfg:
+ nix_find_link_frs(rvu, req, pcifunc);
+
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link));
cfg = (cfg & ~(0xFFFFULL << 16)) | ((u64)req->maxlen << 16);
if (req->update_minlen)
@@ -4069,6 +4334,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
else
cfg &= ~BIT_ULL(40);
+ if (req->len_verify & NIX_RX_DROP_RE)
+ cfg |= BIT_ULL(32);
+ else
+ cfg &= ~BIT_ULL(32);
+
if (req->csum_verify & BIT(0))
cfg |= BIT_ULL(37);
else
@@ -4266,8 +4536,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr)
* Check if HW uses a common MTU for all DWRR quantum configs.
* On OcteonTx2 this register field is '0'.
*/
- if (((hw_const >> 56) & 0x10) == 0x10)
+ if ((((hw_const >> 56) & 0x10) == 0x10) && !(hw_const & BIT_ULL(61)))
hw->cap.nix_common_dwrr_mtu = true;
+
+ if (hw_const & BIT_ULL(61))
+ hw->cap.nix_multiple_dwrr_mtu = true;
}
static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
index 9f11c1e40737..7e20282c12d0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
@@ -218,13 +218,54 @@ void npc_config_secret_key(struct rvu *rvu, int blkaddr)
void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
{
+ struct npc_mcam_kex_hash *mh = rvu->kpu.mkex_hash;
struct hw_cap *hwcap = &rvu->hw->cap;
+ u8 intf, ld, hdr_offset, byte_len;
struct rvu_hwinfo *hw = rvu->hw;
- u8 intf;
+ u64 cfg;
+ /* Check if hardware supports hash extraction */
if (!hwcap->npc_hash_extract)
return;
+ /* Check if IPv6 source/destination address
+ * should be hash enabled.
+ * Hashing reduces 128bit SIP/DIP fields to 32bit
+ * so that 224 bit X2 key can be used for IPv6 based filters as well,
+ * which in turn results in more number of MCAM entries available for
+ * use.
+ *
+ * Hashing of IPV6 SIP/DIP is enabled in below scenarios
+ * 1. If the silicon variant supports hashing feature
+ * 2. If the number of bytes of IP addr being extracted is 4 bytes ie
+ * 32bit. The assumption here is that if user wants 8bytes of LSB of
+ * IP addr or full 16 bytes then his intention is not to use 32bit
+ * hash.
+ */
+ for (intf = 0; intf < hw->npc_intfs; intf++) {
+ for (ld = 0; ld < NPC_MAX_LD; ld++) {
+ cfg = rvu_read64(rvu, blkaddr,
+ NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf,
+ NPC_LID_LC,
+ NPC_LT_LC_IP6,
+ ld));
+ hdr_offset = FIELD_GET(NPC_HDR_OFFSET, cfg);
+ byte_len = FIELD_GET(NPC_BYTESM, cfg);
+ /* Hashing of IPv6 source/destination address should be
+ * enabled if,
+ * hdr_offset == 8 (offset of source IPv6 address) or
+ * hdr_offset == 24 (offset of destination IPv6)
+ * address) and the number of byte to be
+ * extracted is 4. As per hardware configuration
+ * byte_len should be == actual byte_len - 1.
+ * Hence byte_len is checked against 3 but nor 4.
+ */
+ if ((hdr_offset == 8 || hdr_offset == 24) && byte_len == 3)
+ mh->lid_lt_ld_hash_en[intf][NPC_LID_LC][NPC_LT_LC_IP6][ld] = true;
+ }
+ }
+
+ /* Update hash configuration if the field is hash enabled */
for (intf = 0; intf < hw->npc_intfs; intf++) {
npc_program_mkex_hash_rx(rvu, blkaddr, intf);
npc_program_mkex_hash_tx(rvu, blkaddr, intf);
@@ -1164,8 +1205,10 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
{
struct npc_exact_table *table;
u16 *cnt, old_cnt;
+ bool promisc;
table = rvu->hw->table;
+ promisc = table->promisc_mode[drop_mcam_idx];
cnt = &table->cnt_cmd_rules[drop_mcam_idx];
old_cnt = *cnt;
@@ -1177,13 +1220,18 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
*enable_or_disable_cam = false;
- /* If all rules are deleted, disable cam */
+ if (promisc)
+ goto done;
+
+ /* If all rules are deleted and not already in promisc mode;
+ * disable cam
+ */
if (!*cnt && val < 0) {
*enable_or_disable_cam = true;
goto done;
}
- /* If rule got added, enable cam */
+ /* If rule got added and not already in promisc mode; enable cam */
if (!old_cnt && val > 0) {
*enable_or_disable_cam = true;
goto done;
@@ -1462,6 +1510,12 @@ int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc)
*promisc = false;
mutex_unlock(&table->lock);
+ /* Enable drop rule */
+ rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+ true);
+
+ dev_dbg(rvu->dev, "%s: disabled promisc mode (cgx=%d lmac=%d)\n",
+ __func__, cgx_id, lmac_id);
return 0;
}
@@ -1503,6 +1557,12 @@ int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc)
*promisc = true;
mutex_unlock(&table->lock);
+ /* disable drop rule */
+ rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+ false);
+
+ dev_dbg(rvu->dev, "%s: Enabled promisc mode (cgx=%d lmac=%d)\n",
+ __func__, cgx_id, lmac_id);
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
index a1c3d987b804..57a09328d46b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
@@ -70,8 +70,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
[NIX_INTF_RX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
- true,
- true,
+ false,
+ false,
},
},
},
@@ -79,8 +79,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
[NIX_INTF_TX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
- true,
- true,
+ false,
+ false,
},
},
},
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
index 7007f0b8e659..b42e631e52d0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
@@ -272,7 +272,8 @@
#define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3)
#define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16)
#define NIX_AF_SQM_DBG_CTL_STATUS (0x750)
-#define NIX_AF_DWRR_SDP_MTU (0x790)
+#define NIX_AF_DWRR_SDP_MTU (0x790) /* All CN10K except CN10KB */
+#define NIX_AF_DWRR_MTUX(a) (0x790 | (a) << 16) /* Only for CN10KB */
#define NIX_AF_DWRR_RPM_MTU (0x7A0)
#define NIX_AF_PSE_CHANNEL_LEVEL (0x800)
#define NIX_AF_PSE_SHAPER_CFG (0x810)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
index 3392487f6b47..592b317f4637 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
@@ -8,6 +8,17 @@
#include <linux/bitfield.h>
#include "rvu.h"
+static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
+{
+ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+ struct nix_hw *nix_hw;
+
+ nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);
+ /* Enable LBK links with channel 63 for TX MCAM rule */
+ rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,
+ &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);
+}
+
static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
u16 chan_mask)
{
@@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
return 0;
+ rvu_switch_enable_lbk_link(rvu, pcifunc, true);
+
lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
eth_broadcast_addr((u8 *)&req.mask.dmac);
@@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu)
"Reverting RX rule for PF%d failed(%d)\n",
pf, err);
+ /* Disable LBK link */
+ rvu_switch_enable_lbk_link(rvu, pcifunc, false);
+
rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
for (vf = 0; vf < numvfs; vf++) {
pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
@@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu)
dev_err(rvu->dev,
"Reverting RX rule for PF%dVF%d failed(%d)\n",
pf, vf, err);
+
+ rvu_switch_enable_lbk_link(rvu, pcifunc, false);
}
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index 73fdb8798614..5664f768cb0c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -8,7 +8,7 @@ obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o
rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
- otx2_devlink.o
+ otx2_devlink.o qos_sq.o qos.o
rvu_nicvf-y := otx2_vf.o otx2_devlink.o
rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
index 826f691de259..a4a258da8dd5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
@@ -107,12 +107,13 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
}
#define NPA_MAX_BURST 16
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
{
struct otx2_nic *pfvf = dev;
+ int cnt = cq->pool_ptrs;
u64 ptrs[NPA_MAX_BURST];
- int num_ptrs = 1;
dma_addr_t bufptr;
+ int num_ptrs = 1;
/* Refill pool with new buffers */
while (cq->pool_ptrs) {
@@ -131,6 +132,7 @@ void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
num_ptrs = 1;
}
}
+ return cnt - cq->pool_ptrs;
}
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
index 8ae96815865e..c1861f7de254 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.h
@@ -24,7 +24,7 @@ static inline int mtu_to_dwrr_weight(struct otx2_nic *pfvf, int mtu)
return weight;
}
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq, int size, int qidx);
int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int cn10k_lmtst_init(struct otx2_nic *pfvf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
index a487a98eac88..59b138214af2 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
@@ -4,9 +4,9 @@
* Copyright (C) 2022 Marvell.
*/
+#include <crypto/skcipher.h>
#include <linux/rtnetlink.h>
#include <linux/bitfield.h>
-#include <net/macsec.h>
#include "otx2_common.h"
#define MCS_TCAM0_MAC_DA_MASK GENMASK_ULL(47, 0)
@@ -43,6 +43,56 @@
#define MCS_TCI_E 0x08 /* encryption */
#define MCS_TCI_C 0x04 /* changed text */
+#define CN10K_MAX_HASH_LEN 16
+#define CN10K_MAX_SAK_LEN 32
+
+static int cn10k_ecb_aes_encrypt(struct otx2_nic *pfvf, u8 *sak,
+ u16 sak_len, u8 *hash)
+{
+ u8 data[CN10K_MAX_HASH_LEN] = { 0 };
+ struct skcipher_request *req = NULL;
+ struct scatterlist sg_src, sg_dst;
+ struct crypto_skcipher *tfm;
+ DECLARE_CRYPTO_WAIT(wait);
+ int err;
+
+ tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ dev_err(pfvf->dev, "failed to allocate transform for ecb-aes\n");
+ return PTR_ERR(tfm);
+ }
+
+ req = skcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ dev_err(pfvf->dev, "failed to allocate request for skcipher\n");
+ err = -ENOMEM;
+ goto free_tfm;
+ }
+
+ err = crypto_skcipher_setkey(tfm, sak, sak_len);
+ if (err) {
+ dev_err(pfvf->dev, "failed to set key for skcipher\n");
+ goto free_req;
+ }
+
+ /* build sg list */
+ sg_init_one(&sg_src, data, CN10K_MAX_HASH_LEN);
+ sg_init_one(&sg_dst, hash, CN10K_MAX_HASH_LEN);
+
+ skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
+ skcipher_request_set_crypt(req, &sg_src, &sg_dst,
+ CN10K_MAX_HASH_LEN, NULL);
+
+ err = crypto_skcipher_encrypt(req);
+ err = crypto_wait_req(err, &wait);
+
+free_req:
+ skcipher_request_free(req);
+free_tfm:
+ crypto_free_skcipher(tfm);
+ return err;
+}
+
static struct cn10k_mcs_txsc *cn10k_mcs_get_txsc(struct cn10k_mcs_cfg *cfg,
struct macsec_secy *secy)
{
@@ -212,6 +262,7 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf,
struct mcs_secy_plcy_write_req *req;
struct mbox *mbox = &pfvf->mbox;
u64 policy;
+ u8 cipher;
int ret;
mutex_lock(&mbox->lock);
@@ -227,7 +278,21 @@ static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf,
policy |= MCS_RX_SECY_PLCY_RP;
policy |= MCS_RX_SECY_PLCY_AUTH_ENA;
- policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, MCS_GCM_AES_128);
+
+ switch (secy->key_len) {
+ case 16:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
+ break;
+ case 32:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
+ break;
+ default:
+ cipher = MCS_GCM_AES_128;
+ dev_warn(pfvf->dev, "Unsupported key length\n");
+ break;
+ }
+
+ policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, cipher);
policy |= FIELD_PREP(MCS_RX_SECY_PLCY_VAL, secy->validate_frames);
policy |= MCS_RX_SECY_PLCY_ENA;
@@ -316,16 +381,53 @@ fail:
return ret;
}
+static int cn10k_mcs_write_keys(struct otx2_nic *pfvf,
+ struct macsec_secy *secy,
+ struct mcs_sa_plcy_write_req *req,
+ u8 *sak, u8 *salt, ssci_t ssci)
+{
+ u8 hash_rev[CN10K_MAX_HASH_LEN];
+ u8 sak_rev[CN10K_MAX_SAK_LEN];
+ u8 salt_rev[MACSEC_SALT_LEN];
+ u8 hash[CN10K_MAX_HASH_LEN];
+ u32 ssci_63_32;
+ int err, i;
+
+ err = cn10k_ecb_aes_encrypt(pfvf, sak, secy->key_len, hash);
+ if (err) {
+ dev_err(pfvf->dev, "Generating hash using ECB(AES) failed\n");
+ return err;
+ }
+
+ for (i = 0; i < secy->key_len; i++)
+ sak_rev[i] = sak[secy->key_len - 1 - i];
+
+ for (i = 0; i < CN10K_MAX_HASH_LEN; i++)
+ hash_rev[i] = hash[CN10K_MAX_HASH_LEN - 1 - i];
+
+ for (i = 0; i < MACSEC_SALT_LEN; i++)
+ salt_rev[i] = salt[MACSEC_SALT_LEN - 1 - i];
+
+ ssci_63_32 = (__force u32)cpu_to_be32((__force u32)ssci);
+
+ memcpy(&req->plcy[0][0], sak_rev, secy->key_len);
+ memcpy(&req->plcy[0][4], hash_rev, CN10K_MAX_HASH_LEN);
+ memcpy(&req->plcy[0][6], salt_rev, MACSEC_SALT_LEN);
+ req->plcy[0][7] |= (u64)ssci_63_32 << 32;
+
+ return 0;
+}
+
static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
struct macsec_secy *secy,
struct cn10k_mcs_rxsc *rxsc,
u8 assoc_num, bool sa_in_use)
{
- unsigned char *src = rxsc->sa_key[assoc_num];
struct mcs_sa_plcy_write_req *plcy_req;
+ u8 *sak = rxsc->sa_key[assoc_num];
+ u8 *salt = rxsc->salt[assoc_num];
struct mcs_rx_sc_sa_map *map_req;
struct mbox *mbox = &pfvf->mbox;
- u8 reg, key_len;
int ret;
mutex_lock(&mbox->lock);
@@ -343,11 +445,10 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
goto fail;
}
- for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
- memcpy((u8 *)&plcy_req->plcy[0][reg],
- (src + reg * 8), 8);
- reg++;
- }
+ ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+ salt, rxsc->ssci[assoc_num]);
+ if (ret)
+ goto fail;
plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num];
plcy_req->sa_cnt = 1;
@@ -400,12 +501,16 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
struct mcs_secy_plcy_write_req *req;
struct mbox *mbox = &pfvf->mbox;
struct macsec_tx_sc *sw_tx_sc;
- /* Insert SecTag after 12 bytes (DA+SA)*/
- u8 tag_offset = 12;
u8 sectag_tci = 0;
+ u8 tag_offset;
u64 policy;
+ u8 cipher;
int ret;
+ /* Insert SecTag after 12 bytes (DA+SA) or 16 bytes
+ * if VLAN tag needs to be sent in clear text.
+ */
+ tag_offset = txsc->vlan_dev ? 16 : 12;
sw_tx_sc = &secy->tx_sc;
mutex_lock(&mbox->lock);
@@ -434,7 +539,21 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset);
policy |= MCS_TX_SECY_PLCY_INS_MODE;
policy |= MCS_TX_SECY_PLCY_AUTH_ENA;
- policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, MCS_GCM_AES_128);
+
+ switch (secy->key_len) {
+ case 16:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
+ break;
+ case 32:
+ cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
+ break;
+ default:
+ cipher = MCS_GCM_AES_128;
+ dev_warn(pfvf->dev, "Unsupported key length\n");
+ break;
+ }
+
+ policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, cipher);
if (secy->protect_frames)
policy |= MCS_TX_SECY_PLCY_PROTECT;
@@ -542,10 +661,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
struct cn10k_mcs_txsc *txsc,
u8 assoc_num)
{
- unsigned char *src = txsc->sa_key[assoc_num];
struct mcs_sa_plcy_write_req *plcy_req;
+ u8 *sak = txsc->sa_key[assoc_num];
+ u8 *salt = txsc->salt[assoc_num];
struct mbox *mbox = &pfvf->mbox;
- u8 reg, key_len;
int ret;
mutex_lock(&mbox->lock);
@@ -556,10 +675,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
goto fail;
}
- for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
- memcpy((u8 *)&plcy_req->plcy[0][reg], (src + reg * 8), 8);
- reg++;
- }
+ ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+ salt, txsc->ssci[assoc_num]);
+ if (ret)
+ goto fail;
plcy_req->plcy[0][8] = assoc_num;
plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num];
@@ -922,8 +1041,7 @@ static int cn10k_mcs_secy_tx_cfg(struct otx2_nic *pfvf, struct macsec_secy *secy
{
if (sw_tx_sa) {
cn10k_mcs_write_tx_sa_plcy(pfvf, secy, txsc, sa_num);
- cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, sw_tx_sa->next_pn);
cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, sa_num,
sw_tx_sa->active);
}
@@ -959,7 +1077,7 @@ static int cn10k_mcs_secy_rx_cfg(struct otx2_nic *pfvf,
cn10k_mcs_write_rx_sa_plcy(pfvf, secy, mcs_rx_sc,
sa_num, sw_rx_sa->active);
cn10k_mcs_write_rx_sa_pn(pfvf, mcs_rx_sc, sa_num,
- sw_rx_sa->next_pn_halves.lower);
+ sw_rx_sa->next_pn);
}
cn10k_mcs_write_rx_flowid(pfvf, mcs_rx_sc, hw_secy_id);
@@ -1053,7 +1171,7 @@ static void cn10k_mcs_sync_stats(struct otx2_nic *pfvf, struct macsec_secy *secy
static int cn10k_mdo_open(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct macsec_tx_sa *sw_tx_sa;
@@ -1077,7 +1195,7 @@ static int cn10k_mdo_open(struct macsec_context *ctx)
static int cn10k_mdo_stop(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_txsc *txsc;
int err;
@@ -1095,7 +1213,7 @@ static int cn10k_mdo_stop(struct macsec_context *ctx)
static int cn10k_mdo_add_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_txsc *txsc;
@@ -1103,13 +1221,6 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
return -EOPNOTSUPP;
- /* Stick to 16 bytes key len until XPN support is added */
- if (secy->key_len != 16)
- return -EOPNOTSUPP;
-
- if (secy->xpn)
- return -EOPNOTSUPP;
-
txsc = cn10k_mcs_create_txsc(pfvf);
if (IS_ERR(txsc))
return -ENOSPC;
@@ -1118,6 +1229,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
txsc->encoding_sa = secy->tx_sc.encoding_sa;
txsc->last_validate_frames = secy->validate_frames;
txsc->last_replay_protect = secy->replay_protect;
+ txsc->vlan_dev = is_vlan_dev(ctx->netdev);
list_add(&txsc->entry, &cfg->txsc_list);
@@ -1129,7 +1241,7 @@ static int cn10k_mdo_add_secy(struct macsec_context *ctx)
static int cn10k_mdo_upd_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct macsec_tx_sa *sw_tx_sa;
@@ -1164,7 +1276,7 @@ static int cn10k_mdo_upd_secy(struct macsec_context *ctx)
static int cn10k_mdo_del_secy(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_txsc *txsc;
@@ -1183,7 +1295,7 @@ static int cn10k_mdo_del_secy(struct macsec_context *ctx)
static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
@@ -1202,6 +1314,9 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
return -ENOSPC;
memcpy(&txsc->sa_key[sa_num], ctx->sa.key, secy->key_len);
+ memcpy(&txsc->salt[sa_num], sw_tx_sa->key.salt.bytes, MACSEC_SALT_LEN);
+ txsc->ssci[sa_num] = sw_tx_sa->ssci;
+
txsc->sa_bmap |= 1 << sa_num;
if (netif_running(secy->netdev)) {
@@ -1210,7 +1325,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
return err;
err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ sw_tx_sa->next_pn);
if (err)
return err;
@@ -1225,7 +1340,7 @@ static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
@@ -1243,7 +1358,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
if (netif_running(secy->netdev)) {
/* Keys cannot be changed after creation */
err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
- sw_tx_sa->next_pn_halves.lower);
+ sw_tx_sa->next_pn);
if (err)
return err;
@@ -1258,7 +1373,7 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
static int cn10k_mdo_del_txsa(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
u8 sa_num = ctx->sa.assoc_num;
struct cn10k_mcs_txsc *txsc;
@@ -1278,7 +1393,7 @@ static int cn10k_mdo_del_txsa(struct macsec_context *ctx)
static int cn10k_mdo_add_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_rxsc *rxsc;
@@ -1312,7 +1427,7 @@ static int cn10k_mdo_add_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
bool enable = ctx->rx_sc->active;
@@ -1331,7 +1446,7 @@ static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_del_rxsc(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct cn10k_mcs_rxsc *rxsc;
@@ -1349,11 +1464,10 @@ static int cn10k_mdo_del_rxsc(struct macsec_context *ctx)
static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
- u64 next_pn = rx_sa->next_pn_halves.lower;
struct macsec_secy *secy = ctx->secy;
bool sa_in_use = rx_sa->active;
u8 sa_num = ctx->sa.assoc_num;
@@ -1371,6 +1485,9 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
return -ENOSPC;
memcpy(&rxsc->sa_key[sa_num], ctx->sa.key, ctx->secy->key_len);
+ memcpy(&rxsc->salt[sa_num], rx_sa->key.salt.bytes, MACSEC_SALT_LEN);
+ rxsc->ssci[sa_num] = rx_sa->ssci;
+
rxsc->sa_bmap |= 1 << sa_num;
if (netif_running(secy->netdev)) {
@@ -1379,7 +1496,8 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
if (err)
return err;
- err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn);
+ err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
+ rx_sa->next_pn);
if (err)
return err;
}
@@ -1389,11 +1507,10 @@ static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
- u64 next_pn = rx_sa->next_pn_halves.lower;
struct macsec_secy *secy = ctx->secy;
bool sa_in_use = rx_sa->active;
u8 sa_num = ctx->sa.assoc_num;
@@ -1412,7 +1529,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
if (err)
return err;
- err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, next_pn);
+ err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
+ rx_sa->next_pn);
if (err)
return err;
}
@@ -1422,8 +1540,8 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_del_rxsa(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
u8 sa_num = ctx->sa.assoc_num;
struct cn10k_mcs_rxsc *rxsc;
@@ -1445,8 +1563,8 @@ static int cn10k_mdo_del_rxsa(struct macsec_context *ctx)
static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct mcs_secy_stats tx_rsp = { 0 }, rx_rsp = { 0 };
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct cn10k_mcs_txsc *txsc;
@@ -1481,7 +1599,7 @@ static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sc_stats rsp = { 0 };
struct cn10k_mcs_txsc *txsc;
@@ -1502,7 +1620,7 @@ static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sa_stats rsp = { 0 };
u8 sa_num = ctx->sa.assoc_num;
@@ -1525,7 +1643,7 @@ static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx)
{
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct macsec_secy *secy = ctx->secy;
struct mcs_sc_stats rsp = { 0 };
@@ -1567,8 +1685,8 @@ static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx)
static int cn10k_mdo_get_rx_sa_stats(struct macsec_context *ctx)
{
+ struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
- struct otx2_nic *pfvf = netdev_priv(ctx->netdev);
struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
struct mcs_sa_stats rsp = { 0 };
u8 sa_num = ctx->sa.assoc_num;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 8a41ad8ca04f..20ecc90d203e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <net/tso.h>
+#include <linux/bitfield.h>
#include "otx2_reg.h"
#include "otx2_common.h"
@@ -89,6 +90,11 @@ int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx)
if (!pfvf->qset.sq)
return 0;
+ if (qidx >= pfvf->hw.non_qos_queues) {
+ if (!test_bit(qidx - pfvf->hw.non_qos_queues, pfvf->qos.qos_sq_bmap))
+ return 0;
+ }
+
otx2_nix_sq_op_stats(&sq->stats, pfvf, qidx);
return 1;
}
@@ -513,11 +519,32 @@ void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
(pfvf->hw.cq_ecount_wait - 1));
}
-int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma)
+static int otx2_alloc_pool_buf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
+{
+ unsigned int offset = 0;
+ struct page *page;
+ size_t sz;
+
+ sz = SKB_DATA_ALIGN(pool->rbsize);
+ sz = ALIGN(sz, OTX2_ALIGN);
+
+ page = page_pool_alloc_frag(pool->page_pool, &offset, sz, GFP_ATOMIC);
+ if (unlikely(!page))
+ return -ENOMEM;
+
+ *dma = page_pool_get_dma_addr(page) + offset;
+ return 0;
+}
+
+static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
{
u8 *buf;
+ if (pool->page_pool)
+ return otx2_alloc_pool_buf(pfvf, pool, dma);
+
buf = napi_alloc_frag_align(pool->rbsize, OTX2_ALIGN);
if (unlikely(!buf))
return -ENOMEM;
@@ -532,8 +559,8 @@ int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
return 0;
}
-static int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma)
+int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma)
{
int ret;
@@ -546,20 +573,8 @@ static int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
dma_addr_t *dma)
{
- if (unlikely(__otx2_alloc_rbuf(pfvf, cq->rbpool, dma))) {
- struct refill_work *work;
- struct delayed_work *dwork;
-
- work = &pfvf->refill_wrk[cq->cq_idx];
- dwork = &work->pool_refill_work;
- /* Schedule a task if no other task is running */
- if (!cq->refill_task_sched) {
- cq->refill_task_sched = true;
- schedule_delayed_work(dwork,
- msecs_to_jiffies(100));
- }
+ if (unlikely(__otx2_alloc_rbuf(pfvf, cq->rbpool, dma)))
return -ENOMEM;
- }
return 0;
}
@@ -616,6 +631,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU;
req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) |
(0x2ULL << 36);
+ /* Set link type for DWRR MTU selection on CN10K silicons */
+ if (!is_dev_otx2(pfvf->pdev))
+ req->regval[0] |= FIELD_PREP(GENMASK_ULL(58, 57),
+ (u64)hw->smq_link_type);
req->num_regs++;
/* MDQ config */
parent = schq_list[NIX_TXSCH_LVL_TL4][prio];
@@ -716,7 +735,8 @@ EXPORT_SYMBOL(otx2_smq_flush);
int otx2_txsch_alloc(struct otx2_nic *pfvf)
{
struct nix_txsch_alloc_req *req;
- int lvl;
+ struct nix_txsch_alloc_rsp *rsp;
+ int lvl, schq, rc;
/* Get memory to put this msg */
req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
@@ -726,43 +746,84 @@ int otx2_txsch_alloc(struct otx2_nic *pfvf)
/* Request one schq per level */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
req->schq[lvl] = 1;
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (rc)
+ return rc;
- return otx2_sync_mbox_msg(&pfvf->mbox);
+ rsp = (struct nix_txsch_alloc_rsp *)
+ otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+ if (IS_ERR(rsp))
+ return PTR_ERR(rsp);
+
+ /* Setup transmit scheduler list */
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+ for (schq = 0; schq < rsp->schq[lvl]; schq++)
+ pfvf->hw.txschq_list[lvl][schq] =
+ rsp->schq_list[lvl][schq];
+
+ pfvf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
+
+ return 0;
}
-int otx2_txschq_stop(struct otx2_nic *pfvf)
+void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq)
{
struct nix_txsch_free_req *free_req;
- int lvl, schq, err;
+ int err;
mutex_lock(&pfvf->mbox.lock);
- /* Free the transmit schedulers */
+
free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox);
if (!free_req) {
mutex_unlock(&pfvf->mbox.lock);
- return -ENOMEM;
+ netdev_err(pfvf->netdev,
+ "Failed alloc txschq free req\n");
+ return;
}
- free_req->flags = TXSCHQ_FREE_ALL;
+ free_req->schq_lvl = lvl;
+ free_req->schq = schq;
+
err = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed stop txschq %d at level %d\n", schq, lvl);
+ }
+
mutex_unlock(&pfvf->mbox.lock);
+}
+EXPORT_SYMBOL(otx2_txschq_free_one);
+
+void otx2_txschq_stop(struct otx2_nic *pfvf)
+{
+ int lvl, schq;
+
+ /* free non QOS TLx nodes */
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+ otx2_txschq_free_one(pfvf, lvl,
+ pfvf->hw.txschq_list[lvl][0]);
/* Clear the txschq list */
for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
for (schq = 0; schq < MAX_TXSCHQ_PER_FUNC; schq++)
pfvf->hw.txschq_list[lvl][schq] = 0;
}
- return err;
+
}
void otx2_sqb_flush(struct otx2_nic *pfvf)
{
int qidx, sqe_tail, sqe_head;
+ struct otx2_snd_queue *sq;
u64 incr, *ptr, val;
int timeout = 1000;
ptr = (u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
- for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
+ sq = &pfvf->qset.sq[qidx];
+ if (!sq->sqb_ptrs)
+ continue;
+
incr = (u64)qidx << 32;
while (timeout) {
val = otx2_atomic64_add(incr, ptr);
@@ -862,7 +923,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
return otx2_sync_mbox_msg(&pfvf->mbox);
}
-static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
+int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
{
struct otx2_qset *qset = &pfvf->qset;
struct otx2_snd_queue *sq;
@@ -935,9 +996,17 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
cq->cint_idx = qidx - pfvf->hw.rx_queues;
cq->cqe_cnt = qset->sqe_cnt;
} else {
- cq->cq_type = CQ_XDP;
- cq->cint_idx = qidx - non_xdp_queues;
- cq->cqe_cnt = qset->sqe_cnt;
+ if (pfvf->hw.xdp_queues &&
+ qidx < non_xdp_queues + pfvf->hw.xdp_queues) {
+ cq->cq_type = CQ_XDP;
+ cq->cint_idx = qidx - non_xdp_queues;
+ cq->cqe_cnt = qset->sqe_cnt;
+ } else {
+ cq->cq_type = CQ_QOS;
+ cq->cint_idx = qidx - non_xdp_queues -
+ pfvf->hw.xdp_queues;
+ cq->cqe_cnt = qset->sqe_cnt;
+ }
}
cq->cqe_size = pfvf->qset.xqe_size;
@@ -999,39 +1068,20 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
static void otx2_pool_refill_task(struct work_struct *work)
{
struct otx2_cq_queue *cq;
- struct otx2_pool *rbpool;
struct refill_work *wrk;
- int qidx, free_ptrs = 0;
struct otx2_nic *pfvf;
- dma_addr_t bufptr;
+ int qidx;
wrk = container_of(work, struct refill_work, pool_refill_work.work);
pfvf = wrk->pf;
qidx = wrk - pfvf->refill_wrk;
cq = &pfvf->qset.cq[qidx];
- rbpool = cq->rbpool;
- free_ptrs = cq->pool_ptrs;
- while (cq->pool_ptrs) {
- if (otx2_alloc_rbuf(pfvf, rbpool, &bufptr)) {
- /* Schedule a WQ if we fails to free atleast half of the
- * pointers else enable napi for this RQ.
- */
- if (!((free_ptrs - cq->pool_ptrs) > free_ptrs / 2)) {
- struct delayed_work *dwork;
-
- dwork = &wrk->pool_refill_work;
- schedule_delayed_work(dwork,
- msecs_to_jiffies(100));
- } else {
- cq->refill_task_sched = false;
- }
- return;
- }
- pfvf->hw_ops->aura_freeptr(pfvf, qidx, bufptr + OTX2_HEAD_ROOM);
- cq->pool_ptrs--;
- }
cq->refill_task_sched = false;
+
+ local_bh_disable();
+ napi_schedule(wrk->napi);
+ local_bh_enable();
}
int otx2_config_nix_queues(struct otx2_nic *pfvf)
@@ -1048,7 +1098,7 @@ int otx2_config_nix_queues(struct otx2_nic *pfvf)
}
/* Initialize TX queues */
- for (qidx = 0; qidx < pfvf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < pfvf->hw.non_qos_queues; qidx++) {
u16 sqb_aura = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
err = otx2_sq_init(pfvf, qidx, sqb_aura);
@@ -1095,7 +1145,7 @@ int otx2_config_nix(struct otx2_nic *pfvf)
/* Set RQ/SQ/CQ counts */
nixlf->rq_cnt = pfvf->hw.rx_queues;
- nixlf->sq_cnt = pfvf->hw.tot_tx_queues;
+ nixlf->sq_cnt = otx2_get_total_tx_queues(pfvf);
nixlf->cq_cnt = pfvf->qset.cq_cnt;
nixlf->rss_sz = MAX_RSS_INDIR_TBL_SIZE;
nixlf->rss_grps = MAX_RSS_GROUPS;
@@ -1133,7 +1183,7 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
int sqb, qidx;
u64 iova, pa;
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
sq = &qset->sq[qidx];
if (!sq->sqb_ptrs)
continue;
@@ -1151,10 +1201,31 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
}
}
+void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ u64 iova, int size)
+{
+ struct page *page;
+ u64 pa;
+
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ page = virt_to_head_page(phys_to_virt(pa));
+
+ if (pool->page_pool) {
+ page_pool_put_full_page(pool->page_pool, page, true);
+ } else {
+ dma_unmap_page_attrs(pfvf->dev, iova, size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+
+ put_page(page);
+ }
+}
+
void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
{
int pool_id, pool_start = 0, pool_end = 0, size = 0;
- u64 iova, pa;
+ struct otx2_pool *pool;
+ u64 iova;
if (type == AURA_NIX_SQ) {
pool_start = otx2_get_pool_idx(pfvf, type, 0);
@@ -1170,15 +1241,13 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type)
/* Free SQB and RQB pointers from the aura pool */
for (pool_id = pool_start; pool_id < pool_end; pool_id++) {
iova = otx2_aura_allocptr(pfvf, pool_id);
+ pool = &pfvf->qset.pool[pool_id];
while (iova) {
if (type == AURA_NIX_RQ)
iova -= OTX2_HEAD_ROOM;
- pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
- dma_unmap_page_attrs(pfvf->dev, iova, size,
- DMA_FROM_DEVICE,
- DMA_ATTR_SKIP_CPU_SYNC);
- put_page(virt_to_page(phys_to_virt(pa)));
+ otx2_free_bufs(pfvf, pool, iova, size);
+
iova = otx2_aura_allocptr(pfvf, pool_id);
}
}
@@ -1196,13 +1265,15 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf)
pool = &pfvf->qset.pool[pool_id];
qmem_free(pfvf->dev, pool->stack);
qmem_free(pfvf->dev, pool->fc_addr);
+ page_pool_destroy(pool->page_pool);
+ pool->page_pool = NULL;
}
devm_kfree(pfvf->dev, pfvf->qset.pool);
pfvf->qset.pool = NULL;
}
-static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
- int pool_id, int numptrs)
+int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
+ int pool_id, int numptrs)
{
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
@@ -1278,9 +1349,10 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
return 0;
}
-static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
- int stack_pages, int numptrs, int buf_size)
+int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
+ int stack_pages, int numptrs, int buf_size, int type)
{
+ struct page_pool_params pp_params = { 0 };
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
int err;
@@ -1324,6 +1396,22 @@ static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
aq->ctype = NPA_AQ_CTYPE_POOL;
aq->op = NPA_AQ_INSTOP_INIT;
+ if (type != AURA_NIX_RQ) {
+ pool->page_pool = NULL;
+ return 0;
+ }
+
+ pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP;
+ pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs);
+ pp_params.nid = NUMA_NO_NODE;
+ pp_params.dev = pfvf->dev;
+ pp_params.dma_dir = DMA_FROM_DEVICE;
+ pool->page_pool = page_pool_create(&pp_params);
+ if (IS_ERR(pool->page_pool)) {
+ netdev_err(pfvf->netdev, "Creation of page pool failed\n");
+ return PTR_ERR(pool->page_pool);
+ }
+
return 0;
}
@@ -1349,7 +1437,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
stack_pages =
(num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs;
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < hw->non_qos_queues; qidx++) {
pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
/* Initialize aura context */
err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs);
@@ -1358,7 +1446,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
/* Initialize pool context */
err = otx2_pool_init(pfvf, pool_id, stack_pages,
- num_sqbs, hw->sqb_size);
+ num_sqbs, hw->sqb_size, AURA_NIX_SQ);
if (err)
goto fail;
}
@@ -1369,7 +1457,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf)
goto fail;
/* Allocate pointers and free them to aura/pool */
- for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < hw->non_qos_queues; qidx++) {
pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
pool = &pfvf->qset.pool[pool_id];
@@ -1421,7 +1509,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf)
}
for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) {
err = otx2_pool_init(pfvf, pool_id, stack_pages,
- num_ptrs, pfvf->rbsize);
+ num_ptrs, pfvf->rbsize, AURA_NIX_RQ);
if (err)
goto fail;
}
@@ -1605,7 +1693,6 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable)
req->bpid_per_chan = 0;
#endif
-
return otx2_sync_mbox_msg(&pfvf->mbox);
}
EXPORT_SYMBOL(otx2_nix_config_bp);
@@ -1629,21 +1716,6 @@ void mbox_handler_cgx_fec_stats(struct otx2_nic *pfvf,
pfvf->hw.cgx_fec_uncorr_blks += rsp->fec_uncorr_blks;
}
-void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
- struct nix_txsch_alloc_rsp *rsp)
-{
- int lvl, schq;
-
- /* Setup transmit scheduler list */
- for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++)
- for (schq = 0; schq < rsp->schq[lvl]; schq++)
- pf->hw.txschq_list[lvl][schq] =
- rsp->schq_list[lvl][schq];
-
- pf->hw.txschq_link_cfg_lvl = rsp->link_cfg_lvl;
-}
-EXPORT_SYMBOL(mbox_handler_nix_txsch_alloc);
-
void mbox_handler_npa_lf_alloc(struct otx2_nic *pfvf,
struct npa_lf_alloc_rsp *rsp)
{
@@ -1727,6 +1799,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf)
}
}
+static u32 get_dwrr_mtu(struct otx2_nic *pfvf, struct nix_hw_info *hw)
+{
+ if (is_otx2_lbkvf(pfvf->pdev)) {
+ pfvf->hw.smq_link_type = SMQ_LINK_TYPE_LBK;
+ return hw->lbk_dwrr_mtu;
+ }
+
+ pfvf->hw.smq_link_type = SMQ_LINK_TYPE_RPM;
+ return hw->rpm_dwrr_mtu;
+}
+
u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
{
struct nix_hw_info *rsp;
@@ -1756,7 +1839,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN;
/* Also save DWRR MTU, needed for DWRR weight calculation */
- pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu;
+ pfvf->hw.dwrr_mtu = get_dwrr_mtu(pfvf, rsp);
if (!pfvf->hw.dwrr_mtu)
pfvf->hw.dwrr_mtu = 1;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 0c8fc66ade82..0e81849db353 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -15,6 +15,7 @@
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#include <linux/soc/marvell/octeontx2/asm.h>
+#include <net/macsec.h>
#include <net/pkt_cls.h>
#include <net/devlink.h>
#include <linux/time64.h>
@@ -27,6 +28,7 @@
#include "otx2_txrx.h"
#include "otx2_devlink.h"
#include <rvu_trace.h>
+#include "qos.h"
/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
@@ -183,13 +185,29 @@ struct mbox {
int up_num_msgs; /* mbox_up number of messages */
};
+/* Egress rate limiting definitions */
+#define MAX_BURST_EXPONENT 0x0FULL
+#define MAX_BURST_MANTISSA 0xFFULL
+#define MAX_BURST_SIZE 130816ULL
+#define MAX_RATE_DIVIDER_EXPONENT 12ULL
+#define MAX_RATE_EXPONENT 0x0FULL
+#define MAX_RATE_MANTISSA 0xFFULL
+
+/* Bitfields in NIX_TLX_PIR register */
+#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1)
+#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9)
+#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13)
+#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29)
+#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37)
+
struct otx2_hw {
struct pci_dev *pdev;
struct otx2_rss_info rss_info;
u16 rx_queues;
u16 tx_queues;
u16 xdp_queues;
- u16 tot_tx_queues;
+ u16 tc_tx_queues;
+ u16 non_qos_queues; /* tx queues plus xdp queues */
u16 max_queues;
u16 pool_cnt;
u16 rqpool_cnt;
@@ -209,6 +227,7 @@ struct otx2_hw {
u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
u16 matchall_ipolicer;
u32 dwrr_mtu;
+ u8 smq_link_type;
/* HW settings, coalescing etc */
u16 rx_chan_base;
@@ -250,6 +269,7 @@ struct otx2_hw {
#define CN10K_RPM 3
#define CN10K_PTP_ONESTEP 4
#define CN10K_HW_MACSEC 5
+#define QOS_CIR_PIR_SUPPORT 6
unsigned long cap_flag;
#define LMT_LINE_SIZE 128
@@ -281,6 +301,7 @@ struct flr_work {
struct refill_work {
struct delayed_work pool_refill_work;
struct otx2_nic *pf;
+ struct napi_struct *napi;
};
/* PTPv2 originTimestamp structure */
@@ -353,7 +374,7 @@ struct dev_hw_ops {
int (*sq_aq_init)(void *dev, u16 qidx, u16 sqb_aura);
void (*sqe_flush)(void *dev, struct otx2_snd_queue *sq,
int size, int qidx);
- void (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
+ int (*refill_pool_ptrs)(void *dev, struct otx2_cq_queue *cq);
void (*aura_freeptr)(void *dev, int aura, u64 buf);
};
@@ -398,6 +419,9 @@ struct cn10k_mcs_txsc {
u8 sa_bmap;
u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN];
u8 encoding_sa;
+ u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN];
+ ssci_t ssci[CN10K_MCS_SA_PER_SC];
+ bool vlan_dev; /* macsec running on VLAN ? */
};
struct cn10k_mcs_rxsc {
@@ -410,6 +434,8 @@ struct cn10k_mcs_rxsc {
u16 hw_sa_id[CN10K_MCS_SA_PER_SC];
u8 sa_bmap;
u8 sa_key[CN10K_MCS_SA_PER_SC][MACSEC_MAX_KEY_LEN];
+ u8 salt[CN10K_MCS_SA_PER_SC][MACSEC_SALT_LEN];
+ ssci_t ssci[CN10K_MCS_SA_PER_SC];
};
struct cn10k_mcs_cfg {
@@ -501,6 +527,8 @@ struct otx2_nic {
u16 pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
bool pfc_alloc_status[NIX_PF_PFC_PRIO_MAX];
#endif
+ /* qos */
+ struct otx2_qos qos;
/* napi event count. It is needed for adaptive irq coalescing. */
u32 napi_events;
@@ -582,6 +610,7 @@ static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf)
__set_bit(CN10K_LMTST, &hw->cap_flag);
__set_bit(CN10K_RPM, &hw->cap_flag);
__set_bit(CN10K_PTP_ONESTEP, &hw->cap_flag);
+ __set_bit(QOS_CIR_PIR_SUPPORT, &hw->cap_flag);
}
if (is_dev_cn10kb(pfvf->pdev))
@@ -745,8 +774,7 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
/* Alloc pointer from pool/aura */
static inline u64 otx2_aura_allocptr(struct otx2_nic *pfvf, int aura)
{
- u64 *ptr = (u64 *)otx2_get_regaddr(pfvf,
- NPA_LF_AURA_OP_ALLOCX(0));
+ u64 *ptr = (__force u64 *)otx2_get_regaddr(pfvf, NPA_LF_AURA_OP_ALLOCX(0));
u64 incr = (u64)aura | BIT_ULL(63);
return otx2_atomic64_add(incr, ptr);
@@ -888,12 +916,34 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,
static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx)
{
+ u16 smq;
#ifdef CONFIG_DCB
if (qidx < NIX_PF_PFC_PRIO_MAX && pfvf->pfc_alloc_status[qidx])
return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx];
#endif
+ /* check if qidx falls under QOS queues */
+ if (qidx >= pfvf->hw.non_qos_queues)
+ smq = pfvf->qos.qid_to_sqmap[qidx - pfvf->hw.non_qos_queues];
+ else
+ smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+
+ return smq;
+}
+
+static inline u16 otx2_get_total_tx_queues(struct otx2_nic *pfvf)
+{
+ return pfvf->hw.non_qos_queues + pfvf->hw.tc_tx_queues;
+}
+
+static inline u64 otx2_convert_rate(u64 rate)
+{
+ u64 converted_rate;
+
+ /* Convert bytes per second to Mbps */
+ converted_rate = rate * 8;
+ converted_rate = max_t(u64, converted_rate / 1000000, 1);
- return pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+ return converted_rate;
}
/* MSI-X APIs */
@@ -920,19 +970,25 @@ int otx2_config_nix(struct otx2_nic *pfvf);
int otx2_config_nix_queues(struct otx2_nic *pfvf);
int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
int otx2_txsch_alloc(struct otx2_nic *pfvf);
-int otx2_txschq_stop(struct otx2_nic *pfvf);
+void otx2_txschq_stop(struct otx2_nic *pfvf);
+void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq);
void otx2_sqb_flush(struct otx2_nic *pfvf);
-int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
- dma_addr_t *dma);
+int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ dma_addr_t *dma);
int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
+int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura);
int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
dma_addr_t *dma);
+int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
+ int stack_pages, int numptrs, int buf_size, int type);
+int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
+ int pool_id, int numptrs);
/* RSS configuration APIs*/
int otx2_rss_init(struct otx2_nic *pfvf);
@@ -1000,6 +1056,8 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf);
int otx2_handle_ntuple_tc_features(struct net_device *netdev,
netdev_features_t features);
int otx2_smq_flush(struct otx2_nic *pfvf, int smq);
+void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool,
+ u64 iova, int size);
/* tc support */
int otx2_init_tc(struct otx2_nic *nic);
@@ -1040,4 +1098,24 @@ static inline void cn10k_handle_mcs_event(struct otx2_nic *pfvf,
{}
#endif /* CONFIG_MACSEC */
+/* qos support */
+static inline void otx2_qos_init(struct otx2_nic *pfvf, int qos_txqs)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+
+ hw->tc_tx_queues = qos_txqs;
+ INIT_LIST_HEAD(&pfvf->qos.qos_tree);
+ mutex_init(&pfvf->qos.qos_lock);
+}
+
+static inline void otx2_shutdown_qos(struct otx2_nic *pfvf)
+{
+ mutex_destroy(&pfvf->qos.qos_lock);
+}
+
+u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
+ struct net_device *sb_dev);
+int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid);
+void otx2_qos_config_txschq(struct otx2_nic *pfvf);
+void otx2_clean_qos_queues(struct otx2_nic *pfvf);
#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
index ccaf97bb1ce0..bfddbff7bcdf 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
@@ -70,7 +70,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio)
* link config level. These rest of the scheduler can be
* same as hw.txschq_list.
*/
- for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++)
+ for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++)
req->schq[lvl] = 1;
rc = otx2_sync_mbox_msg(&pfvf->mbox);
@@ -83,7 +83,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio)
return PTR_ERR(rsp);
/* Setup transmit scheduler list */
- for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) {
+ for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) {
if (!rsp->schq[lvl])
return -ENOSPC;
@@ -125,19 +125,12 @@ int otx2_pfc_txschq_alloc(struct otx2_nic *pfvf)
static int otx2_pfc_txschq_stop_one(struct otx2_nic *pfvf, u8 prio)
{
- struct nix_txsch_free_req *free_req;
+ int lvl;
- mutex_lock(&pfvf->mbox.lock);
/* free PFC TLx nodes */
- free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox);
- if (!free_req) {
- mutex_unlock(&pfvf->mbox.lock);
- return -ENOMEM;
- }
-
- free_req->flags = TXSCHQ_FREE_ALL;
- otx2_sync_mbox_msg(&pfvf->mbox);
- mutex_unlock(&pfvf->mbox.lock);
+ for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++)
+ otx2_txschq_free_one(pfvf, lvl,
+ pfvf->pfc_schq_list[lvl][prio]);
pfvf->pfc_alloc_status[prio] = false;
return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 0f8d1a69139f..c47d91da32dc 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -92,10 +92,16 @@ static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset)
*data += ETH_GSTRING_LEN;
}
}
- for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) {
+
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
for (stats = 0; stats < otx2_n_queue_stats; stats++) {
- sprintf(*data, "txq%d: %s", qidx + start_qidx,
- otx2_queue_stats[stats].name);
+ if (qidx >= pfvf->hw.non_qos_queues)
+ sprintf(*data, "txq_qos%d: %s",
+ qidx + start_qidx - pfvf->hw.non_qos_queues,
+ otx2_queue_stats[stats].name);
+ else
+ sprintf(*data, "txq%d: %s", qidx + start_qidx,
+ otx2_queue_stats[stats].name);
*data += ETH_GSTRING_LEN;
}
}
@@ -159,7 +165,7 @@ static void otx2_get_qset_stats(struct otx2_nic *pfvf,
[otx2_queue_stats[stat].index];
}
- for (qidx = 0; qidx < pfvf->hw.tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
if (!otx2_update_sq_stats(pfvf, qidx)) {
for (stat = 0; stat < otx2_n_queue_stats; stat++)
*((*data)++) = 0;
@@ -254,7 +260,7 @@ static int otx2_get_sset_count(struct net_device *netdev, int sset)
return -EINVAL;
qstats_count = otx2_n_queue_stats *
- (pfvf->hw.rx_queues + pfvf->hw.tx_queues);
+ (pfvf->hw.rx_queues + otx2_get_total_tx_queues(pfvf));
if (!test_bit(CN10K_RPM, &pfvf->hw.cap_flag))
mac_stats = CGX_RX_STATS_COUNT + CGX_TX_STATS_COUNT;
otx2_update_lmac_fec_stats(pfvf);
@@ -282,7 +288,7 @@ static int otx2_set_channels(struct net_device *dev,
{
struct otx2_nic *pfvf = netdev_priv(dev);
bool if_up = netif_running(dev);
- int err = 0;
+ int err, qos_txqs;
if (!channel->rx_count || !channel->tx_count)
return -EINVAL;
@@ -296,14 +302,19 @@ static int otx2_set_channels(struct net_device *dev,
if (if_up)
dev->netdev_ops->ndo_stop(dev);
- err = otx2_set_real_num_queues(dev, channel->tx_count,
+ qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
+ OTX2_QOS_MAX_LEAF_NODES);
+
+ err = otx2_set_real_num_queues(dev, channel->tx_count + qos_txqs,
channel->rx_count);
if (err)
return err;
pfvf->hw.rx_queues = channel->rx_count;
pfvf->hw.tx_queues = channel->tx_count;
- pfvf->qset.cq_cnt = pfvf->hw.tx_queues + pfvf->hw.rx_queues;
+ if (pfvf->xdp_prog)
+ pfvf->hw.xdp_queues = channel->rx_count;
+ pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues;
if (if_up)
err = dev->netdev_ops->ndo_open(dev);
@@ -1405,7 +1416,7 @@ static int otx2vf_get_sset_count(struct net_device *netdev, int sset)
return -EINVAL;
qstats_count = otx2_n_queue_stats *
- (vf->hw.rx_queues + vf->hw.tx_queues);
+ (vf->hw.rx_queues + otx2_get_total_tx_queues(vf));
return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + 1;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 10e11262d48a..2d7713a1a153 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -872,6 +872,14 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
return -EINVAL;
vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
+
+ /* Drop rule with vlan_etype == 802.1Q
+ * and vlan_id == 0 is not supported
+ */
+ if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci &&
+ fsp->ring_cookie == RX_CLS_FLOW_DISC)
+ return -EINVAL;
+
/* Only ETH_P_8021Q and ETH_P_802AD types supported */
if (vlan_etype != ETH_P_8021Q &&
vlan_etype != ETH_P_8021AD)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 18284ad75157..9ded98bb1c89 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -23,6 +23,7 @@
#include "otx2_struct.h"
#include "otx2_ptp.h"
#include "cn10k.h"
+#include "qos.h"
#include <rvu_trace.h>
#define DRV_NAME "rvu_nicpf"
@@ -271,8 +272,7 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs)
{
int vf;
- pf->flr_wq = alloc_workqueue("otx2_pf_flr_wq",
- WQ_UNBOUND | WQ_HIGHPRI, 1);
+ pf->flr_wq = alloc_ordered_workqueue("otx2_pf_flr_wq", WQ_HIGHPRI);
if (!pf->flr_wq)
return -ENOMEM;
@@ -593,9 +593,8 @@ static int otx2_pfvf_mbox_init(struct otx2_nic *pf, int numvfs)
if (!pf->mbox_pfvf)
return -ENOMEM;
- pf->mbox_pfvf_wq = alloc_workqueue("otx2_pfvf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ pf->mbox_pfvf_wq = alloc_ordered_workqueue("otx2_pfvf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!pf->mbox_pfvf_wq)
return -ENOMEM;
@@ -791,10 +790,6 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(pf, (struct nix_lf_alloc_rsp *)msg);
break;
- case MBOX_MSG_NIX_TXSCH_ALLOC:
- mbox_handler_nix_txsch_alloc(pf,
- (struct nix_txsch_alloc_rsp *)msg);
- break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(pf, (struct nix_bp_cfg_rsp *)msg);
break;
@@ -1063,9 +1058,8 @@ static int otx2_pfaf_mbox_init(struct otx2_nic *pf)
int err;
mbox->pfvf = pf;
- pf->mbox_wq = alloc_workqueue("otx2_pfaf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ pf->mbox_wq = alloc_ordered_workqueue("otx2_pfaf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!pf->mbox_wq)
return -ENOMEM;
@@ -1228,6 +1222,7 @@ static char *nix_snd_status_e_str[NIX_SND_STATUS_MAX] = {
static irqreturn_t otx2_q_intr_handler(int irq, void *data)
{
struct otx2_nic *pf = data;
+ struct otx2_snd_queue *sq;
u64 val, *ptr;
u64 qidx = 0;
@@ -1257,10 +1252,14 @@ static irqreturn_t otx2_q_intr_handler(int irq, void *data)
}
/* SQ */
- for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
u64 sq_op_err_dbg, mnq_err_dbg, snd_err_dbg;
u8 sq_op_err_code, mnq_err_code, snd_err_code;
+ sq = &pf->qset.sq[qidx];
+ if (!sq->sqb_ptrs)
+ continue;
+
/* Below debug registers captures first errors corresponding to
* those registers. We don't have to check against SQ qid as
* these are fatal errors.
@@ -1383,8 +1382,11 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_SQ, false);
/* Free SQB pointers */
otx2_sq_free_sqbs(pf);
- for (qidx = 0; qidx < pf->hw.tot_tx_queues; qidx++) {
+ for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
sq = &qset->sq[qidx];
+ /* Skip freeing Qos queues if they are not initialized */
+ if (!sq->sqe)
+ continue;
qmem_free(pf->dev, sq->sqe);
qmem_free(pf->dev, sq->tso_hdrs);
kfree(sq->sg);
@@ -1433,7 +1435,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
* so, aura count = pool count.
*/
hw->rqpool_cnt = hw->rx_queues;
- hw->sqpool_cnt = hw->tot_tx_queues;
+ hw->sqpool_cnt = otx2_get_total_tx_queues(pf);
hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt;
/* Maximum hardware supported transmit length */
@@ -1452,8 +1454,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
if (err)
goto err_free_npa_lf;
- /* Enable backpressure */
- otx2_nix_config_bp(pf, true);
+ /* Enable backpressure for CGX mapped PF/VFs */
+ if (!is_otx2_lbkvf(pf->pdev))
+ otx2_nix_config_bp(pf, true);
/* Init Auras and pools used by NIX RQ, for free buffer ptrs */
err = otx2_rq_aura_pool_init(pf);
@@ -1516,8 +1519,7 @@ err_free_nix_queues:
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
- if (otx2_txschq_stop(pf))
- dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__);
+ otx2_txschq_stop(pf);
err_free_sq_ptrs:
otx2_sq_free_sqbs(pf);
err_free_rq_ptrs:
@@ -1551,22 +1553,24 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
struct nix_lf_free_req *free_req;
struct mbox *mbox = &pf->mbox;
struct otx2_cq_queue *cq;
+ struct otx2_pool *pool;
struct msg_req *req;
- int qidx, err;
+ int pool_id;
+ int qidx;
/* Ensure all SQE are processed */
otx2_sqb_flush(pf);
/* Stop transmission */
- err = otx2_txschq_stop(pf);
- if (err)
- dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
+ otx2_txschq_stop(pf);
#ifdef CONFIG_DCB
if (pf->pfc_en)
otx2_pfc_txschq_stop(pf);
#endif
+ otx2_clean_qos_queues(pf);
+
mutex_lock(&mbox->lock);
/* Disable backpressure */
if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
@@ -1580,7 +1584,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
for (qidx = 0; qidx < qset->cq_cnt; qidx++) {
cq = &qset->cq[qidx];
if (cq->cq_type == CQ_RX)
- otx2_cleanup_rx_cqes(pf, cq);
+ otx2_cleanup_rx_cqes(pf, cq, qidx);
else
otx2_cleanup_tx_cqes(pf, cq);
}
@@ -1590,6 +1594,13 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
/* Free RQ buffer pointers*/
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
+ for (qidx = 0; qidx < pf->hw.rx_queues; qidx++) {
+ pool_id = otx2_get_pool_idx(pf, AURA_NIX_RQ, qidx);
+ pool = &pf->qset.pool[pool_id];
+ page_pool_destroy(pool->page_pool);
+ pool->page_pool = NULL;
+ }
+
otx2_free_cq_res(pf);
/* Free all ingress bandwidth profiles allocated */
@@ -1688,11 +1699,14 @@ int otx2_open(struct net_device *netdev)
netif_carrier_off(netdev);
- pf->qset.cq_cnt = pf->hw.rx_queues + pf->hw.tot_tx_queues;
/* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed.
*/
- pf->hw.cint_cnt = max(pf->hw.rx_queues, pf->hw.tx_queues);
+ pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues,
+ pf->hw.tc_tx_queues);
+
+ pf->qset.cq_cnt = pf->hw.rx_queues + otx2_get_total_tx_queues(pf);
+
qset->napi = kcalloc(pf->hw.cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
if (!qset->napi)
return -ENOMEM;
@@ -1708,7 +1722,7 @@ int otx2_open(struct net_device *netdev)
if (!qset->cq)
goto err_free_mem;
- qset->sq = kcalloc(pf->hw.tot_tx_queues,
+ qset->sq = kcalloc(otx2_get_total_tx_queues(pf),
sizeof(struct otx2_snd_queue), GFP_KERNEL);
if (!qset->sq)
goto err_free_mem;
@@ -1743,6 +1757,11 @@ int otx2_open(struct net_device *netdev)
else
cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;
+ cq_poll->cq_ids[CQ_QOS] = (qidx < pf->hw.tc_tx_queues) ?
+ (qidx + pf->hw.rx_queues +
+ pf->hw.non_qos_queues) :
+ CINT_INVALID_CQ;
+
cq_poll->dev = (void *)pf;
cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
INIT_WORK(&cq_poll->dim.work, otx2_dim_work);
@@ -1826,6 +1845,9 @@ int otx2_open(struct net_device *netdev)
/* 'intf_down' may be checked on any cpu */
smp_wmb();
+ /* Enable QoS configuration before starting tx queues */
+ otx2_qos_config_txschq(pf);
+
/* we have already received link status notification */
if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK))
otx2_handle_link_event(pf);
@@ -1920,6 +1942,10 @@ int otx2_stop(struct net_device *netdev)
netif_tx_disable(netdev);
+ for (wrk = 0; wrk < pf->qset.cq_cnt; wrk++)
+ cancel_delayed_work_sync(&pf->refill_wrk[wrk].pool_refill_work);
+ devm_kfree(pf->dev, pf->refill_wrk);
+
otx2_free_hw_resources(pf);
otx2_free_cints(pf, pf->hw.cint_cnt);
otx2_disable_napi(pf);
@@ -1927,9 +1953,6 @@ int otx2_stop(struct net_device *netdev)
for (qidx = 0; qidx < netdev->num_tx_queues; qidx++)
netdev_tx_reset_queue(netdev_get_tx_queue(netdev, qidx));
- for (wrk = 0; wrk < pf->qset.cq_cnt; wrk++)
- cancel_delayed_work_sync(&pf->refill_wrk[wrk].pool_refill_work);
- devm_kfree(pf->dev, pf->refill_wrk);
kfree(qset->sq);
kfree(qset->cq);
@@ -1947,6 +1970,12 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
int qidx = skb_get_queue_mapping(skb);
struct otx2_snd_queue *sq;
struct netdev_queue *txq;
+ int sq_idx;
+
+ /* XDP SQs are not mapped with TXQs
+ * advance qid to derive correct sq mapped with QOS
+ */
+ sq_idx = (qidx >= pf->hw.tx_queues) ? (qidx + pf->hw.xdp_queues) : qidx;
/* Check for minimum and maximum packet length */
if (skb->len <= ETH_HLEN ||
@@ -1955,7 +1984,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
- sq = &pf->qset.sq[qidx];
+ sq = &pf->qset.sq[sq_idx];
txq = netdev_get_tx_queue(netdev, qidx);
if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
@@ -1973,14 +2002,48 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
-static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
- struct net_device *sb_dev)
+static int otx2_qos_select_htb_queue(struct otx2_nic *pf, struct sk_buff *skb,
+ u16 htb_maj_id)
+{
+ u16 classid;
+
+ if ((TC_H_MAJ(skb->priority) >> 16) == htb_maj_id)
+ classid = TC_H_MIN(skb->priority);
+ else
+ classid = READ_ONCE(pf->qos.defcls);
+
+ if (!classid)
+ return 0;
+
+ return otx2_get_txq_by_classid(pf, classid);
+}
+
+u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
+ struct net_device *sb_dev)
{
-#ifdef CONFIG_DCB
struct otx2_nic *pf = netdev_priv(netdev);
+ bool qos_enabled;
+#ifdef CONFIG_DCB
u8 vlan_prio;
#endif
+ int txq;
+
+ qos_enabled = (netdev->real_num_tx_queues > pf->hw.tx_queues) ? true : false;
+ if (unlikely(qos_enabled)) {
+ /* This smp_load_acquire() pairs with smp_store_release() in
+ * otx2_qos_root_add() called from htb offload root creation
+ */
+ u16 htb_maj_id = smp_load_acquire(&pf->qos.maj_id);
+ if (unlikely(htb_maj_id)) {
+ txq = otx2_qos_select_htb_queue(pf, skb, htb_maj_id);
+ if (txq > 0)
+ return txq;
+ goto process_pfc;
+ }
+ }
+
+process_pfc:
#ifdef CONFIG_DCB
if (!skb_vlan_tag_present(skb))
goto pick_tx;
@@ -1994,8 +2057,13 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
pick_tx:
#endif
- return netdev_pick_tx(netdev, skb, NULL);
+ txq = netdev_pick_tx(netdev, skb, NULL);
+ if (unlikely(qos_enabled))
+ return txq % pf->hw.tx_queues;
+
+ return txq;
}
+EXPORT_SYMBOL(otx2_select_queue);
static netdev_features_t otx2_fix_features(struct net_device *dev,
netdev_features_t features)
@@ -2529,7 +2597,7 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog)
xdp_features_clear_redirect_target(dev);
}
- pf->hw.tot_tx_queues += pf->hw.xdp_queues;
+ pf->hw.non_qos_queues += pf->hw.xdp_queues;
if (if_up)
otx2_open(pf->netdev);
@@ -2712,10 +2780,10 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
+ int err, qcount, qos_txqs;
struct net_device *netdev;
struct otx2_nic *pf;
struct otx2_hw *hw;
- int err, qcount;
int num_vec;
err = pcim_enable_device(pdev);
@@ -2740,8 +2808,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set number of queues */
qcount = min_t(int, num_online_cpus(), OTX2_MAX_CQ_CNT);
+ qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES);
- netdev = alloc_etherdev_mqs(sizeof(*pf), qcount, qcount);
+ netdev = alloc_etherdev_mqs(sizeof(*pf), qcount + qos_txqs, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
@@ -2760,7 +2829,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hw->pdev = pdev;
hw->rx_queues = qcount;
hw->tx_queues = qcount;
- hw->tot_tx_queues = qcount;
+ hw->non_qos_queues = qcount;
hw->max_queues = qcount;
hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN;
/* Use CQE of 128 byte descriptor size by default */
@@ -2929,6 +2998,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_pf_sriov_init;
#endif
+ otx2_qos_init(pf, qos_txqs);
+
return 0;
err_pf_sriov_init:
@@ -3104,6 +3175,7 @@ static void otx2_remove(struct pci_dev *pdev)
otx2_ptp_destroy(pf);
otx2_mcam_flow_del(pf);
otx2_shutdown_tc(pf);
+ otx2_shutdown_qos(pf);
otx2_detach_resources(&pf->mbox);
if (pf->hw.lmt_info)
free_percpu(pf->hw.lmt_info);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
index 1b967eaf948b..45a32e4b49d1 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
@@ -145,12 +145,25 @@
#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (a) << 16)
#define NIX_AF_TL2X_PARENT(a) (0xE88 | (a) << 16)
#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (a) << 16)
+#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (a) << 16)
+#define NIX_AF_TL2X_CIR(a) (0xE20 | (a) << 16)
+#define NIX_AF_TL2X_PIR(a) (0xE30 | (a) << 16)
#define NIX_AF_TL3X_PARENT(a) (0x1088 | (a) << 16)
#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (a) << 16)
+#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (a) << 16)
+#define NIX_AF_TL3X_CIR(a) (0x1020 | (a) << 16)
+#define NIX_AF_TL3X_PIR(a) (0x1030 | (a) << 16)
+#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (a) << 16)
#define NIX_AF_TL4X_PARENT(a) (0x1288 | (a) << 16)
#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (a) << 16)
+#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (a) << 16)
+#define NIX_AF_TL4X_CIR(a) (0x1220 | (a) << 16)
#define NIX_AF_TL4X_PIR(a) (0x1230 | (a) << 16)
+#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (a) << 16)
#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (a) << 16)
+#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (a) << 16)
+#define NIX_AF_MDQX_CIR(a) (0x1420 | (a) << 16)
+#define NIX_AF_MDQX_PIR(a) (0x1430 | (a) << 16)
#define NIX_AF_MDQX_PARENT(a) (0x1480 | (a) << 16)
#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (a) << 16 | (b) << 3)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
index 8392f63e433f..5e56b6c3e60a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
@@ -19,25 +19,11 @@
#include "cn10k.h"
#include "otx2_common.h"
-
-/* Egress rate limiting definitions */
-#define MAX_BURST_EXPONENT 0x0FULL
-#define MAX_BURST_MANTISSA 0xFFULL
-#define MAX_BURST_SIZE 130816ULL
-#define MAX_RATE_DIVIDER_EXPONENT 12ULL
-#define MAX_RATE_EXPONENT 0x0FULL
-#define MAX_RATE_MANTISSA 0xFFULL
+#include "qos.h"
#define CN10K_MAX_BURST_MANTISSA 0x7FFFULL
#define CN10K_MAX_BURST_SIZE 8453888ULL
-/* Bitfields in NIX_TLX_PIR register */
-#define TLX_RATE_MANTISSA GENMASK_ULL(8, 1)
-#define TLX_RATE_EXPONENT GENMASK_ULL(12, 9)
-#define TLX_RATE_DIVIDER_EXPONENT GENMASK_ULL(16, 13)
-#define TLX_BURST_MANTISSA GENMASK_ULL(36, 29)
-#define TLX_BURST_EXPONENT GENMASK_ULL(40, 37)
-
#define CN10K_TLX_BURST_MANTISSA GENMASK_ULL(43, 29)
#define CN10K_TLX_BURST_EXPONENT GENMASK_ULL(47, 44)
@@ -147,8 +133,8 @@ static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp,
}
}
-static u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic,
- u64 maxrate, u32 burst)
+u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic,
+ u64 maxrate, u32 burst)
{
u32 burst_exp, burst_mantissa;
u32 exp, mantissa, div_exp;
@@ -264,7 +250,6 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
struct netlink_ext_ack *extack = cls->common.extack;
struct flow_action *actions = &cls->rule->action;
struct flow_action_entry *entry;
- u64 rate;
int err;
err = otx2_tc_validate_flow(nic, actions, extack);
@@ -288,10 +273,8 @@ static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
return -EOPNOTSUPP;
}
- /* Convert bytes per second to Mbps */
- rate = entry->police.rate_bytes_ps * 8;
- rate = max_t(u64, rate / 1000000, 1);
- err = otx2_set_matchall_egress_rate(nic, entry->police.burst, rate);
+ err = otx2_set_matchall_egress_rate(nic, entry->police.burst,
+ otx2_convert_rate(entry->police.rate_bytes_ps));
if (err)
return err;
nic->flags |= OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED;
@@ -413,8 +396,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
return -EOPNOTSUPP;
}
req->vf = priv->pcifunc & RVU_PFVF_FUNC_MASK;
- req->op = NIX_RX_ACTION_DEFAULT;
- return 0;
+
+ /* if op is already set; avoid overwriting the same */
+ if (!req->op)
+ req->op = NIX_RX_ACTION_DEFAULT;
+ break;
+
case FLOW_ACTION_VLAN_POP:
req->vtag0_valid = true;
/* use RX_VTAG_TYPE7 which is initialized to strip vlan tag */
@@ -450,6 +437,12 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
case FLOW_ACTION_MARK:
mark = act->mark;
break;
+
+ case FLOW_ACTION_RX_QUEUE_MAPPING:
+ req->op = NIX_RX_ACTIONOP_UCAST;
+ req->index = act->rx_queue;
+ break;
+
default:
return -EOPNOTSUPP;
}
@@ -604,6 +597,21 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
return -EOPNOTSUPP;
}
+ if (!match.mask->vlan_id) {
+ struct flow_action_entry *act;
+ int i;
+
+ flow_action_for_each(i, act, &rule->action) {
+ if (act->id == FLOW_ACTION_DROP) {
+ netdev_err(nic->netdev,
+ "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n",
+ ntohs(match.key->vlan_tpid),
+ match.key->vlan_id);
+ return -EOPNOTSUPP;
+ }
+ }
+ }
+
if (match.mask->vlan_id ||
match.mask->vlan_dei ||
match.mask->vlan_priority) {
@@ -1127,6 +1135,8 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return otx2_setup_tc_block(netdev, type_data);
+ case TC_SETUP_QDISC_HTB:
+ return otx2_setup_tc_htb(netdev, type_data);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 7af223b0a37f..e77d43848955 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -217,9 +217,6 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
va - page_address(page) + off,
len - off, pfvf->rbsize);
-
- otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM,
- pfvf->rbsize, DMA_FROM_DEVICE);
return true;
}
@@ -382,6 +379,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
if (pfvf->netdev->features & NETIF_F_RXCSUM)
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_mark_for_recycle(skb);
+
napi_gro_frags(napi);
}
@@ -425,9 +424,10 @@ process_cqe:
return processed_cqe;
}
-void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
+int otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
{
struct otx2_nic *pfvf = dev;
+ int cnt = cq->pool_ptrs;
dma_addr_t bufptr;
while (cq->pool_ptrs) {
@@ -436,6 +436,8 @@ void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
otx2_aura_freeptr(pfvf, cq->cq_idx, bufptr + OTX2_HEAD_ROOM);
cq->pool_ptrs--;
}
+
+ return cnt - cq->pool_ptrs;
}
static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
@@ -464,12 +466,13 @@ process_cqe:
break;
}
- if (cq->cq_type == CQ_XDP) {
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+
+ if (cq->cq_type == CQ_XDP)
otx2_xdp_snd_pkt_handler(pfvf, sq, cqe);
- } else {
- otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget,
- &tx_pkts, &tx_bytes);
- }
+ else
+ otx2_snd_pkt_handler(pfvf, cq, &pfvf->qset.sq[qidx],
+ cqe, budget, &tx_pkts, &tx_bytes);
cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID;
processed_cqe++;
@@ -486,7 +489,11 @@ process_cqe:
if (likely(tx_pkts)) {
struct netdev_queue *txq;
- txq = netdev_get_tx_queue(pfvf->netdev, cq->cint_idx);
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+
+ if (qidx >= pfvf->hw.tx_queues)
+ qidx -= pfvf->hw.xdp_queues;
+ txq = netdev_get_tx_queue(pfvf->netdev, qidx);
netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
/* Check if queue was stopped earlier due to ring full */
smp_mb();
@@ -517,6 +524,7 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
struct otx2_cq_queue *cq;
struct otx2_qset *qset;
struct otx2_nic *pfvf;
+ int filled_cnt = -1;
cq_poll = container_of(napi, struct otx2_cq_poll, napi);
pfvf = (struct otx2_nic *)cq_poll->dev;
@@ -537,7 +545,7 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
}
if (rx_cq && rx_cq->pool_ptrs)
- pfvf->hw_ops->refill_pool_ptrs(pfvf, rx_cq);
+ filled_cnt = pfvf->hw_ops->refill_pool_ptrs(pfvf, rx_cq);
/* Clear the IRQ */
otx2_write64(pfvf, NIX_LF_CINTX_INT(cq_poll->cint_idx), BIT_ULL(0));
@@ -557,9 +565,25 @@ int otx2_napi_handler(struct napi_struct *napi, int budget)
otx2_config_irq_coalescing(pfvf, i);
}
- /* Re-enable interrupts */
- otx2_write64(pfvf, NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx),
- BIT_ULL(0));
+ if (unlikely(!filled_cnt)) {
+ struct refill_work *work;
+ struct delayed_work *dwork;
+
+ work = &pfvf->refill_wrk[cq->cq_idx];
+ dwork = &work->pool_refill_work;
+ /* Schedule a task if no other task is running */
+ if (!cq->refill_task_sched) {
+ work->napi = napi;
+ cq->refill_task_sched = true;
+ schedule_delayed_work(dwork,
+ msecs_to_jiffies(100));
+ }
+ } else {
+ /* Re-enable interrupts */
+ otx2_write64(pfvf,
+ NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx),
+ BIT_ULL(0));
+ }
}
return workdone;
}
@@ -734,7 +758,8 @@ static void otx2_sqe_add_hdr(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
sqe_hdr->aura = sq->aura_id;
/* Post a CQE Tx after pkt transmission */
sqe_hdr->pnc = 1;
- sqe_hdr->sq = qidx;
+ sqe_hdr->sq = (qidx >= pfvf->hw.tx_queues) ?
+ qidx + pfvf->hw.xdp_queues : qidx;
}
sqe_hdr->total = skb->len;
/* Set SQE identifier which will be used later for freeing SKB */
@@ -1178,11 +1203,13 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
}
EXPORT_SYMBOL(otx2_sq_append_skb);
-void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
+void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx)
{
struct nix_cqe_rx_s *cqe;
+ struct otx2_pool *pool;
int processed_cqe = 0;
- u64 iova, pa;
+ u16 pool_id;
+ u64 iova;
if (pfvf->xdp_prog)
xdp_rxq_info_unreg(&cq->xdp_rxq);
@@ -1190,6 +1217,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
return;
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx);
+ pool = &pfvf->qset.pool[pool_id];
+
while (cq->pend_cqe) {
cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq);
processed_cqe++;
@@ -1202,9 +1232,8 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
continue;
}
iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM;
- pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
- otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE);
- put_page(virt_to_page(phys_to_virt(pa)));
+
+ otx2_free_bufs(pfvf, pool, iova, pfvf->rbsize);
}
/* Free CQEs to HW */
@@ -1219,8 +1248,10 @@ void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq)
struct nix_cqe_tx_s *cqe;
int processed_cqe = 0;
struct sg_list *sg;
+ int qidx;
- sq = &pfvf->qset.sq[cq->cint_idx];
+ qidx = cq->cq_idx - pfvf->hw.rx_queues;
+ sq = &pfvf->qset.sq[qidx];
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
return;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index 93cac2c2664c..a82ffca8ce1b 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -23,6 +23,8 @@
#define OTX2_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN)
#define OTX2_MIN_MTU 60
+#define OTX2_PAGE_POOL_SZ 2048
+
#define OTX2_MAX_GSO_SEGS 255
#define OTX2_MAX_FRAGS_IN_SQE 9
@@ -102,7 +104,8 @@ enum cq_type {
CQ_RX,
CQ_TX,
CQ_XDP,
- CQS_PER_CINT = 3, /* RQ + SQ + XDP */
+ CQ_QOS,
+ CQS_PER_CINT = 4, /* RQ + SQ + XDP + QOS_SQ */
};
struct otx2_cq_poll {
@@ -117,6 +120,7 @@ struct otx2_cq_poll {
struct otx2_pool {
struct qmem *stack;
struct qmem *fc_addr;
+ struct page_pool *page_pool;
u16 rbsize;
};
@@ -166,6 +170,6 @@ void cn10k_sqe_flush(void *dev, struct otx2_snd_queue *sq,
int size, int qidx);
void otx2_sqe_flush(void *dev, struct otx2_snd_queue *sq,
int size, int qidx);
-void otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
-void cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
+int cn10k_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq);
#endif /* OTX2_TXRX_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 53366dbfbf27..35e06048356f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -70,10 +70,6 @@ static void otx2vf_process_vfaf_mbox_msg(struct otx2_nic *vf,
case MBOX_MSG_NIX_LF_ALLOC:
mbox_handler_nix_lf_alloc(vf, (struct nix_lf_alloc_rsp *)msg);
break;
- case MBOX_MSG_NIX_TXSCH_ALLOC:
- mbox_handler_nix_txsch_alloc(vf,
- (struct nix_txsch_alloc_rsp *)msg);
- break;
case MBOX_MSG_NIX_BP_ENABLE:
mbox_handler_nix_bp_enable(vf, (struct nix_bp_cfg_rsp *)msg);
break;
@@ -297,9 +293,8 @@ static int otx2vf_vfaf_mbox_init(struct otx2_nic *vf)
int err;
mbox->pfvf = vf;
- vf->mbox_wq = alloc_workqueue("otx2_vfaf_mailbox",
- WQ_UNBOUND | WQ_HIGHPRI |
- WQ_MEM_RECLAIM, 1);
+ vf->mbox_wq = alloc_ordered_workqueue("otx2_vfaf_mailbox",
+ WQ_HIGHPRI | WQ_MEM_RECLAIM);
if (!vf->mbox_wq)
return -ENOMEM;
@@ -479,6 +474,7 @@ static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_open = otx2vf_open,
.ndo_stop = otx2vf_stop,
.ndo_start_xmit = otx2vf_xmit,
+ .ndo_select_queue = otx2_select_queue,
.ndo_set_rx_mode = otx2vf_set_rx_mode,
.ndo_set_mac_address = otx2_set_mac_address,
.ndo_change_mtu = otx2vf_change_mtu,
@@ -524,10 +520,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int num_vec = pci_msix_vec_count(pdev);
struct device *dev = &pdev->dev;
+ int err, qcount, qos_txqs;
struct net_device *netdev;
struct otx2_nic *vf;
struct otx2_hw *hw;
- int err, qcount;
err = pcim_enable_device(pdev);
if (err) {
@@ -550,7 +546,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
qcount = num_online_cpus();
- netdev = alloc_etherdev_mqs(sizeof(*vf), qcount, qcount);
+ qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES);
+ netdev = alloc_etherdev_mqs(sizeof(*vf), qcount + qos_txqs, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
@@ -570,7 +567,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hw->rx_queues = qcount;
hw->tx_queues = qcount;
hw->max_queues = qcount;
- hw->tot_tx_queues = qcount;
+ hw->non_qos_queues = qcount;
hw->rbuf_len = OTX2_DEFAULT_RBUF_LEN;
/* Use CQE of 128 byte descriptor size by default */
hw->xqe_size = 128;
@@ -699,6 +696,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_shutdown_tc;
#endif
+ otx2_qos_init(vf, qos_txqs);
return 0;
@@ -761,6 +759,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
otx2_ptp_destroy(vf);
otx2_mcam_flow_del(vf);
otx2_shutdown_tc(vf);
+ otx2_shutdown_qos(vf);
otx2vf_disable_mbox_intr(vf);
otx2_detach_resources(&vf->mbox);
free_percpu(vf->hw.lmt_info);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
new file mode 100644
index 000000000000..d3a76c5ccda8
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
@@ -0,0 +1,1363 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/bitfield.h>
+
+#include "otx2_common.h"
+#include "cn10k.h"
+#include "qos.h"
+
+#define OTX2_QOS_QID_INNER 0xFFFFU
+#define OTX2_QOS_QID_NONE 0xFFFEU
+#define OTX2_QOS_ROOT_CLASSID 0xFFFFFFFF
+#define OTX2_QOS_CLASS_NONE 0
+#define OTX2_QOS_DEFAULT_PRIO 0xF
+#define OTX2_QOS_INVALID_SQ 0xFFFF
+
+static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int tx_queues, qos_txqs, err;
+
+ qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
+ OTX2_QOS_MAX_LEAF_NODES);
+
+ tx_queues = hw->tx_queues + qos_txqs;
+
+ err = netif_set_real_num_tx_queues(pfvf->netdev, tx_queues);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to set no of Tx queues: %d\n", tx_queues);
+ return;
+ }
+}
+
+static void otx2_qos_get_regaddr(struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg,
+ int index)
+{
+ if (node->level == NIX_TXSCH_LVL_SMQ) {
+ cfg->reg[index++] = NIX_AF_MDQX_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_MDQX_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_MDQX_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_MDQX_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL4) {
+ cfg->reg[index++] = NIX_AF_TL4X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL4X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL4X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL4X_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL3) {
+ cfg->reg[index++] = NIX_AF_TL3X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL3X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL3X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL3X_CIR(node->schq);
+ } else if (node->level == NIX_TXSCH_LVL_TL2) {
+ cfg->reg[index++] = NIX_AF_TL2X_PARENT(node->schq);
+ cfg->reg[index++] = NIX_AF_TL2X_SCHEDULE(node->schq);
+ cfg->reg[index++] = NIX_AF_TL2X_PIR(node->schq);
+ cfg->reg[index] = NIX_AF_TL2X_CIR(node->schq);
+ }
+}
+
+static void otx2_config_sched_shaping(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg,
+ int *num_regs)
+{
+ u64 maxrate;
+
+ otx2_qos_get_regaddr(node, cfg, *num_regs);
+
+ /* configure parent txschq */
+ cfg->regval[*num_regs] = node->parent->schq << 16;
+ (*num_regs)++;
+
+ /* configure prio/quantum */
+ if (node->qid == OTX2_QOS_QID_NONE) {
+ cfg->regval[*num_regs] = node->prio << 24 |
+ mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
+ (*num_regs)++;
+ return;
+ }
+
+ /* configure priority */
+ cfg->regval[*num_regs] = (node->schq - node->parent->prio_anchor) << 24;
+ (*num_regs)++;
+
+ /* configure PIR */
+ maxrate = (node->rate > node->ceil) ? node->rate : node->ceil;
+
+ cfg->regval[*num_regs] =
+ otx2_get_txschq_rate_regval(pfvf, maxrate, 65536);
+ (*num_regs)++;
+
+ /* Don't configure CIR when both CIR+PIR not supported
+ * On 96xx, CIR + PIR + RED_ALGO=STALL causes deadlock
+ */
+ if (!test_bit(QOS_CIR_PIR_SUPPORT, &pfvf->hw.cap_flag))
+ return;
+
+ cfg->regval[*num_regs] =
+ otx2_get_txschq_rate_regval(pfvf, node->rate, 65536);
+ (*num_regs)++;
+}
+
+static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct nix_txschq_config *cfg)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int num_regs = 0;
+ u8 level;
+
+ level = node->level;
+
+ /* program txschq registers */
+ if (level == NIX_TXSCH_LVL_SMQ) {
+ cfg->reg[num_regs] = NIX_AF_SMQX_CFG(node->schq);
+ cfg->regval[num_regs] = ((u64)pfvf->tx_max_pktlen << 8) |
+ OTX2_MIN_MTU;
+ cfg->regval[num_regs] |= (0x20ULL << 51) | (0x80ULL << 39) |
+ (0x2ULL << 36);
+ num_regs++;
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+
+ } else if (level == NIX_TXSCH_LVL_TL4) {
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ } else if (level == NIX_TXSCH_LVL_TL3) {
+ /* configure link cfg */
+ if (level == pfvf->qos.link_cfg_lvl) {
+ cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
+ cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
+ num_regs++;
+ }
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ } else if (level == NIX_TXSCH_LVL_TL2) {
+ /* configure link cfg */
+ if (level == pfvf->qos.link_cfg_lvl) {
+ cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
+ cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
+ num_regs++;
+ }
+
+ /* check if node is root */
+ if (node->qid == OTX2_QOS_QID_INNER && !node->parent) {
+ cfg->reg[num_regs] = NIX_AF_TL2X_SCHEDULE(node->schq);
+ cfg->regval[num_regs] = TXSCH_TL1_DFLT_RR_PRIO << 24 |
+ mtu_to_dwrr_weight(pfvf,
+ pfvf->tx_max_pktlen);
+ num_regs++;
+ goto txschq_cfg_out;
+ }
+
+ otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
+ }
+
+txschq_cfg_out:
+ cfg->num_regs = num_regs;
+}
+
+static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct mbox *mbox = &pfvf->mbox;
+ struct nix_txschq_config *cfg;
+ int rc;
+
+ if (parent->level == NIX_TXSCH_LVL_MDQ)
+ return 0;
+
+ mutex_lock(&mbox->lock);
+
+ cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
+ if (!cfg) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ cfg->lvl = parent->level;
+
+ if (parent->level == NIX_TXSCH_LVL_TL4)
+ cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL3)
+ cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL2)
+ cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(parent->schq);
+ else if (parent->level == NIX_TXSCH_LVL_TL1)
+ cfg->reg[0] = NIX_AF_TL1X_TOPOLOGY(parent->schq);
+
+ cfg->regval[0] = (u64)parent->prio_anchor << 32;
+ if (parent->level == NIX_TXSCH_LVL_TL1)
+ cfg->regval[0] |= (u64)TXSCH_TL1_DFLT_RR_PRIO << 1;
+
+ cfg->num_regs++;
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+
+ mutex_unlock(&mbox->lock);
+
+ return rc;
+}
+
+static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry_reverse(node, &parent->child_schq_list, list)
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+}
+
+static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
+ otx2_qos_free_hw_node(pfvf, node);
+ otx2_qos_free_hw_node_schq(pfvf, node);
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+ }
+}
+
+static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+
+ /* free child node hw mappings */
+ otx2_qos_free_hw_node(pfvf, node);
+ otx2_qos_free_hw_node_schq(pfvf, node);
+
+ /* free node hw mappings */
+ otx2_txschq_free_one(pfvf, node->level, node->schq);
+
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_sw_node_delete(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ hash_del_rcu(&node->hlist);
+
+ if (node->qid != OTX2_QOS_QID_INNER && node->qid != OTX2_QOS_QID_NONE) {
+ __clear_bit(node->qid, pfvf->qos.qos_sq_bmap);
+ otx2_qos_update_tx_netdev_queues(pfvf);
+ }
+
+ list_del(&node->list);
+ kfree(node);
+}
+
+static void otx2_qos_free_sw_node_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_schq_list, list) {
+ list_del(&node->list);
+ kfree(node);
+ }
+}
+
+static void __otx2_qos_free_sw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent)
+{
+ struct otx2_qos_node *node, *tmp;
+
+ list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
+ __otx2_qos_free_sw_node(pfvf, node);
+ otx2_qos_free_sw_node_schq(pfvf, node);
+ otx2_qos_sw_node_delete(pfvf, node);
+ }
+}
+
+static void otx2_qos_free_sw_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+
+ __otx2_qos_free_sw_node(pfvf, node);
+ otx2_qos_free_sw_node_schq(pfvf, node);
+ otx2_qos_sw_node_delete(pfvf, node);
+
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_destroy_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ otx2_qos_free_hw_cfg(pfvf, node);
+ otx2_qos_free_sw_node(pfvf, node);
+}
+
+static void otx2_qos_fill_cfg_schq(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry(node, &parent->child_schq_list, list)
+ cfg->schq[node->level]++;
+}
+
+static void otx2_qos_fill_cfg_tl(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+
+ list_for_each_entry(node, &parent->child_list, list) {
+ otx2_qos_fill_cfg_tl(node, cfg);
+ cfg->schq_contig[node->level]++;
+ otx2_qos_fill_cfg_schq(node, cfg);
+ }
+}
+
+static void otx2_qos_prepare_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_fill_cfg_tl(parent, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static void otx2_qos_read_txschq_cfg_schq(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+ int cnt;
+
+ list_for_each_entry(node, &parent->child_schq_list, list) {
+ cnt = cfg->dwrr_node_pos[node->level];
+ cfg->schq_list[node->level][cnt] = node->schq;
+ cfg->schq[node->level]++;
+ cfg->dwrr_node_pos[node->level]++;
+ }
+}
+
+static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *node;
+ int cnt;
+
+ list_for_each_entry(node, &parent->child_list, list) {
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ cnt = cfg->static_node_pos[node->level];
+ cfg->schq_contig_list[node->level][cnt] = node->schq;
+ cfg->schq_contig[node->level]++;
+ cfg->static_node_pos[node->level]++;
+ otx2_qos_read_txschq_cfg_schq(node, cfg);
+ }
+}
+
+static void otx2_qos_read_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static struct otx2_qos_node *
+otx2_qos_alloc_root(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *node;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ node->parent = NULL;
+ if (!is_otx2_vf(pfvf->pcifunc))
+ node->level = NIX_TXSCH_LVL_TL1;
+ else
+ node->level = NIX_TXSCH_LVL_TL2;
+
+ WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
+ node->classid = OTX2_QOS_ROOT_CLASSID;
+
+ hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, node->classid);
+ list_add_tail(&node->list, &pfvf->qos.qos_tree);
+ INIT_LIST_HEAD(&node->child_list);
+ INIT_LIST_HEAD(&node->child_schq_list);
+
+ return node;
+}
+
+static int otx2_qos_add_child_node(struct otx2_qos_node *parent,
+ struct otx2_qos_node *node)
+{
+ struct list_head *head = &parent->child_list;
+ struct otx2_qos_node *tmp_node;
+ struct list_head *tmp;
+
+ for (tmp = head->next; tmp != head; tmp = tmp->next) {
+ tmp_node = list_entry(tmp, struct otx2_qos_node, list);
+ if (tmp_node->prio == node->prio)
+ return -EEXIST;
+ if (tmp_node->prio > node->prio) {
+ list_add_tail(&node->list, tmp);
+ return 0;
+ }
+ }
+
+ list_add_tail(&node->list, head);
+ return 0;
+}
+
+static int otx2_qos_alloc_txschq_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node)
+{
+ struct otx2_qos_node *txschq_node, *parent, *tmp;
+ int lvl;
+
+ parent = node;
+ for (lvl = node->level - 1; lvl >= NIX_TXSCH_LVL_MDQ; lvl--) {
+ txschq_node = kzalloc(sizeof(*txschq_node), GFP_KERNEL);
+ if (!txschq_node)
+ goto err_out;
+
+ txschq_node->parent = parent;
+ txschq_node->level = lvl;
+ txschq_node->classid = OTX2_QOS_CLASS_NONE;
+ WRITE_ONCE(txschq_node->qid, OTX2_QOS_QID_NONE);
+ txschq_node->rate = 0;
+ txschq_node->ceil = 0;
+ txschq_node->prio = 0;
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ list_add_tail(&txschq_node->list, &node->child_schq_list);
+ mutex_unlock(&pfvf->qos.qos_lock);
+
+ INIT_LIST_HEAD(&txschq_node->child_list);
+ INIT_LIST_HEAD(&txschq_node->child_schq_list);
+ parent = txschq_node;
+ }
+
+ return 0;
+
+err_out:
+ list_for_each_entry_safe(txschq_node, tmp, &node->child_schq_list,
+ list) {
+ list_del(&txschq_node->list);
+ kfree(txschq_node);
+ }
+ return -ENOMEM;
+}
+
+static struct otx2_qos_node *
+otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf,
+ struct otx2_qos_node *parent,
+ u16 classid, u32 prio, u64 rate, u64 ceil,
+ u16 qid)
+{
+ struct otx2_qos_node *node;
+ int err;
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return ERR_PTR(-ENOMEM);
+
+ node->parent = parent;
+ node->level = parent->level - 1;
+ node->classid = classid;
+ WRITE_ONCE(node->qid, qid);
+
+ node->rate = otx2_convert_rate(rate);
+ node->ceil = otx2_convert_rate(ceil);
+ node->prio = prio;
+
+ __set_bit(qid, pfvf->qos.qos_sq_bmap);
+
+ hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, classid);
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ err = otx2_qos_add_child_node(parent, node);
+ if (err) {
+ mutex_unlock(&pfvf->qos.qos_lock);
+ return ERR_PTR(err);
+ }
+ mutex_unlock(&pfvf->qos.qos_lock);
+
+ INIT_LIST_HEAD(&node->child_list);
+ INIT_LIST_HEAD(&node->child_schq_list);
+
+ err = otx2_qos_alloc_txschq_node(pfvf, node);
+ if (err) {
+ otx2_qos_sw_node_delete(pfvf, node);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return node;
+}
+
+static struct otx2_qos_node *
+otx2_sw_node_find(struct otx2_nic *pfvf, u32 classid)
+{
+ struct otx2_qos_node *node = NULL;
+
+ hash_for_each_possible(pfvf->qos.qos_hlist, node, hlist, classid) {
+ if (node->classid == classid)
+ break;
+ }
+
+ return node;
+}
+
+static struct otx2_qos_node *
+otx2_sw_node_find_rcu(struct otx2_nic *pfvf, u32 classid)
+{
+ struct otx2_qos_node *node = NULL;
+
+ hash_for_each_possible_rcu(pfvf->qos.qos_hlist, node, hlist, classid) {
+ if (node->classid == classid)
+ break;
+ }
+
+ return node;
+}
+
+int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid)
+{
+ struct otx2_qos_node *node;
+ u16 qid;
+ int res;
+
+ node = otx2_sw_node_find_rcu(pfvf, classid);
+ if (!node) {
+ res = -ENOENT;
+ goto out;
+ }
+ qid = READ_ONCE(node->qid);
+ if (qid == OTX2_QOS_QID_INNER) {
+ res = -EINVAL;
+ goto out;
+ }
+ res = pfvf->hw.tx_queues + qid;
+out:
+ return res;
+}
+
+static int
+otx2_qos_txschq_config(struct otx2_nic *pfvf, struct otx2_qos_node *node)
+{
+ struct mbox *mbox = &pfvf->mbox;
+ struct nix_txschq_config *req;
+ int rc;
+
+ mutex_lock(&mbox->lock);
+
+ req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ req->lvl = node->level;
+ __otx2_qos_txschq_cfg(pfvf, node, req);
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+
+ mutex_unlock(&mbox->lock);
+
+ return rc;
+}
+
+static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf,
+ struct otx2_qos_cfg *cfg)
+{
+ struct nix_txsch_alloc_req *req;
+ struct nix_txsch_alloc_rsp *rsp;
+ struct mbox *mbox = &pfvf->mbox;
+ int lvl, rc, schq;
+
+ mutex_lock(&mbox->lock);
+ req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
+ if (!req) {
+ mutex_unlock(&mbox->lock);
+ return -ENOMEM;
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ req->schq[lvl] = cfg->schq[lvl];
+ req->schq_contig[lvl] = cfg->schq_contig[lvl];
+ }
+
+ rc = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (rc) {
+ mutex_unlock(&mbox->lock);
+ return rc;
+ }
+
+ rsp = (struct nix_txsch_alloc_rsp *)
+ otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+
+ if (IS_ERR(rsp)) {
+ rc = PTR_ERR(rsp);
+ goto out;
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (schq = 0; schq < rsp->schq_contig[lvl]; schq++) {
+ cfg->schq_contig_list[lvl][schq] =
+ rsp->schq_contig_list[lvl][schq];
+ }
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (schq = 0; schq < rsp->schq[lvl]; schq++) {
+ cfg->schq_list[lvl][schq] =
+ rsp->schq_list[lvl][schq];
+ }
+ }
+
+ pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl;
+
+out:
+ mutex_unlock(&mbox->lock);
+ return rc;
+}
+
+static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int cnt;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ cnt = cfg->dwrr_node_pos[tmp->level];
+ tmp->schq = cfg->schq_list[tmp->level][cnt];
+ cfg->dwrr_node_pos[tmp->level]++;
+ }
+}
+
+static void otx2_qos_txschq_fill_cfg_tl(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int cnt;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg);
+ cnt = cfg->static_node_pos[tmp->level];
+ tmp->schq = cfg->schq_contig_list[tmp->level][cnt];
+ if (cnt == 0)
+ node->prio_anchor = tmp->schq;
+ cfg->static_node_pos[tmp->level]++;
+ otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg);
+ }
+}
+
+static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg);
+ otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int ret;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ ret = otx2_qos_txschq_config(pfvf, tmp);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_set_parent_topology(pfvf, tmp->parent);
+ if (ret)
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int otx2_qos_txschq_push_cfg_tl(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ struct otx2_qos_node *tmp;
+ int ret;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ ret = otx2_qos_txschq_push_cfg_tl(pfvf, tmp, cfg);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_config(pfvf, tmp);
+ if (ret)
+ return -EIO;
+ ret = otx2_qos_txschq_push_cfg_schq(pfvf, tmp, cfg);
+ if (ret)
+ return -EIO;
+ }
+
+ ret = otx2_qos_txschq_set_parent_topology(pfvf, node);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+static int otx2_qos_txschq_push_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ int ret;
+
+ mutex_lock(&pfvf->qos.qos_lock);
+ ret = otx2_qos_txschq_push_cfg_tl(pfvf, node, cfg);
+ if (ret)
+ goto out;
+ ret = otx2_qos_txschq_push_cfg_schq(pfvf, node, cfg);
+out:
+ mutex_unlock(&pfvf->qos.qos_lock);
+ return ret;
+}
+
+static int otx2_qos_txschq_update_config(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
+
+ return otx2_qos_txschq_push_cfg(pfvf, node, cfg);
+}
+
+static int otx2_qos_txschq_update_root_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *root,
+ struct otx2_qos_cfg *cfg)
+{
+ root->schq = cfg->schq_list[root->level][0];
+ return otx2_qos_txschq_config(pfvf, root);
+}
+
+static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
+{
+ int lvl, idx, schq;
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (idx = 0; idx < cfg->schq[lvl]; idx++) {
+ schq = cfg->schq_list[lvl][idx];
+ otx2_txschq_free_one(pfvf, lvl, schq);
+ }
+ }
+
+ for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+ for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
+ schq = cfg->schq_contig_list[lvl][idx];
+ otx2_txschq_free_one(pfvf, lvl, schq);
+ }
+ }
+}
+
+static void otx2_qos_enadis_sq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ u16 qid)
+{
+ if (pfvf->qos.qid_to_sqmap[qid] != OTX2_QOS_INVALID_SQ)
+ otx2_qos_disable_sq(pfvf, qid);
+
+ pfvf->qos.qid_to_sqmap[qid] = node->schq;
+ otx2_qos_enable_sq(pfvf, qid);
+}
+
+static void otx2_qos_update_smq_schq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ struct otx2_qos_node *tmp;
+
+ if (node->qid == OTX2_QOS_QID_INNER)
+ return;
+
+ list_for_each_entry(tmp, &node->child_schq_list, list) {
+ if (tmp->level == NIX_TXSCH_LVL_MDQ) {
+ if (action == QOS_SMQ_FLUSH)
+ otx2_smq_flush(pfvf, tmp->schq);
+ else
+ otx2_qos_enadis_sq(pfvf, tmp, node->qid);
+ }
+ }
+}
+
+static void __otx2_qos_update_smq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ struct otx2_qos_node *tmp;
+
+ list_for_each_entry(tmp, &node->child_list, list) {
+ __otx2_qos_update_smq(pfvf, tmp, action);
+ if (tmp->qid == OTX2_QOS_QID_INNER)
+ continue;
+ if (tmp->level == NIX_TXSCH_LVL_MDQ) {
+ if (action == QOS_SMQ_FLUSH)
+ otx2_smq_flush(pfvf, tmp->schq);
+ else
+ otx2_qos_enadis_sq(pfvf, tmp, tmp->qid);
+ } else {
+ otx2_qos_update_smq_schq(pfvf, tmp, action);
+ }
+ }
+}
+
+static void otx2_qos_update_smq(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ bool action)
+{
+ mutex_lock(&pfvf->qos.qos_lock);
+ __otx2_qos_update_smq(pfvf, node, action);
+ otx2_qos_update_smq_schq(pfvf, node, action);
+ mutex_unlock(&pfvf->qos.qos_lock);
+}
+
+static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ int ret;
+
+ ret = otx2_qos_txschq_alloc(pfvf, cfg);
+ if (ret)
+ return -ENOSPC;
+
+ if (!(pfvf->netdev->flags & IFF_UP)) {
+ otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
+ return 0;
+ }
+
+ ret = otx2_qos_txschq_update_config(pfvf, node, cfg);
+ if (ret) {
+ otx2_qos_free_cfg(pfvf, cfg);
+ return -EIO;
+ }
+
+ otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
+
+ return 0;
+}
+
+static int otx2_qos_update_tree(struct otx2_nic *pfvf,
+ struct otx2_qos_node *node,
+ struct otx2_qos_cfg *cfg)
+{
+ otx2_qos_prepare_txschq_cfg(pfvf, node->parent, cfg);
+ return otx2_qos_push_txschq_cfg(pfvf, node->parent, cfg);
+}
+
+static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defcls,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *new_cfg;
+ struct otx2_qos_node *root;
+ int err;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_CREATE: handle=0x%x defcls=0x%x\n",
+ htb_maj_id, htb_defcls);
+
+ root = otx2_qos_alloc_root(pfvf);
+ if (IS_ERR(root)) {
+ err = PTR_ERR(root);
+ return err;
+ }
+
+ /* allocate txschq queue */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ err = -ENOMEM;
+ goto free_root_node;
+ }
+ /* allocate htb root node */
+ new_cfg->schq[root->level] = 1;
+ err = otx2_qos_txschq_alloc(pfvf, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Error allocating txschq");
+ goto free_root_node;
+ }
+
+ if (!(pfvf->netdev->flags & IFF_UP) ||
+ root->level == NIX_TXSCH_LVL_TL1) {
+ root->schq = new_cfg->schq_list[root->level][0];
+ goto out;
+ }
+
+ /* update the txschq configuration in hw */
+ err = otx2_qos_txschq_update_root_cfg(pfvf, root, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Error updating txschq configuration");
+ goto txschq_free;
+ }
+
+out:
+ WRITE_ONCE(pfvf->qos.defcls, htb_defcls);
+ /* Pairs with smp_load_acquire() in ndo_select_queue */
+ smp_store_release(&pfvf->qos.maj_id, htb_maj_id);
+ kfree(new_cfg);
+ return 0;
+
+txschq_free:
+ otx2_qos_free_cfg(pfvf, new_cfg);
+free_root_node:
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, root);
+ return err;
+}
+
+static int otx2_qos_root_destroy(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+
+ netdev_dbg(pfvf->netdev, "TC_HTB_DESTROY\n");
+
+ /* find root node */
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return -ENOENT;
+
+ /* free the hw mappings */
+ otx2_qos_destroy_node(pfvf, root);
+
+ return 0;
+}
+
+static int otx2_qos_validate_configuration(struct otx2_qos_node *parent,
+ struct netlink_ext_ack *extack,
+ struct otx2_nic *pfvf,
+ u64 prio)
+{
+ if (test_bit(prio, parent->prio_bmap)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Static priority child with same priority exists");
+ return -EEXIST;
+ }
+
+ if (prio == TXSCH_TL1_DFLT_RR_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Priority is reserved for Round Robin");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid,
+ u32 parent_classid, u64 rate, u64 ceil,
+ u64 prio, struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *old_cfg, *new_cfg;
+ struct otx2_qos_node *node, *parent;
+ int qid, ret, err;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld\n",
+ classid, parent_classid, rate, ceil, prio);
+
+ if (prio > OTX2_QOS_MAX_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* get parent node */
+ parent = otx2_sw_node_find(pfvf, parent_classid);
+ if (!parent) {
+ NL_SET_ERR_MSG_MOD(extack, "parent node not found");
+ ret = -ENOENT;
+ goto out;
+ }
+ if (parent->level == NIX_TXSCH_LVL_MDQ) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB qos max levels reached");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio);
+ if (ret)
+ goto out;
+
+ set_bit(prio, parent->prio_bmap);
+
+ /* read current txschq configuration */
+ old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
+ if (!old_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto reset_prio;
+ }
+ otx2_qos_read_txschq_cfg(pfvf, parent, old_cfg);
+
+ /* allocate a new sq */
+ qid = otx2_qos_get_qid(pfvf);
+ if (qid < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Reached max supported QOS SQ's");
+ ret = -ENOMEM;
+ goto free_old_cfg;
+ }
+
+ /* Actual SQ mapping will be updated after SMQ alloc */
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ /* allocate and initialize a new child node */
+ node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate,
+ ceil, qid);
+ if (IS_ERR(node)) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
+ ret = PTR_ERR(node);
+ goto free_old_cfg;
+ }
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto free_node;
+ }
+ ret = otx2_qos_update_tree(pfvf, node, new_cfg);
+ if (ret) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, node);
+ /* restore the old qos tree */
+ err = otx2_qos_txschq_update_config(pfvf, parent, old_cfg);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore txcshq configuration");
+ goto free_old_cfg;
+ }
+
+ otx2_qos_update_smq(pfvf, parent, QOS_CFG_SQ);
+ goto free_old_cfg;
+ }
+
+ /* update tx_real_queues */
+ otx2_qos_update_tx_netdev_queues(pfvf);
+
+ /* free new txschq config */
+ kfree(new_cfg);
+
+ /* free old txschq config */
+ otx2_qos_free_cfg(pfvf, old_cfg);
+ kfree(old_cfg);
+
+ return pfvf->hw.tx_queues + qid;
+
+free_node:
+ otx2_qos_sw_node_delete(pfvf, node);
+free_old_cfg:
+ kfree(old_cfg);
+reset_prio:
+ clear_bit(prio, parent->prio_bmap);
+out:
+ return ret;
+}
+
+static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid,
+ u16 child_classid, u64 rate, u64 ceil, u64 prio,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_cfg *old_cfg, *new_cfg;
+ struct otx2_qos_node *node, *child;
+ int ret, err;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_TO_INNER classid %04x, child %04x, rate %llu, ceil %llu\n",
+ classid, child_classid, rate, ceil);
+
+ if (prio > OTX2_QOS_MAX_PRIO) {
+ NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ ret = -ENOENT;
+ goto out;
+ }
+ /* check max qos txschq level */
+ if (node->level == NIX_TXSCH_LVL_MDQ) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB qos level not supported");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ set_bit(prio, node->prio_bmap);
+
+ /* store the qid to assign to leaf node */
+ qid = node->qid;
+
+ /* read current txschq configuration */
+ old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
+ if (!old_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto reset_prio;
+ }
+ otx2_qos_read_txschq_cfg(pfvf, node, old_cfg);
+
+ /* delete the txschq nodes allocated for this node */
+ otx2_qos_free_sw_node_schq(pfvf, node);
+
+ /* mark this node as htb inner node */
+ WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
+
+ /* allocate and initialize a new child node */
+ child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid,
+ prio, rate, ceil, qid);
+ if (IS_ERR(child)) {
+ NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
+ ret = PTR_ERR(child);
+ goto free_old_cfg;
+ }
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ ret = -ENOMEM;
+ goto free_node;
+ }
+ ret = otx2_qos_update_tree(pfvf, child, new_cfg);
+ if (ret) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ otx2_qos_sw_node_delete(pfvf, child);
+ /* restore the old qos tree */
+ WRITE_ONCE(node->qid, qid);
+ err = otx2_qos_alloc_txschq_node(pfvf, node);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore old leaf node");
+ goto free_old_cfg;
+ }
+ err = otx2_qos_txschq_update_config(pfvf, node, old_cfg);
+ if (err) {
+ netdev_err(pfvf->netdev,
+ "Failed to restore txcshq configuration");
+ goto free_old_cfg;
+ }
+ otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
+ goto free_old_cfg;
+ }
+
+ /* free new txschq config */
+ kfree(new_cfg);
+
+ /* free old txschq config */
+ otx2_qos_free_cfg(pfvf, old_cfg);
+ kfree(old_cfg);
+
+ return 0;
+
+free_node:
+ otx2_qos_sw_node_delete(pfvf, child);
+free_old_cfg:
+ kfree(old_cfg);
+reset_prio:
+ clear_bit(prio, node->prio_bmap);
+out:
+ return ret;
+}
+
+static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_node *node, *parent;
+ u64 prio;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid);
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, *classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ return -ENOENT;
+ }
+ parent = node->parent;
+ prio = node->prio;
+ qid = node->qid;
+
+ otx2_qos_disable_sq(pfvf, node->qid);
+
+ otx2_qos_destroy_node(pfvf, node);
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ clear_bit(prio, parent->prio_bmap);
+
+ return 0;
+}
+
+static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force,
+ struct netlink_ext_ack *extack)
+{
+ struct otx2_qos_node *node, *parent;
+ struct otx2_qos_cfg *new_cfg;
+ u64 prio;
+ int err;
+ u16 qid;
+
+ netdev_dbg(pfvf->netdev,
+ "TC_HTB_LEAF_DEL_LAST classid %04x\n", classid);
+
+ /* find node related to classid */
+ node = otx2_sw_node_find(pfvf, classid);
+ if (!node) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
+ return -ENOENT;
+ }
+
+ /* save qid for use by parent */
+ qid = node->qid;
+ prio = node->prio;
+
+ parent = otx2_sw_node_find(pfvf, node->parent->classid);
+ if (!parent) {
+ NL_SET_ERR_MSG_MOD(extack, "parent node not found");
+ return -ENOENT;
+ }
+
+ /* destroy the leaf node */
+ otx2_qos_destroy_node(pfvf, node);
+ pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
+
+ clear_bit(prio, parent->prio_bmap);
+
+ /* create downstream txschq entries to parent */
+ err = otx2_qos_alloc_txschq_node(pfvf, parent);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB failed to create txsch configuration");
+ return err;
+ }
+ WRITE_ONCE(parent->qid, qid);
+ __set_bit(qid, pfvf->qos.qos_sq_bmap);
+
+ /* push new txschq config to hw */
+ new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
+ if (!new_cfg) {
+ NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
+ return -ENOMEM;
+ }
+ /* fill txschq cfg and push txschq cfg to hw */
+ otx2_qos_fill_cfg_schq(parent, new_cfg);
+ err = otx2_qos_push_txschq_cfg(pfvf, parent, new_cfg);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
+ kfree(new_cfg);
+ return err;
+ }
+ kfree(new_cfg);
+
+ /* update tx_real_queues */
+ otx2_qos_update_tx_netdev_queues(pfvf);
+
+ return 0;
+}
+
+void otx2_clean_qos_queues(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return;
+
+ otx2_qos_update_smq(pfvf, root, QOS_SMQ_FLUSH);
+}
+
+void otx2_qos_config_txschq(struct otx2_nic *pfvf)
+{
+ struct otx2_qos_node *root;
+ int err;
+
+ root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
+ if (!root)
+ return;
+
+ err = otx2_qos_txschq_config(pfvf, root);
+ if (err) {
+ netdev_err(pfvf->netdev, "Error update txschq configuration\n");
+ goto root_destroy;
+ }
+
+ err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL);
+ if (err) {
+ netdev_err(pfvf->netdev, "Error update txschq configuration\n");
+ goto root_destroy;
+ }
+
+ otx2_qos_update_smq(pfvf, root, QOS_CFG_SQ);
+ return;
+
+root_destroy:
+ netdev_err(pfvf->netdev, "Failed to update Scheduler/Shaping config in Hardware\n");
+ /* Free resources allocated */
+ otx2_qos_root_destroy(pfvf);
+}
+
+int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb)
+{
+ struct otx2_nic *pfvf = netdev_priv(ndev);
+ int res;
+
+ switch (htb->command) {
+ case TC_HTB_CREATE:
+ return otx2_qos_root_add(pfvf, htb->parent_classid,
+ htb->classid, htb->extack);
+ case TC_HTB_DESTROY:
+ return otx2_qos_root_destroy(pfvf);
+ case TC_HTB_LEAF_ALLOC_QUEUE:
+ res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid,
+ htb->parent_classid,
+ htb->rate, htb->ceil,
+ htb->prio, htb->extack);
+ if (res < 0)
+ return res;
+ htb->qid = res;
+ return 0;
+ case TC_HTB_LEAF_TO_INNER:
+ return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid,
+ htb->classid, htb->rate,
+ htb->ceil, htb->prio,
+ htb->extack);
+ case TC_HTB_LEAF_DEL:
+ return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack);
+ case TC_HTB_LEAF_DEL_LAST:
+ case TC_HTB_LEAF_DEL_LAST_FORCE:
+ return otx2_qos_leaf_del_last(pfvf, htb->classid,
+ htb->command == TC_HTB_LEAF_DEL_LAST_FORCE,
+ htb->extack);
+ case TC_HTB_LEAF_QUERY_QUEUE:
+ res = otx2_get_txq_by_classid(pfvf, htb->classid);
+ htb->qid = res;
+ return 0;
+ case TC_HTB_NODE_MODIFY:
+ fallthrough;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.h b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h
new file mode 100644
index 000000000000..19773284be27
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell RVU Ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+#ifndef OTX2_QOS_H
+#define OTX2_QOS_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/rhashtable.h>
+
+#define OTX2_QOS_MAX_LVL 4
+#define OTX2_QOS_MAX_PRIO 7
+#define OTX2_QOS_MAX_LEAF_NODES 16
+
+enum qos_smq_operations {
+ QOS_CFG_SQ,
+ QOS_SMQ_FLUSH,
+};
+
+u64 otx2_get_txschq_rate_regval(struct otx2_nic *nic, u64 maxrate, u32 burst);
+
+int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb);
+int otx2_qos_get_qid(struct otx2_nic *pfvf);
+void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx);
+int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx);
+void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx);
+
+struct otx2_qos_cfg {
+ u16 schq[NIX_TXSCH_LVL_CNT];
+ u16 schq_contig[NIX_TXSCH_LVL_CNT];
+ int static_node_pos[NIX_TXSCH_LVL_CNT];
+ int dwrr_node_pos[NIX_TXSCH_LVL_CNT];
+ u16 schq_contig_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+ u16 schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+};
+
+struct otx2_qos {
+ DECLARE_HASHTABLE(qos_hlist, order_base_2(OTX2_QOS_MAX_LEAF_NODES));
+ struct mutex qos_lock; /* child list lock */
+ u16 qid_to_sqmap[OTX2_QOS_MAX_LEAF_NODES];
+ struct list_head qos_tree;
+ DECLARE_BITMAP(qos_sq_bmap, OTX2_QOS_MAX_LEAF_NODES);
+ u16 maj_id;
+ u16 defcls;
+ u8 link_cfg_lvl; /* LINKX_CFG CSRs mapped to TL3 or TL2's index ? */
+};
+
+struct otx2_qos_node {
+ struct list_head list; /* list management */
+ struct list_head child_list;
+ struct list_head child_schq_list;
+ struct hlist_node hlist;
+ DECLARE_BITMAP(prio_bmap, OTX2_QOS_MAX_PRIO + 1);
+ struct otx2_qos_node *parent; /* parent qos node */
+ u64 rate; /* htb params */
+ u64 ceil;
+ u32 classid;
+ u32 prio;
+ u16 schq; /* hw txschq */
+ u16 qid;
+ u16 prio_anchor;
+ u8 level;
+};
+
+
+#endif
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c
new file mode 100644
index 000000000000..9d887bfc3108
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell RVU Physical Function ethernet driver
+ *
+ * Copyright (C) 2023 Marvell.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <net/tso.h>
+
+#include "cn10k.h"
+#include "otx2_reg.h"
+#include "otx2_common.h"
+#include "otx2_txrx.h"
+#include "otx2_struct.h"
+
+#define OTX2_QOS_MAX_LEAF_NODES 16
+
+static void otx2_qos_aura_pool_free(struct otx2_nic *pfvf, int pool_id)
+{
+ struct otx2_pool *pool;
+
+ if (!pfvf->qset.pool)
+ return;
+
+ pool = &pfvf->qset.pool[pool_id];
+ qmem_free(pfvf->dev, pool->stack);
+ qmem_free(pfvf->dev, pool->fc_addr);
+ pool->stack = NULL;
+ pool->fc_addr = NULL;
+}
+
+static int otx2_qos_sq_aura_pool_init(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ int pool_id, stack_pages, num_sqbs;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ struct otx2_pool *pool;
+ dma_addr_t bufptr;
+ int err, ptr;
+ u64 iova, pa;
+
+ /* Calculate number of SQBs needed.
+ *
+ * For a 128byte SQE, and 4K size SQB, 31 SQEs will fit in one SQB.
+ * Last SQE is used for pointing to next SQB.
+ */
+ num_sqbs = (hw->sqb_size / 128) - 1;
+ num_sqbs = (qset->sqe_cnt + num_sqbs) / num_sqbs;
+
+ /* Get no of stack pages needed */
+ stack_pages =
+ (num_sqbs + hw->stack_pg_ptrs - 1) / hw->stack_pg_ptrs;
+
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx);
+ pool = &pfvf->qset.pool[pool_id];
+
+ /* Initialize aura context */
+ err = otx2_aura_init(pfvf, pool_id, pool_id, num_sqbs);
+ if (err)
+ return err;
+
+ /* Initialize pool context */
+ err = otx2_pool_init(pfvf, pool_id, stack_pages,
+ num_sqbs, hw->sqb_size, AURA_NIX_SQ);
+ if (err)
+ goto aura_free;
+
+ /* Flush accumulated messages */
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
+ if (err)
+ goto pool_free;
+
+ /* Allocate pointers and free them to aura/pool */
+ sq = &qset->sq[qidx];
+ sq->sqb_count = 0;
+ sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL);
+ if (!sq->sqb_ptrs) {
+ err = -ENOMEM;
+ goto pool_free;
+ }
+
+ for (ptr = 0; ptr < num_sqbs; ptr++) {
+ err = otx2_alloc_rbuf(pfvf, pool, &bufptr);
+ if (err)
+ goto sqb_free;
+ pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr);
+ sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr;
+ }
+
+ return 0;
+
+sqb_free:
+ while (ptr--) {
+ if (!sq->sqb_ptrs[ptr])
+ continue;
+ iova = sq->sqb_ptrs[ptr];
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ put_page(virt_to_page(phys_to_virt(pa)));
+ otx2_aura_allocptr(pfvf, pool_id);
+ }
+ sq->sqb_count = 0;
+ kfree(sq->sqb_ptrs);
+pool_free:
+ qmem_free(pfvf->dev, pool->stack);
+aura_free:
+ qmem_free(pfvf->dev, pool->fc_addr);
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return err;
+}
+
+static void otx2_qos_sq_free_sqbs(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ u64 iova, pa;
+ int sqb;
+
+ sq = &qset->sq[qidx];
+ if (!sq->sqb_ptrs)
+ return;
+ for (sqb = 0; sqb < sq->sqb_count; sqb++) {
+ if (!sq->sqb_ptrs[sqb])
+ continue;
+ iova = sq->sqb_ptrs[sqb];
+ pa = otx2_iova_to_phys(pfvf->iommu_domain, iova);
+ dma_unmap_page_attrs(pfvf->dev, iova, hw->sqb_size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ put_page(virt_to_page(phys_to_virt(pa)));
+ }
+
+ sq->sqb_count = 0;
+
+ sq = &qset->sq[qidx];
+ qmem_free(pfvf->dev, sq->sqe);
+ qmem_free(pfvf->dev, sq->tso_hdrs);
+ kfree(sq->sg);
+ kfree(sq->sqb_ptrs);
+ qmem_free(pfvf->dev, sq->timestamps);
+
+ memset((void *)sq, 0, sizeof(*sq));
+}
+
+/* send queue id */
+static void otx2_qos_sqb_flush(struct otx2_nic *pfvf, int qidx)
+{
+ int sqe_tail, sqe_head;
+ u64 incr, *ptr, val;
+
+ ptr = (__force u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
+ incr = (u64)qidx << 32;
+ val = otx2_atomic64_add(incr, ptr);
+ sqe_head = (val >> 20) & 0x3F;
+ sqe_tail = (val >> 28) & 0x3F;
+ if (sqe_head != sqe_tail)
+ usleep_range(50, 60);
+}
+
+static int otx2_qos_ctx_disable(struct otx2_nic *pfvf, u16 qidx, int aura_id)
+{
+ struct nix_cn10k_aq_enq_req *cn10k_sq_aq;
+ struct npa_aq_enq_req *aura_aq;
+ struct npa_aq_enq_req *pool_aq;
+ struct nix_aq_enq_req *sq_aq;
+
+ if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
+ cn10k_sq_aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
+ if (!cn10k_sq_aq)
+ return -ENOMEM;
+ cn10k_sq_aq->qidx = qidx;
+ cn10k_sq_aq->sq.ena = 0;
+ cn10k_sq_aq->sq_mask.ena = 1;
+ cn10k_sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+ cn10k_sq_aq->op = NIX_AQ_INSTOP_WRITE;
+ } else {
+ sq_aq = otx2_mbox_alloc_msg_nix_aq_enq(&pfvf->mbox);
+ if (!sq_aq)
+ return -ENOMEM;
+ sq_aq->qidx = qidx;
+ sq_aq->sq.ena = 0;
+ sq_aq->sq_mask.ena = 1;
+ sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+ sq_aq->op = NIX_AQ_INSTOP_WRITE;
+ }
+
+ aura_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
+ if (!aura_aq) {
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return -ENOMEM;
+ }
+
+ aura_aq->aura_id = aura_id;
+ aura_aq->aura.ena = 0;
+ aura_aq->aura_mask.ena = 1;
+ aura_aq->ctype = NPA_AQ_CTYPE_AURA;
+ aura_aq->op = NPA_AQ_INSTOP_WRITE;
+
+ pool_aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
+ if (!pool_aq) {
+ otx2_mbox_reset(&pfvf->mbox.mbox, 0);
+ return -ENOMEM;
+ }
+
+ pool_aq->aura_id = aura_id;
+ pool_aq->pool.ena = 0;
+ pool_aq->pool_mask.ena = 1;
+
+ pool_aq->ctype = NPA_AQ_CTYPE_POOL;
+ pool_aq->op = NPA_AQ_INSTOP_WRITE;
+
+ return otx2_sync_mbox_msg(&pfvf->mbox);
+}
+
+int otx2_qos_get_qid(struct otx2_nic *pfvf)
+{
+ int qidx;
+
+ qidx = find_first_zero_bit(pfvf->qos.qos_sq_bmap,
+ pfvf->hw.tc_tx_queues);
+
+ return qidx == pfvf->hw.tc_tx_queues ? -ENOSPC : qidx;
+}
+
+void otx2_qos_free_qid(struct otx2_nic *pfvf, int qidx)
+{
+ clear_bit(qidx, pfvf->qos.qos_sq_bmap);
+}
+
+int otx2_qos_enable_sq(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_hw *hw = &pfvf->hw;
+ int pool_id, sq_idx, err;
+
+ if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
+ return -EPERM;
+
+ sq_idx = hw->non_qos_queues + qidx;
+
+ mutex_lock(&pfvf->mbox.lock);
+ err = otx2_qos_sq_aura_pool_init(pfvf, sq_idx);
+ if (err)
+ goto out;
+
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
+ err = otx2_sq_init(pfvf, sq_idx, pool_id);
+ if (err)
+ goto out;
+out:
+ mutex_unlock(&pfvf->mbox.lock);
+ return err;
+}
+
+void otx2_qos_disable_sq(struct otx2_nic *pfvf, int qidx)
+{
+ struct otx2_qset *qset = &pfvf->qset;
+ struct otx2_hw *hw = &pfvf->hw;
+ struct otx2_snd_queue *sq;
+ struct otx2_cq_queue *cq;
+ int pool_id, sq_idx;
+
+ sq_idx = hw->non_qos_queues + qidx;
+
+ /* If the DOWN flag is set SQs are already freed */
+ if (pfvf->flags & OTX2_FLAG_INTF_DOWN)
+ return;
+
+ sq = &pfvf->qset.sq[sq_idx];
+ if (!sq->sqb_ptrs)
+ return;
+
+ if (sq_idx < hw->non_qos_queues ||
+ sq_idx >= otx2_get_total_tx_queues(pfvf)) {
+ netdev_err(pfvf->netdev, "Send Queue is not a QoS queue\n");
+ return;
+ }
+
+ cq = &qset->cq[pfvf->hw.rx_queues + sq_idx];
+ pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, sq_idx);
+
+ otx2_qos_sqb_flush(pfvf, sq_idx);
+ otx2_smq_flush(pfvf, otx2_get_smq_idx(pfvf, sq_idx));
+ otx2_cleanup_tx_cqes(pfvf, cq);
+
+ mutex_lock(&pfvf->mbox.lock);
+ otx2_qos_ctx_disable(pfvf, sq_idx, pool_id);
+ mutex_unlock(&pfvf->mbox.lock);
+
+ otx2_qos_sq_free_sqbs(pfvf, sq_idx);
+ otx2_qos_aura_pool_free(pfvf, pool_id);
+}
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c
index 91a478b75cbf..3e20e71b0f81 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c
@@ -148,6 +148,12 @@ static int prestera_flower_parse_meta(struct prestera_acl_rule *rule,
__be16 key, mask;
flow_rule_match_meta(f_rule, &match);
+
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+
if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported ingress ifindex mask");
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c
index 9d504142e51a..4fb886c57cd7 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c
@@ -300,8 +300,7 @@ static void prestera_pcs_get_state(struct phylink_pcs *pcs,
}
}
-static int prestera_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int prestera_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -316,30 +315,25 @@ static int prestera_pcs_config(struct phylink_pcs *pcs,
cfg_mac.admin = true;
cfg_mac.fec = PRESTERA_PORT_FEC_OFF;
+ cfg_mac.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
switch (interface) {
case PHY_INTERFACE_MODE_10GBASER:
cfg_mac.speed = SPEED_10000;
- cfg_mac.inband = 0;
cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR;
break;
case PHY_INTERFACE_MODE_2500BASEX:
cfg_mac.speed = SPEED_2500;
cfg_mac.duplex = DUPLEX_FULL;
- cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;
break;
case PHY_INTERFACE_MODE_SGMII:
- cfg_mac.inband = 1;
cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;
break;
case PHY_INTERFACE_MODE_1000BASEX:
default:
cfg_mac.speed = SPEED_1000;
cfg_mac.duplex = DUPLEX_FULL;
- cfg_mac.inband = test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;
break;
}
@@ -401,6 +395,7 @@ static int prestera_port_sfp_bind(struct prestera_port *port)
continue;
port->phylink_pcs.ops = &prestera_pcs_ops;
+ port->phylink_pcs.neg_mode = true;
port->phy_config.dev = &port->dev->dev;
port->phy_config.type = PHYLINK_NETDEV;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_pci.c b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
index f328d957b2db..35857dc19542 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_pci.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_pci.c
@@ -727,7 +727,8 @@ pick_fw_ver:
err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
if (err) {
- if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) {
+ if (ver_maj != PRESTERA_PREV_FW_MAJ_VER ||
+ ver_min != PRESTERA_PREV_FW_MIN_VER) {
ver_maj = PRESTERA_PREV_FW_MAJ_VER;
ver_min = PRESTERA_PREV_FW_MIN_VER;
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
index a9a1028cb17b..de317179a7dc 100644
--- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
+++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
@@ -166,11 +166,11 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
static bool __prestera_fi_is_direct(struct fib_info *fi)
{
- struct fib_nh *fib_nh;
+ struct fib_nh_common *fib_nhc;
if (fib_info_num_path(fi) == 1) {
- fib_nh = fib_info_nh(fi, 0);
- if (fib_nh->fib_nh_gw_family == AF_UNSPEC)
+ fib_nhc = fib_info_nhc(fi, 0);
+ if (fib_nhc->nhc_gw_family == AF_UNSPEC)
return true;
}
@@ -261,7 +261,7 @@ static bool
__prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
struct net_device *dev)
{
- struct fib_nh *fib_nh;
+ struct fib_nh_common *fib_nhc;
struct fib_result res;
bool reachable;
@@ -269,8 +269,8 @@ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
if (!prestera_util_kern_get_route(&res, tb_id, addr))
if (prestera_fi_is_direct(res.fi)) {
- fib_nh = fib_info_nh(res.fi, 0);
- if (dev == fib_nh->fib_nh_dev)
+ fib_nhc = fib_info_nhc(res.fi, 0);
+ if (dev == fib_nhc->nhc_dev)
reachable = true;
}
@@ -324,7 +324,7 @@ prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n)
if (info->family == AF_INET) {
fen4_info = container_of(info, struct fib_entry_notifier_info,
info);
- return &fib_info_nh(fen4_info->fi, n)->nh_common;
+ return fib_info_nhc(fen4_info->fi, n);
} else if (info->family == AF_INET6) {
fen6_info = container_of(info, struct fib6_entry_notifier_info,
info);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 834c644b67db..7f0807672071 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2860,6 +2860,9 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
int i;
for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (cnt == cmd->rule_cnt)
+ return -EMSGSIZE;
+
if (mac->hwlro_ip[i]) {
rule_locs[cnt] = i;
cnt++;
@@ -3846,23 +3849,6 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
return 0;
}
-static int __init mtk_init(struct net_device *dev)
-{
- struct mtk_mac *mac = netdev_priv(dev);
- struct mtk_eth *eth = mac->hw;
- int ret;
-
- ret = of_get_ethdev_address(mac->of_node, dev);
- if (ret) {
- /* If the mac address is invalid, use random mac address */
- eth_hw_addr_random(dev);
- dev_err(eth->dev, "generated random MAC address %pM\n",
- dev->dev_addr);
- }
-
- return 0;
-}
-
static void mtk_uninit(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -4278,7 +4264,6 @@ static const struct ethtool_ops mtk_ethtool_ops = {
};
static const struct net_device_ops mtk_netdev_ops = {
- .ndo_init = mtk_init,
.ndo_uninit = mtk_uninit,
.ndo_open = mtk_open,
.ndo_stop = mtk_stop,
@@ -4340,6 +4325,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->hw = eth;
mac->of_node = np;
+ err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
+ if (err == -EPROBE_DEFER)
+ return err;
+
+ if (err) {
+ /* If the mac address is invalid, use random mac address */
+ eth_hw_addr_random(eth->netdev[id]);
+ dev_err(eth->dev, "generated random MAC address %pM\n",
+ eth->netdev[id]->dev_addr);
+ }
+
memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
mac->hwlro_ip_cnt = 0;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
index 316fe2e70fea..1a97feca77f2 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
acct = mtk_foe_entry_get_mib(ppe, i, NULL);
- type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
+ type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1);
seq_printf(m, "%05x %s %7s", i,
mtk_foe_entry_state_str(state),
mtk_foe_pkt_type_str(type));
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
index 985cff910f30..3b651efcc25e 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -221,9 +221,13 @@ void mtk_wed_fe_reset(void)
for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
- struct mtk_wed_device *dev = hw->wed_dev;
+ struct mtk_wed_device *dev;
int err;
+ if (!hw)
+ break;
+
+ dev = hw->wed_dev;
if (!dev || !dev->wlan.reset)
continue;
@@ -244,8 +248,12 @@ void mtk_wed_fe_reset_complete(void)
for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
- struct mtk_wed_device *dev = hw->wed_dev;
+ struct mtk_wed_device *dev;
+
+ if (!hw)
+ break;
+ dev = hw->wed_dev;
if (!dev || !dev->wlan.reset_complete)
continue;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 277738c50c56..61286b0d9b0c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1374,16 +1374,13 @@ static int mlx4_mf_bond(struct mlx4_dev *dev)
int nvfs;
struct mlx4_slaves_pport slaves_port1;
struct mlx4_slaves_pport slaves_port2;
- DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX);
slaves_port1 = mlx4_phys_to_slaves_pport(dev, 1);
slaves_port2 = mlx4_phys_to_slaves_pport(dev, 2);
- bitmap_and(slaves_port_1_2,
- slaves_port1.slaves, slaves_port2.slaves,
- dev->persist->num_vfs + 1);
/* only single port vfs are allowed */
- if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) {
+ if (bitmap_weight_and(slaves_port1.slaves, slaves_port2.slaves,
+ dev->persist->num_vfs + 1) > 1) {
mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n");
return -EINVAL;
}
@@ -3027,13 +3024,43 @@ no_msi:
}
}
+static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
+ enum devlink_port_type port_type)
+{
+ struct mlx4_port_info *info = container_of(devlink_port,
+ struct mlx4_port_info,
+ devlink_port);
+ enum mlx4_port_type mlx4_port_type;
+
+ switch (port_type) {
+ case DEVLINK_PORT_TYPE_AUTO:
+ mlx4_port_type = MLX4_PORT_TYPE_AUTO;
+ break;
+ case DEVLINK_PORT_TYPE_ETH:
+ mlx4_port_type = MLX4_PORT_TYPE_ETH;
+ break;
+ case DEVLINK_PORT_TYPE_IB:
+ mlx4_port_type = MLX4_PORT_TYPE_IB;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return __set_port_type(info, mlx4_port_type);
+}
+
+static const struct devlink_port_ops mlx4_devlink_port_ops = {
+ .port_type_set = mlx4_devlink_port_type_set,
+};
+
static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
{
struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
int err;
- err = devl_port_register(devlink, &info->devlink_port, port);
+ err = devl_port_register_with_ops(devlink, &info->devlink_port, port,
+ &mlx4_devlink_port_ops);
if (err)
return err;
@@ -3877,31 +3904,6 @@ err_disable_pdev:
return err;
}
-static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
- enum devlink_port_type port_type)
-{
- struct mlx4_port_info *info = container_of(devlink_port,
- struct mlx4_port_info,
- devlink_port);
- enum mlx4_port_type mlx4_port_type;
-
- switch (port_type) {
- case DEVLINK_PORT_TYPE_AUTO:
- mlx4_port_type = MLX4_PORT_TYPE_AUTO;
- break;
- case DEVLINK_PORT_TYPE_ETH:
- mlx4_port_type = MLX4_PORT_TYPE_ETH;
- break;
- case DEVLINK_PORT_TYPE_IB:
- mlx4_port_type = MLX4_PORT_TYPE_IB;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return __set_port_type(info, mlx4_port_type);
-}
-
static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
{
struct mlx4_priv *priv = devlink_priv(devlink);
@@ -3986,7 +3988,6 @@ static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
}
static const struct devlink_ops mlx4_devlink_ops = {
- .port_type_set = mlx4_devlink_port_type_set,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
.reload_down = mlx4_devlink_reload_down,
.reload_up = mlx4_devlink_reload_up,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index ddf1e352f51d..35f00700a4d6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -75,7 +75,8 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o
-mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o en/rep/bridge.o
+mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \
+ en/rep/bridge.o
mlx5_core-$(CONFIG_THERMAL) += thermal.o
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index bb95b40d25eb..2138f28a2931 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -246,6 +246,7 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev)
debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages);
debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]);
+ debugfs_create_u32("fw_pages_ec_vfs", 0400, pages, &dev->priv.page_counters[MLX5_EC_VF]);
debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]);
debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]);
debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed);
@@ -513,11 +514,11 @@ EXPORT_SYMBOL(mlx5_debug_qp_add);
void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp)
{
- if (!mlx5_debugfs_root)
+ if (!mlx5_debugfs_root || !qp->dbg)
return;
- if (qp->dbg)
- rem_res_tree(qp->dbg);
+ rem_res_tree(qp->dbg);
+ qp->dbg = NULL;
}
EXPORT_SYMBOL(mlx5_debug_qp_remove);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
index 1b33533b15de..edb06fb9bbc5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c
@@ -151,12 +151,6 @@ static bool is_ib_rep_supported(struct mlx5_core_dev *dev)
if (!is_eth_rep_supported(dev))
return false;
- if (!MLX5_ESWITCH_MANAGER(dev))
- return false;
-
- if (!is_mdev_switchdev_mode(dev))
- return false;
-
if (mlx5_core_mp_enabled(dev))
return false;
@@ -323,6 +317,18 @@ static void del_adev(struct auxiliary_device *adev)
auxiliary_device_uninit(adev);
}
+void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev)
+{
+ mutex_lock(&mlx5_intf_mutex);
+ dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
+ mutex_unlock(&mlx5_intf_mutex);
+}
+
+bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev)
+{
+ return dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV;
+}
+
int mlx5_attach_device(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
@@ -457,6 +463,10 @@ static int add_drivers(struct mlx5_core_dev *dev)
if (priv->adev[i])
continue;
+ if (mlx5_adev_devices[i].is_enabled &&
+ !(mlx5_adev_devices[i].is_enabled(dev)))
+ continue;
+
if (mlx5_adev_devices[i].is_supported)
is_supported = mlx5_adev_devices[i].is_supported(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index 4b607785d694..3d82ec890666 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -7,7 +7,6 @@
#include "fw_reset.h"
#include "fs_core.h"
#include "eswitch.h"
-#include "lag/lag.h"
#include "esw/qos.h"
#include "sf/dev/dev.h"
#include "sf/sf.h"
@@ -142,6 +141,13 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
bool sf_dev_allocated;
int ret = 0;
+ if (mlx5_dev_is_lightweight(dev)) {
+ if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
+ return -EOPNOTSUPP;
+ mlx5_unload_one_light(dev);
+ return 0;
+ }
+
sf_dev_allocated = mlx5_sf_dev_allocated(dev);
if (sf_dev_allocated) {
/* Reload results in deleting SF device which further results in
@@ -162,9 +168,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
return -EOPNOTSUPP;
}
- if (pci_num_vf(pdev)) {
+ if (mlx5_core_is_pf(dev) && pci_num_vf(pdev))
NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable");
- }
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
@@ -195,6 +200,10 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
*actions_performed = BIT(action);
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
+ if (mlx5_dev_is_lightweight(dev)) {
+ mlx5_fw_reporters_create(dev);
+ return mlx5_init_one_devl_locked(dev);
+ }
ret = mlx5_load_one_devl_locked(dev, false);
break;
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
@@ -311,8 +320,6 @@ static const struct devlink_ops mlx5_devlink_ops = {
.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
.eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set,
.eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get,
- .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get,
- .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set,
.rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set,
.rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set,
.rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set,
@@ -320,16 +327,9 @@ static const struct devlink_ops mlx5_devlink_ops = {
.rate_node_new = mlx5_esw_devlink_rate_node_new,
.rate_node_del = mlx5_esw_devlink_rate_node_del,
.rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
- .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
- .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
- .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
- .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
#endif
#ifdef CONFIG_MLX5_SF_MANAGER
.port_new = mlx5_devlink_sf_port_new,
- .port_del = mlx5_devlink_sf_port_del,
- .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
- .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
#endif
.flash_update = mlx5_devlink_flash_update,
.info_get = mlx5_devlink_info_get,
@@ -437,54 +437,6 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
return 0;
}
-
-static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- return -EOPNOTSUPP;
-
- if (ctx->val.vbool)
- return mlx5_lag_mpesw_enable(dev);
-
- mlx5_lag_mpesw_disable(dev);
- return 0;
-}
-
-static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- return -EOPNOTSUPP;
-
- ctx->val.vbool = mlx5_lag_is_mpesw(dev);
- return 0;
-}
-
-static int mlx5_devlink_esw_multiport_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
- struct netlink_ext_ack *extack)
-{
- struct mlx5_core_dev *dev = devlink_priv(devlink);
-
- if (!MLX5_ESWITCH_MANAGER(dev)) {
- NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
- return -EOPNOTSUPP;
- }
-
- if (mlx5_eswitch_mode(dev) != MLX5_ESWITCH_OFFLOADS) {
- NL_SET_ERR_MSG_MOD(extack,
- "E-Switch must be in switchdev mode");
- return -EBUSY;
- }
-
- return 0;
-}
-
#endif
static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
@@ -558,12 +510,6 @@ static const struct devlink_param mlx5_devlink_params[] = {
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL,
mlx5_devlink_large_group_num_validate),
- DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
- "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
- BIT(DEVLINK_PARAM_CMODE_RUNTIME),
- mlx5_devlink_esw_multiport_get,
- mlx5_devlink_esw_multiport_set,
- mlx5_devlink_esw_multiport_validate),
#endif
DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL, mlx5_devlink_eq_depth_validate),
@@ -576,7 +522,7 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
struct mlx5_core_dev *dev = devlink_priv(devlink);
union devlink_param_value value;
- value.vbool = MLX5_CAP_GEN(dev, roce);
+ value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
value);
@@ -626,7 +572,7 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
value);
@@ -666,6 +612,7 @@ static const struct devlink_param mlx5_devlink_rdma_params[] = {
static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
union devlink_param_value value;
int err;
@@ -677,7 +624,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
value);
@@ -712,7 +659,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
if (err)
return err;
- value.vbool = true;
+ value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
value);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
index 9114661cd967..e869c65d8e90 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */
#include "reporter_vnic.h"
+#include "en_stats.h"
#include "devlink.h"
#define VNIC_ENV_GET64(vnic_env_stats, c) \
@@ -36,45 +37,72 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev,
if (err)
return err;
- err = devlink_fmsg_u64_pair_put(fmsg, "total_error_queues",
- VNIC_ENV_GET64(&vnic, total_error_queues));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "send_queue_priority_update_flow",
- VNIC_ENV_GET64(&vnic, send_queue_priority_update_flow));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "comp_eq_overrun",
- VNIC_ENV_GET64(&vnic, comp_eq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "async_eq_overrun",
- VNIC_ENV_GET64(&vnic, async_eq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "cq_overrun",
- VNIC_ENV_GET64(&vnic, cq_overrun));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "invalid_command",
- VNIC_ENV_GET64(&vnic, invalid_command));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "quota_exceeded_command",
- VNIC_ENV_GET64(&vnic, quota_exceeded_command));
- if (err)
- return err;
-
- err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
- VNIC_ENV_GET64(&vnic, nic_receive_steering_discard));
- if (err)
- return err;
+ if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues",
+ VNIC_ENV_GET(&vnic, total_error_queues));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow",
+ VNIC_ENV_GET(&vnic,
+ send_queue_priority_update_flow));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, eq_overrun_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun",
+ VNIC_ENV_GET(&vnic, comp_eq_overrun));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun",
+ VNIC_ENV_GET(&vnic, async_eq_overrun));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun",
+ VNIC_ENV_GET(&vnic, cq_overrun));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, invalid_command_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command",
+ VNIC_ENV_GET(&vnic, invalid_command));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, quota_exceeded_count)) {
+ err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command",
+ VNIC_ENV_GET(&vnic, quota_exceeded_command));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) {
+ err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard",
+ VNIC_ENV_GET64(&vnic,
+ nic_receive_steering_discard));
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, vnic_env_cnt_steering_fail)) {
+ err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail",
+ VNIC_ENV_GET64(&vnic,
+ generated_pkt_steering_fail));
+ if (err)
+ return err;
+
+ err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail",
+ VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail));
+ if (err)
+ return err;
+ }
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 8e999f238194..b1807bfb815f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -165,15 +165,6 @@ struct page_pool;
#define MLX5E_MAX_KLM_PER_WQE(mdev) \
MLX5E_KLM_ENTRIES_PER_WQE(MLX5_SEND_WQE_BB * mlx5e_get_max_sq_aligned_wqebbs(mdev))
-#define MLX5E_MSG_LEVEL NETIF_MSG_LINK
-
-#define mlx5e_dbg(mlevel, priv, format, ...) \
-do { \
- if (NETIF_MSG_##mlevel & (priv)->msglevel) \
- netdev_warn(priv->netdev, format, \
- ##__VA_ARGS__); \
-} while (0)
-
#define mlx5e_state_dereference(priv, p) \
rcu_dereference_protected((p), lockdep_is_held(&(priv)->state_lock))
@@ -594,13 +585,6 @@ struct mlx5e_mpw_info {
#define MLX5E_MAX_RX_FRAGS 4
-/* a single cache unit is capable to serve one napi call (for non-striding rq)
- * or a MPWQE (for striding rq).
- */
-#define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \
- MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT)
-#define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT))
-
struct mlx5e_rq;
typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*);
typedef struct sk_buff *
@@ -887,7 +871,6 @@ struct mlx5e_priv {
#endif
/* priv data path fields - end */
- u32 msglevel;
unsigned long state;
struct mutex state_lock; /* Protects Interface state */
struct mlx5e_rq drop_rq;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
index 03cb79adf912..be83ad9db82a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
@@ -594,7 +594,7 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
err = fs_any_create_table(fs);
if (err)
- return err;
+ goto err_free_any;
err = fs_any_enable(fs);
if (err)
@@ -606,8 +606,8 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
err_destroy_table:
fs_any_destroy_table(fs_any);
-
- kfree(fs_any);
+err_free_any:
mlx5e_fs_set_any(fs, NULL);
+ kfree(fs_any);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
index 7e8e96cc5cd0..8e25f4ef5ccc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
@@ -65,12 +65,13 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz;
total_used += port_buffer->buffer[i].size;
- mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i,
- port_buffer->buffer[i].size,
- port_buffer->buffer[i].xon,
- port_buffer->buffer[i].xoff,
- port_buffer->buffer[i].epsb,
- port_buffer->buffer[i].lossy);
+ netdev_dbg(priv->netdev, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n",
+ i,
+ port_buffer->buffer[i].size,
+ port_buffer->buffer[i].xon,
+ port_buffer->buffer[i].xoff,
+ port_buffer->buffer[i].epsb,
+ port_buffer->buffer[i].lossy);
}
port_buffer->internal_buffers_size = 0;
@@ -87,11 +88,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
port_buffer->internal_buffers_size -
port_buffer->headroom_size;
- mlx5e_dbg(HW, priv,
- "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
- port_buffer->port_buffer_size, port_buffer->headroom_size,
- port_buffer->internal_buffers_size,
- port_buffer->spare_buffer_size);
+ netdev_dbg(priv->netdev,
+ "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n",
+ port_buffer->port_buffer_size, port_buffer->headroom_size,
+ port_buffer->internal_buffers_size,
+ port_buffer->spare_buffer_size);
out:
kfree(out);
return err;
@@ -352,7 +353,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100;
- mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff);
+ netdev_dbg(priv->netdev, "%s: xoff=%d\n", __func__, xoff);
return xoff;
}
@@ -484,6 +485,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
u8 *prio2buffer)
{
u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
+ struct net_device *netdev = priv->netdev;
struct mlx5e_port_buffer port_buffer;
u32 xoff = calculate_xoff(priv, mtu);
bool update_prio2buffer = false;
@@ -495,7 +497,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
int err;
int i;
- mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change);
+ netdev_dbg(netdev, "%s: change=%x\n", __func__, change);
max_mtu = max_t(unsigned int, priv->netdev->max_mtu, MINIMUM_MAX_MTU);
err = mlx5e_port_query_buffer(priv, &port_buffer);
@@ -510,8 +512,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
}
if (change & MLX5E_PORT_BUFFER_PFC) {
- mlx5e_dbg(HW, priv, "%s: requested PFC per priority bitmask: 0x%x\n",
- __func__, pfc->pfc_en);
+ netdev_dbg(netdev, "%s: requested PFC per priority bitmask: 0x%x\n",
+ __func__, pfc->pfc_en);
err = mlx5e_port_query_priority2buffer(priv->mdev, buffer);
if (err)
return err;
@@ -526,8 +528,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
update_prio2buffer = true;
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
- mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n",
- __func__, i, prio2buffer[i]);
+ netdev_dbg(priv->netdev, "%s: requested to map prio[%d] to buffer %d\n",
+ __func__, i, prio2buffer[i]);
err = fill_pfc_en(priv->mdev, &curr_pfc_en);
if (err)
@@ -541,10 +543,10 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
if (change & MLX5E_PORT_BUFFER_SIZE) {
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
- mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
+ netdev_dbg(priv->netdev, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]);
if (!port_buffer.buffer[i].lossy && !buffer_size[i]) {
- mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n",
- __func__, i);
+ netdev_dbg(priv->netdev, "%s: lossless buffer[%d] size cannot be zero\n",
+ __func__, i);
return -EINVAL;
}
@@ -552,7 +554,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
total_used += buffer_size[i];
}
- mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used);
+ netdev_dbg(priv->netdev, "%s: total buffer requested=%d\n", __func__, total_used);
if (total_used > port_buffer.headroom_size &&
(total_used - port_buffer.headroom_size) >
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
index 3cbebfba582b..b0b429a0321e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
@@ -729,8 +729,10 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
c = kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev(mdev)));
cparams = kvzalloc(sizeof(*cparams), GFP_KERNEL);
- if (!c || !cparams)
- return -ENOMEM;
+ if (!c || !cparams) {
+ err = -ENOMEM;
+ goto err_free;
+ }
c->priv = priv;
c->mdev = priv->mdev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
index 2842195ee548..1874c2f0587f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
@@ -379,6 +379,12 @@ int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb_
if (!htb && htb_qopt->command != TC_HTB_CREATE)
return -EINVAL;
+ if (htb_qopt->prio) {
+ NL_SET_ERR_MSG_MOD(htb_qopt->extack,
+ "prio parameter is not supported by device with HTB offload enabled.");
+ return -EOPNOTSUPP;
+ }
+
switch (htb_qopt->command) {
case TC_HTB_CREATE:
if (!mlx5_qos_is_supported(priv->mdev)) {
@@ -515,4 +521,3 @@ int mlx5e_mqprio_rl_get_node_hw_id(struct mlx5e_mqprio_rl *rl, int tc, u32 *hw_i
*hw_id = rl->leaves_id[tc];
return 0;
}
-
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
index fd191925ab4b..560800246573 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
@@ -136,7 +136,6 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
struct mlx5_eswitch *esw = br_offloads->esw;
u16 vport_num, esw_owner_vhca_id;
struct netlink_ext_ack *extack;
- int ifindex = upper->ifindex;
int err = 0;
if (!netif_is_bridge_master(upper))
@@ -150,15 +149,15 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
if (mlx5_esw_bridge_is_local(dev, rep, esw))
err = info->linking ?
- mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_link(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack) :
- mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_unlink(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack);
else if (mlx5_esw_bridge_dev_same_hw(rep, esw))
err = info->linking ?
- mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_peer_link(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack) :
- mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id,
+ mlx5_esw_bridge_vport_peer_unlink(upper, vport_num, esw_owner_vhca_id,
br_offloads, extack);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/ct.c
index 92d3952dfa8b..feeb41693c17 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/ct.c
@@ -17,8 +17,10 @@ tc_act_parse_ct(struct mlx5e_tc_act_parse_state *parse_state,
if (err)
return err;
- if (mlx5e_is_eswitch_flow(parse_state->flow))
+ if (mlx5e_is_eswitch_flow(parse_state->flow)) {
attr->esw_attr->split_count = attr->esw_attr->out_count;
+ parse_state->if_count = 0;
+ }
attr->flags |= MLX5_ATTR_FLAG_CT;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
index 291193f7120d..f63402c48028 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/mirred.c
@@ -294,6 +294,7 @@ parse_mirred_ovs_master(struct mlx5e_tc_act_parse_state *parse_state,
if (err)
return err;
+ parse_state->if_count = 0;
esw_attr->out_count++;
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
index 3b272bbf4c53..368a95fa77d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
@@ -98,8 +98,10 @@ tc_act_parse_pedit(struct mlx5e_tc_act_parse_state *parse_state,
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
- if (ns_type == MLX5_FLOW_NAMESPACE_FDB)
+ if (ns_type == MLX5_FLOW_NAMESPACE_FDB) {
esw_attr->split_count = esw_attr->out_count;
+ parse_state->if_count = 0;
+ }
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/redirect_ingress.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/redirect_ingress.c
index ad09a8a5f36e..2d1d4a04501b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/redirect_ingress.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/redirect_ingress.c
@@ -66,6 +66,7 @@ tc_act_parse_redirect_ingress(struct mlx5e_tc_act_parse_state *parse_state,
if (err)
return err;
+ parse_state->if_count = 0;
esw_attr->out_count++;
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
index c8a3eaf189f6..a13c5e707b83 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan.c
@@ -166,6 +166,7 @@ tc_act_parse_vlan(struct mlx5e_tc_act_parse_state *parse_state,
return err;
esw_attr->split_count = esw_attr->out_count;
+ parse_state->if_count = 0;
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c
index 310b99230760..f17575b09788 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/vlan_mangle.c
@@ -65,8 +65,10 @@ tc_act_parse_vlan_mangle(struct mlx5e_tc_act_parse_state *parse_state,
if (err)
return err;
- if (ns_type == MLX5_FLOW_NAMESPACE_FDB)
+ if (ns_type == MLX5_FLOW_NAMESPACE_FDB) {
attr->esw_attr->split_count = attr->esw_attr->out_count;
+ parse_state->if_count = 0;
+ }
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
index 07c1895a2b23..7aa926e542d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
@@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats {
static const struct rhashtable_params act_counters_ht_params = {
.head_offset = offsetof(struct mlx5e_tc_act_stats, hash),
- .key_offset = 0,
- .key_len = offsetof(struct mlx5e_tc_act_stats, counter),
+ .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie),
+ .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie),
.automatic_shrinking = true,
};
@@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
{
struct rhashtable *ht = &handle->ht;
struct mlx5e_tc_act_stats *item;
- struct mlx5e_tc_act_stats key;
u64 pkts, bytes, lastused;
int err = 0;
- key.tc_act_cookie = fl_act->cookie;
-
rcu_read_lock();
- item = rhashtable_lookup(ht, &key, act_counters_ht_params);
+ item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params);
if (!item) {
rcu_read_unlock();
err = -ENOENT;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
index 0290e0dea539..4e923a2874ae 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
@@ -112,10 +112,8 @@ mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *po
int err;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
- kfree(handle);
+ if (!handle)
return ERR_PTR(-ENOMEM);
- }
post_attr->chain = 0;
post_attr->prio = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
index a254e728ac95..fadfa8b50beb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -1545,7 +1545,8 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
attr->ct_attr.ct_action |= act->ct.action; /* So we can have clear + ct */
attr->ct_attr.zone = act->ct.zone;
- attr->ct_attr.nf_ft = act->ct.flow_table;
+ if (!(act->ct.action & TCA_CT_ACT_CLEAR))
+ attr->ct_attr.nf_ft = act->ct.flow_table;
attr->ct_attr.act_miss_cookie = act->miss_cookie;
return 0;
@@ -1990,6 +1991,9 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
if (!priv)
return -EOPNOTSUPP;
+ if (attr->ct_attr.offloaded)
+ return 0;
+
if (attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR) {
err = mlx5_tc_ct_entry_set_registers(priv, &attr->parse_attr->mod_hdr_acts,
0, 0, 0, 0);
@@ -1999,11 +2003,15 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
}
- if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
+ if (!attr->ct_attr.nf_ft) { /* means only ct clear action, and not ct_clear,ct() */
+ attr->ct_attr.offloaded = true;
return 0;
+ }
mutex_lock(&priv->control_lock);
err = __mlx5_tc_ct_flow_offload(priv, attr);
+ if (!err)
+ attr->ct_attr.offloaded = true;
mutex_unlock(&priv->control_lock);
return err;
@@ -2021,7 +2029,7 @@ void
mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
struct mlx5_flow_attr *attr)
{
- if (!attr->ct_attr.ft) /* no ct action, return */
+ if (!attr->ct_attr.offloaded) /* no ct action, return */
return;
if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
index 8e9316fa46d4..b66c5f98067f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
@@ -29,6 +29,7 @@ struct mlx5_ct_attr {
u32 ct_labels_id;
u32 act_miss_mapping;
u64 act_miss_cookie;
+ bool offloaded;
struct mlx5_ct_ft *ft;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
index ba2b1f24ff14..6cc23af66b5b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
@@ -94,13 +94,13 @@ struct mlx5e_tc_flow {
* destinations.
*/
struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS];
- struct mlx5e_tc_flow *peer_flow;
struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */
struct list_head hairpin; /* flows sharing the same hairpin */
- struct list_head peer; /* flows with peer flow */
+ struct list_head peer[MLX5_MAX_PORTS]; /* flows with peer flow */
struct list_head unready; /* flows not ready to be offloaded (e.g
* due to missing route)
*/
+ struct list_head peer_flows; /* flows on peer */
struct net_device *orig_dev; /* netdev adding flow first */
int tmp_entry_index;
struct list_head tmp_list; /* temporary flow list used by neigh update */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index f0c3464f037f..1730f6a716ee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
int out_index;
int err = 0;
- if (!mlx5e_is_eswitch_flow(flow))
- return 0;
-
parse_attr = attr->parse_attr;
esw_attr = attr->esw_attr;
*vf_tun = false;
@@ -1464,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
attr = mlx5e_tc_get_encap_attr(flow);
esw_attr = attr->esw_attr;
- if (flow_flag_test(flow, SLOW))
+ if (flow_flag_test(flow, SLOW)) {
mlx5e_tc_unoffload_from_slow_path(esw, flow);
- else
+ } else {
mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr);
+ mlx5e_tc_unoffload_flow_post_acts(flow);
+ }
mlx5e_tc_detach_mod_hdr(priv, flow, attr);
attr->modify_hdr = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index f0e6095809fa..40589cebb773 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -662,8 +662,7 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq,
/* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE)
* as we know this is a page_pool page.
*/
- page_pool_put_defragged_page(page->pp,
- page, -1, true);
+ page_pool_recycle_direct(page->pp, page);
} while (++n < num);
break;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
index 9e8e6184f9e4..ecfe93a479da 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
@@ -84,6 +84,8 @@ enum mlx5e_xdp_xmit_mode {
* MLX5E_XDP_XMIT_MODE_XSK:
* none.
*/
+#define MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO 4
+
union mlx5e_xdp_info {
enum mlx5e_xdp_xmit_mode mode;
union {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
index d97e6df66f45..b8dd74453655 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
@@ -323,8 +323,11 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
net_prefetch(mxbuf->xdp.data);
prog = rcu_dereference(rq->xdp_prog);
- if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf)))
+ if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) {
+ if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)))
+ wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
return NULL; /* page/packet was consumed by XDP */
+ }
/* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse
* will be handled by mlx5e_free_rx_wqe.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
index c964644ee866..bac4717548c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
@@ -125,7 +125,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
#ifdef CONFIG_MLX5_EN_TLS
/* May send WQEs. */
- if (mlx5e_ktls_skb_offloaded(skb))
+ if (tls_is_skb_tx_device_offloaded(skb))
if (unlikely(!mlx5e_ktls_handle_tx_skb(dev, sq, skb,
&state->tls)))
return false;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
index 88a5aed9d678..c7d191f66ad1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
@@ -190,6 +190,7 @@ static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft,
in = kvzalloc(inlen, GFP_KERNEL);
if (!in || !ft->g) {
kfree(ft->g);
+ ft->g = NULL;
kvfree(in);
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
index dbe87bf89c0d..832d36be4a17 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
@@ -808,9 +808,9 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp
}
if (upspec->sport) {
- MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport,
+ MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport,
upspec->sport_mask);
- MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->sport);
+ MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport);
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
index eab5bc718771..8d995e304869 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
@@ -58,7 +58,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x)
trailer_len = alen + plen + 2;
- pskb_trim(skb, skb->len - trailer_len);
+ ret = pskb_trim(skb, skb->len - trailer_len);
+ if (unlikely(ret))
+ return ret;
if (skb->protocol == htons(ETH_P_IP)) {
ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
ip_send_check(ipv4hdr);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
index cf704f106b7c..984fa04bd331 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
@@ -188,7 +188,6 @@ static void mlx5e_tls_debugfs_init(struct mlx5e_tls *tls,
int mlx5e_ktls_init(struct mlx5e_priv *priv)
{
- struct mlx5_crypto_dek_pool *dek_pool;
struct mlx5e_tls *tls;
if (!mlx5e_is_ktls_device(priv->mdev))
@@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv)
return -ENOMEM;
tls->mdev = priv->mdev;
- dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
- if (IS_ERR(dek_pool)) {
- kfree(tls);
- return PTR_ERR(dek_pool);
- }
- tls->dek_pool = dek_pool;
priv->tls = tls;
mlx5e_tls_debugfs_init(tls, priv->dfs_root);
@@ -222,7 +215,6 @@ void mlx5e_ktls_cleanup(struct mlx5e_priv *priv)
debugfs_remove_recursive(tls->debugfs.dfs);
tls->debugfs.dfs = NULL;
- mlx5_crypto_dek_pool_destroy(tls->dek_pool);
kfree(priv->tls);
priv->tls = NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
index 0e4c0a093293..d61be26a4df1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -846,7 +846,7 @@ bool mlx5e_ktls_handle_tx_skb(struct net_device *netdev, struct mlx5e_txqsq *sq,
tls_ctx = tls_get_ctx(skb->sk);
tls_netdev = rcu_dereference_bh(tls_ctx->netdev);
/* Don't WARN on NULL: if tls_device_down is running in parallel,
- * netdev might become NULL, even if tls_is_sk_tx_device_offloaded was
+ * netdev might become NULL, even if tls_is_skb_tx_device_offloaded was
* true. Rather continue processing this packet.
*/
if (WARN_ON_ONCE(tls_netdev && tls_netdev != netdev))
@@ -908,28 +908,51 @@ static void mlx5e_tls_tx_debugfs_init(struct mlx5e_tls *tls,
int mlx5e_ktls_init_tx(struct mlx5e_priv *priv)
{
+ struct mlx5_crypto_dek_pool *dek_pool;
struct mlx5e_tls *tls = priv->tls;
+ int err;
+
+ if (!mlx5e_is_ktls_device(priv->mdev))
+ return 0;
+
+ /* DEK pool could be used by either or both of TX and RX. But we have to
+ * put the creation here to avoid syndrome when doing devlink reload.
+ */
+ dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
+ if (IS_ERR(dek_pool))
+ return PTR_ERR(dek_pool);
+ tls->dek_pool = dek_pool;
if (!mlx5e_is_ktls_tx(priv->mdev))
return 0;
priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats);
- if (!priv->tls->tx_pool)
- return -ENOMEM;
+ if (!priv->tls->tx_pool) {
+ err = -ENOMEM;
+ goto err_tx_pool_init;
+ }
mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs);
return 0;
+
+err_tx_pool_init:
+ mlx5_crypto_dek_pool_destroy(dek_pool);
+ return err;
}
void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv)
{
if (!mlx5e_is_ktls_tx(priv->mdev))
- return;
+ goto dek_pool_destroy;
debugfs_remove_recursive(priv->tls->debugfs.dfs_tx);
priv->tls->debugfs.dfs_tx = NULL;
mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool);
priv->tls->tx_pool = NULL;
+
+dek_pool_destroy:
+ if (mlx5e_is_ktls_device(priv->mdev))
+ mlx5_crypto_dek_pool_destroy(priv->tls->dek_pool);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
index 2dd78dd4ad65..f87b65c560ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_txrx.h
@@ -49,11 +49,6 @@ mlx5e_ktls_rx_pending_resync_list(struct mlx5e_channel *c, int budget)
return budget && test_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &c->async_icosq.state);
}
-static inline bool mlx5e_ktls_skb_offloaded(struct sk_buff *skb)
-{
- return skb->sk && tls_is_sk_tx_device_offloaded(skb->sk);
-}
-
static inline void
mlx5e_ktls_handle_tx_wqe(struct mlx5_wqe_ctrl_seg *cseg,
struct mlx5e_accel_tx_tls_state *state)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
index 6b7b563f844a..592b165530ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
@@ -349,15 +349,6 @@ static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec,
sa->macsec_rule = NULL;
}
-static struct mlx5e_priv *macsec_netdev_priv(const struct net_device *dev)
-{
-#if IS_ENABLED(CONFIG_VLAN_8021Q)
- if (is_vlan_dev(dev))
- return netdev_priv(vlan_dev_priv(dev)->real_dev);
-#endif
- return netdev_priv(dev);
-}
-
static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
struct mlx5e_macsec_sa *sa,
bool encrypt,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
index 7fc901a6ec5f..414e28584881 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
@@ -161,6 +161,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
if (!in) {
kfree(ft->g);
+ ft->g = NULL;
return -ENOMEM;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index bed0c2d043e7..5aa51d74f8b4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs);
int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
{
+ /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile
+ * cleanup_rx callback and it is not recreated when
+ * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering()
+ * is not called by the uplink_rep profile init_rx callback. Thus, if
+ * ntuple is set, moving to switchdev flow will enter this function
+ * with fs->arfs nullified.
+ */
+ if (!mlx5e_fs_get_arfs(fs))
+ return 0;
+
arfs_del_rules(fs);
return arfs_disable(fs);
@@ -570,10 +580,10 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++;
- mlx5e_dbg(HW, priv,
- "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n",
- __func__, arfs_rule->filter_id, arfs_rule->rxq,
- tuple->ip_proto, err);
+ netdev_dbg(priv->netdev,
+ "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n",
+ __func__, arfs_rule->filter_id, arfs_rule->rxq,
+ tuple->ip_proto, err);
}
out:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index ebee52a8361a..8705cffc747f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -275,10 +275,10 @@ static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets
memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n",
- __func__, i, ets->prio_tc[i]);
- mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
- __func__, i, tc_tx_bw[i], tc_group[i]);
+ netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n",
+ __func__, i, ets->prio_tc[i]);
+ netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
+ __func__, i, tc_tx_bw[i], tc_group[i]);
}
return err;
@@ -399,9 +399,9 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
}
if (!ret) {
- mlx5e_dbg(HW, priv,
- "%s: PFC per priority bit mask: 0x%x\n",
- __func__, pfc->pfc_en);
+ netdev_dbg(dev,
+ "%s: PFC per priority bit mask: 0x%x\n",
+ __func__, pfc->pfc_en);
}
return ret;
}
@@ -611,8 +611,8 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
}
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n",
- __func__, i, max_bw_value[i]);
+ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n",
+ __func__, i, max_bw_value[i]);
}
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
@@ -640,10 +640,10 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i];
- mlx5e_dbg(HW, priv,
- "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
- __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
- ets.prio_tc[i]);
+ netdev_dbg(netdev,
+ "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
+ __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
+ ets.prio_tc[i]);
}
err = mlx5e_dbcnl_validate_ets(netdev, &ets, true);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 1f5a2110d31f..27861b68ced5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1689,16 +1689,6 @@ static int mlx5e_set_fecparam(struct net_device *netdev,
return 0;
}
-static u32 mlx5e_get_msglevel(struct net_device *dev)
-{
- return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel;
-}
-
-static void mlx5e_set_msglevel(struct net_device *dev, u32 val)
-{
- ((struct mlx5e_priv *)netdev_priv(dev))->msglevel = val;
-}
-
static int mlx5e_set_phys_id(struct net_device *dev,
enum ethtool_phys_id_state state)
{
@@ -1952,9 +1942,9 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val
if (err)
return err;
- mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n",
- MLX5E_GET_PFLAG(&priv->channels.params,
- MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
+ netdev_dbg(priv->netdev, "MLX5E: RxCqeCmprss was turned %s\n",
+ MLX5E_GET_PFLAG(&priv->channels.params,
+ MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF");
return 0;
}
@@ -2444,8 +2434,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.get_priv_flags = mlx5e_get_priv_flags,
.set_priv_flags = mlx5e_set_priv_flags,
.self_test = mlx5e_self_test,
- .get_msglevel = mlx5e_get_msglevel,
- .set_msglevel = mlx5e_set_msglevel,
.get_fec_stats = mlx5e_get_fec_stats,
.get_fecparam = mlx5e_get_fecparam,
.set_fecparam = mlx5e_set_fecparam,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
index 33bfe4d7338b..934b0d5ce1b3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -283,7 +283,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs,
if (IS_ERR(*rule_p)) {
err = PTR_ERR(*rule_p);
*rule_p = NULL;
- fs_err(fs, "%s: add rule failed\n", __func__);
+ fs_err(fs, "add rule failed\n");
}
return err;
@@ -395,8 +395,7 @@ int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
fs->vlan->trap_rule = NULL;
- fs_err(fs, "%s: add VLAN trap rule failed, err %d\n",
- __func__, err);
+ fs_err(fs, "add VLAN trap rule failed, err %d\n", err);
return err;
}
fs->vlan->trap_rule = rule;
@@ -421,8 +420,7 @@ int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num)
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
fs->l2.trap_rule = NULL;
- fs_err(fs, "%s: add MAC trap rule failed, err %d\n",
- __func__, err);
+ fs_err(fs, "add MAC trap rule failed, err %d\n", err);
return err;
}
fs->l2.trap_rule = rule;
@@ -763,7 +761,7 @@ static int mlx5e_add_promisc_rule(struct mlx5e_flow_steering *fs)
if (IS_ERR(*rule_p)) {
err = PTR_ERR(*rule_p);
*rule_p = NULL;
- fs_err(fs, "%s: add promiscuous rule failed\n", __func__);
+ fs_err(fs, "add promiscuous rule failed\n");
}
kvfree(spec);
return err;
@@ -995,7 +993,7 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs,
ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(ai->rule)) {
- fs_err(fs, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac);
+ fs_err(fs, "add l2 rule(mac:%pM) failed\n", mv_dmac);
err = PTR_ERR(ai->rule);
ai->rule = NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index a5bdf78955d7..f7b494125eee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -1036,7 +1036,23 @@ static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_s
return err;
}
-static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
+static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq)
+{
+ struct mlx5_cqwq *cqwq = &rq->cq.wq;
+ struct mlx5_cqe64 *cqe;
+
+ if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) {
+ while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)))
+ mlx5_cqwq_pop(cqwq);
+ } else {
+ while ((cqe = mlx5_cqwq_get_cqe(cqwq)))
+ mlx5_cqwq_pop(cqwq);
+ }
+
+ mlx5_cqwq_update_db_record(cqwq);
+}
+
+int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
{
struct net_device *dev = rq->netdev;
int err;
@@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn);
return err;
}
+
+ mlx5e_free_rx_descs(rq);
+ mlx5e_flush_rq_cq(rq);
+
err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
if (err) {
netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn);
@@ -1055,13 +1075,6 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
return 0;
}
-int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
-{
- mlx5e_free_rx_descs(rq);
-
- return mlx5e_rq_to_ready(rq, curr_state);
-}
-
static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
{
struct mlx5_core_dev *mdev = rq->mdev;
@@ -1285,11 +1298,13 @@ static int mlx5e_alloc_xdpsq_fifo(struct mlx5e_xdpsq *sq, int numa)
{
struct mlx5e_xdp_info_fifo *xdpi_fifo = &sq->db.xdpi_fifo;
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
- int entries = wq_sz * MLX5_SEND_WQEBB_NUM_DS * 2; /* upper bound for maximum num of
- * entries of all xmit_modes.
- */
+ int entries;
size_t size;
+ /* upper bound for maximum num of entries of all xmit_modes. */
+ entries = roundup_pow_of_two(wq_sz * MLX5_SEND_WQEBB_NUM_DS *
+ MLX5E_XDP_FIFO_ENTRIES2DS_MAX_RATIO);
+
size = array_size(sizeof(*xdpi_fifo->xi), entries);
xdpi_fifo->xi = kvzalloc_node(size, GFP_KERNEL, numa);
if (!xdpi_fifo->xi)
@@ -2402,7 +2417,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu)
/* Asymmetric dynamic memory allocation.
* Freed in mlx5e_priv_arrays_free, not on channel closure.
*/
- mlx5e_dbg(DRV, priv, "Creating channel stats %d\n", ix);
+ netdev_dbg(priv->netdev, "Creating channel stats %d\n", ix);
priv->channel_stats[ix] = kvzalloc_node(sizeof(**priv->channel_stats),
GFP_KERNEL, cpu_to_node(cpu));
if (!priv->channel_stats[ix])
@@ -2780,7 +2795,7 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv)
if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS))
num_txqs += ntc;
- mlx5e_dbg(DRV, priv, "Setting num_txqs %d\n", num_txqs);
+ netdev_dbg(priv->netdev, "Setting num_txqs %d\n", num_txqs);
err = netif_set_real_num_tx_queues(priv->netdev, num_txqs);
if (err)
netdev_warn(priv->netdev, "netif_set_real_num_tx_queues failed, %d\n", err);
@@ -5253,6 +5268,7 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
struct net_device *netdev)
{
+ const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED;
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_flow_steering *fs;
int err;
@@ -5281,9 +5297,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
mlx5e_health_create_reporters(priv);
+
+ /* If netdev is already registered (e.g. move from uplink to nic profile),
+ * RTNL lock must be held before triggering netdev notifiers.
+ */
+ if (take_rtnl)
+ rtnl_lock();
+
/* update XDP supported features */
mlx5e_set_xdp_feature(netdev);
+ if (take_rtnl)
+ rtnl_unlock();
+
return 0;
}
@@ -5586,7 +5612,6 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
/* priv init */
priv->mdev = mdev;
priv->netdev = netdev;
- priv->msglevel = MLX5E_MSG_LEVEL;
priv->max_nch = nch;
priv->max_opened_tc = 1;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 3e7041bd5705..99b3843396f3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -374,7 +374,9 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_sq *rep_sq, *tmp;
+ struct mlx5e_rep_sq_peer *sq_peer;
struct mlx5e_rep_priv *rpriv;
+ unsigned long i;
if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return;
@@ -382,31 +384,78 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
- if (rep_sq->send_to_vport_rule_peer)
- mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
+ xa_for_each(&rep_sq->sq_peer, i, sq_peer) {
+ if (sq_peer->rule)
+ mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
+
+ xa_erase(&rep_sq->sq_peer, i);
+ kfree(sq_peer);
+ }
+
+ xa_destroy(&rep_sq->sq_peer);
list_del(&rep_sq->list);
kfree(rep_sq);
}
}
+static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep,
+ struct mlx5_devcom *devcom,
+ struct mlx5e_rep_sq *rep_sq, int i)
+{
+ struct mlx5_eswitch *peer_esw = NULL;
+ struct mlx5_flow_handle *flow_rule;
+ int tmp;
+
+ mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ peer_esw, tmp) {
+ u16 peer_rule_idx = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ struct mlx5e_rep_sq_peer *sq_peer;
+ int err;
+
+ sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
+ if (!sq_peer)
+ return -ENOMEM;
+
+ flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
+ rep, rep_sq->sqn);
+ if (IS_ERR(flow_rule)) {
+ kfree(sq_peer);
+ return PTR_ERR(flow_rule);
+ }
+
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
+ err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL);
+ if (err) {
+ kfree(sq_peer);
+ mlx5_eswitch_del_send_to_vport_rule(flow_rule);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
u32 *sqns_array, int sqns_num)
{
- struct mlx5_eswitch *peer_esw = NULL;
struct mlx5_flow_handle *flow_rule;
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ struct mlx5_devcom *devcom;
+ bool devcom_locked = false;
int err;
int i;
if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return 0;
+ devcom = esw->dev->priv.devcom;
rpriv = mlx5e_rep_to_rep_priv(rep);
- if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS))
- peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS);
+ if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) &&
+ mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
+ devcom_locked = true;
for (i = 0; i < sqns_num; i++) {
rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
@@ -426,31 +475,30 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
rep_sq->send_to_vport_rule = flow_rule;
rep_sq->sqn = sqns_array[i];
- if (peer_esw) {
- flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
- rep, sqns_array[i]);
- if (IS_ERR(flow_rule)) {
- err = PTR_ERR(flow_rule);
+ xa_init(&rep_sq->sq_peer);
+ if (devcom_locked) {
+ err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i);
+ if (err) {
mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
+ xa_destroy(&rep_sq->sq_peer);
kfree(rep_sq);
goto out_err;
}
- rep_sq->send_to_vport_rule_peer = flow_rule;
}
list_add(&rep_sq->list, &rpriv->vport_sqs_list);
}
- if (peer_esw)
- mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ if (devcom_locked)
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return 0;
out_err:
mlx5e_sqs2vport_stop(esw, rep);
- if (peer_esw)
- mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ if (devcom_locked)
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return err;
}
@@ -964,7 +1012,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
if (err) {
mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
- return err;
+ goto err_rx_res_free;
}
err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
@@ -998,6 +1046,7 @@ err_destroy_rx_res:
mlx5e_rx_res_destroy(priv->rx_res);
err_close_drop_rq:
mlx5e_close_drop_rq(&priv->drop_rq);
+err_rx_res_free:
mlx5e_rx_res_free(priv->rx_res);
priv->rx_res = NULL;
err_free_fs:
@@ -1111,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
return err;
}
+ err = mlx5e_rep_neigh_init(rpriv);
+ if (err)
+ goto err_neigh_init;
+
if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
err = mlx5e_init_uplink_rep_tx(rpriv);
if (err)
@@ -1127,6 +1180,8 @@ err_ht_init:
if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
mlx5e_cleanup_uplink_rep_tx(rpriv);
err_init_tx:
+ mlx5e_rep_neigh_cleanup(rpriv);
+err_neigh_init:
mlx5e_destroy_tises(priv);
return err;
}
@@ -1140,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
mlx5e_cleanup_uplink_rep_tx(rpriv);
+ mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_destroy_tises(priv);
}
static void mlx5e_rep_enable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
mlx5e_set_netdev_mtu_boundaries(priv);
- mlx5e_rep_neigh_init(rpriv);
}
static void mlx5e_rep_disable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
- mlx5e_rep_neigh_cleanup(rpriv);
}
static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
@@ -1205,7 +1255,6 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event
static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct net_device *netdev = priv->netdev;
struct mlx5_core_dev *mdev = priv->mdev;
u16 max_mtu;
@@ -1227,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
mlx5_notifier_register(mdev, &priv->events_nb);
mlx5e_dcbnl_initialize(priv);
mlx5e_dcbnl_init_app(priv);
- mlx5e_rep_neigh_init(rpriv);
mlx5e_rep_bridge_init(priv);
netdev->wanted_features |= NETIF_F_HW_TC;
@@ -1242,7 +1290,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
{
- struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_core_dev *mdev = priv->mdev;
rtnl_lock();
@@ -1252,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
rtnl_unlock();
mlx5e_rep_bridge_cleanup(priv);
- mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_dcbnl_delete_app(priv);
mlx5_notifier_unregister(mdev, &priv->events_nb);
mlx5e_rep_tc_disable(priv);
@@ -1530,17 +1576,24 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
return rpriv->netdev;
}
-static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep)
+static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep,
+ struct mlx5_eswitch *peer_esw)
{
+ u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ WARN_ON_ONCE(!peer_esw);
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
- if (!rep_sq->send_to_vport_rule_peer)
+ struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i);
+
+ if (!sq_peer || sq_peer->peer != peer_esw)
continue;
- mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
- rep_sq->send_to_vport_rule_peer = NULL;
+
+ mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule);
+ xa_erase(&rep_sq->sq_peer, i);
+ kfree(sq_peer);
}
}
@@ -1548,24 +1601,52 @@ static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw,
struct mlx5_eswitch_rep *rep,
struct mlx5_eswitch *peer_esw)
{
+ u16 i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
struct mlx5_flow_handle *flow_rule;
+ struct mlx5e_rep_sq_peer *sq_peer;
struct mlx5e_rep_priv *rpriv;
struct mlx5e_rep_sq *rep_sq;
+ int err;
rpriv = mlx5e_rep_to_rep_priv(rep);
list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
- if (rep_sq->send_to_vport_rule_peer)
+ sq_peer = xa_load(&rep_sq->sq_peer, i);
+
+ if (sq_peer && sq_peer->peer)
continue;
- flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn);
- if (IS_ERR(flow_rule))
+
+ flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep,
+ rep_sq->sqn);
+ if (IS_ERR(flow_rule)) {
+ err = PTR_ERR(flow_rule);
goto err_out;
- rep_sq->send_to_vport_rule_peer = flow_rule;
+ }
+
+ if (sq_peer) {
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
+ continue;
+ }
+ sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL);
+ if (!sq_peer) {
+ err = -ENOMEM;
+ goto err_sq_alloc;
+ }
+ err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL);
+ if (err)
+ goto err_xa;
+ sq_peer->rule = flow_rule;
+ sq_peer->peer = peer_esw;
}
return 0;
+err_xa:
+ kfree(sq_peer);
+err_sq_alloc:
+ mlx5_eswitch_del_send_to_vport_rule(flow_rule);
err_out:
- mlx5e_vport_rep_event_unpair(rep);
- return PTR_ERR(flow_rule);
+ mlx5e_vport_rep_event_unpair(rep, peer_esw);
+ return err;
}
static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
@@ -1578,7 +1659,7 @@ static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
if (event == MLX5_SWITCHDEV_EVENT_PAIR)
err = mlx5e_vport_rep_event_pair(esw, rep, data);
else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR)
- mlx5e_vport_rep_event_unpair(rep);
+ mlx5e_vport_rep_event_unpair(rep, data);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
index 80b7f5079a5a..70640fa1ad7b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
@@ -225,9 +225,14 @@ struct mlx5e_encap_entry {
struct rcu_head rcu;
};
+struct mlx5e_rep_sq_peer {
+ struct mlx5_flow_handle *rule;
+ void *peer;
+};
+
struct mlx5e_rep_sq {
struct mlx5_flow_handle *send_to_vport_rule;
- struct mlx5_flow_handle *send_to_vport_rule_peer;
+ struct xarray sq_peer;
u32 sqn;
struct list_head list;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 69634829558e..41d37159e027 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -390,10 +390,18 @@ static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
{
struct mlx5e_wqe_frag_info *wi = get_frag(rq, ix);
- if (rq->xsk_pool)
+ if (rq->xsk_pool) {
mlx5e_xsk_free_rx_wqe(wi);
- else
+ } else {
mlx5e_free_rx_wqe(rq, wi);
+
+ /* Avoid a second release of the wqe pages: dealloc is called
+ * for the same missing wqes on regular RQ flush and on regular
+ * RQ close. This happens when XSK RQs come into play.
+ */
+ for (int i = 0; i < rq->wqe.info.num_frags; i++, wi++)
+ wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+ }
}
static void mlx5e_xsk_free_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
@@ -491,9 +499,7 @@ mlx5e_add_skb_shared_info_frag(struct mlx5e_rq *rq, struct skb_shared_info *sinf
}
frag = &sinfo->frags[sinfo->nr_frags++];
- __skb_frag_set_page(frag, frag_page->page);
- skb_frag_off_set(frag, frag_offset);
- skb_frag_size_set(frag, len);
+ skb_frag_fill_page_desc(frag, frag_page->page, frag_offset, len);
if (page_is_pfmemalloc(frag_page->page))
xdp_buff_set_frag_pfmemalloc(xdp);
@@ -1745,11 +1751,11 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
prog = rcu_dereference(rq->xdp_prog);
if (prog && mlx5e_xdp_handle(rq, prog, &mxbuf)) {
- if (test_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
struct mlx5e_wqe_frag_info *pwi;
for (pwi = head_wi; pwi < wi; pwi++)
- pwi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+ pwi->frag_page->frags++;
}
return NULL; /* page/packet was consumed by XDP */
}
@@ -1819,12 +1825,8 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
rq, wi, cqe, cqe_bcnt);
if (!skb) {
/* probably for XDP */
- if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- /* do not return page to cache,
- * it will be returned on XDP_TX completion.
- */
- wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
- }
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+ wi->frag_page->frags++;
goto wq_cyc_pop;
}
@@ -1870,12 +1872,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
rq, wi, cqe, cqe_bcnt);
if (!skb) {
/* probably for XDP */
- if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- /* do not return page to cache,
- * it will be returned on XDP_TX completion.
- */
- wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
- }
+ if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+ wi->frag_page->frags++;
goto wq_cyc_pop;
}
@@ -2054,12 +2052,12 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
if (prog) {
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
- int i;
+ struct mlx5e_frag_page *pfp;
+
+ for (pfp = head_page; pfp < frag_page; pfp++)
+ pfp->frags++;
- for (i = 0; i < sinfo->nr_frags; i++)
- /* non-atomic */
- __set_bit(page_idx + i, wi->skip_release_bitmap);
- return NULL;
+ wi->linear_page.frags++;
}
mlx5e_page_release_fragmented(rq, &wi->linear_page);
return NULL; /* page/packet was consumed by XDP */
@@ -2157,7 +2155,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
cqe_bcnt, &mxbuf);
if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
- __set_bit(page_idx, wi->skip_release_bitmap); /* non-atomic */
+ frag_page->frags++;
return NULL; /* page/packet was consumed by XDP */
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
index f1d9596905c6..4d77055abd4b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -30,7 +30,7 @@
* SOFTWARE.
*/
-#include "lib/mlx5.h"
+#include "lib/events.h"
#include "en.h"
#include "en_accel/ktls.h"
#include "en_accel/en_accel.h"
@@ -748,11 +748,22 @@ static const struct counter_desc vport_stats_desc[] = {
VPORT_COUNTER_OFF(transmitted_ib_multicast.octets) },
};
+static const struct counter_desc vport_loopback_stats_desc[] = {
+ { "vport_loopback_packets",
+ VPORT_COUNTER_OFF(local_loopback.packets) },
+ { "vport_loopback_bytes",
+ VPORT_COUNTER_OFF(local_loopback.octets) },
+};
+
#define NUM_VPORT_COUNTERS ARRAY_SIZE(vport_stats_desc)
+#define NUM_VPORT_LOOPBACK_COUNTERS(dev) \
+ (MLX5_CAP_GEN(dev, vport_counter_local_loopback) ? \
+ ARRAY_SIZE(vport_loopback_stats_desc) : 0)
static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport)
{
- return NUM_VPORT_COUNTERS;
+ return NUM_VPORT_COUNTERS +
+ NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev);
}
static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport)
@@ -761,6 +772,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport)
for (i = 0; i < NUM_VPORT_COUNTERS; i++)
strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_stats_desc[i].format);
+
+ for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++)
+ strcpy(data + (idx++) * ETH_GSTRING_LEN,
+ vport_loopback_stats_desc[i].format);
+
return idx;
}
@@ -771,6 +787,11 @@ static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport)
for (i = 0; i < NUM_VPORT_COUNTERS; i++)
data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out,
vport_stats_desc, i);
+
+ for (i = 0; i < NUM_VPORT_LOOPBACK_COUNTERS(priv->mdev); i++)
+ data[idx++] = MLX5E_READ_CTR64_BE(priv->stats.vport.query_vport_out,
+ vport_loopback_stats_desc, i);
+
return idx;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index b9b1da751a3b..4b22a91482ce 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1639,7 +1639,8 @@ static void remove_unready_flow(struct mlx5e_tc_flow *flow)
uplink_priv = &rpriv->uplink_priv;
mutex_lock(&uplink_priv->unready_flows_lock);
- unready_flow_del(flow);
+ if (flow_flag_test(flow, NOT_READY))
+ unready_flow_del(flow);
mutex_unlock(&uplink_priv->unready_flows_lock);
}
@@ -1667,8 +1668,11 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
{
struct mlx5e_priv *out_priv, *route_priv;
struct mlx5_core_dev *route_mdev;
+ struct mlx5_devcom *devcom;
struct mlx5_eswitch *esw;
u16 vhca_id;
+ int err;
+ int i;
out_priv = netdev_priv(out_dev);
esw = out_priv->mdev->priv.eswitch;
@@ -1676,28 +1680,25 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
route_mdev = route_priv->mdev;
vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
- if (mlx5_lag_is_active(out_priv->mdev)) {
- struct mlx5_devcom *devcom;
- int err;
-
- /* In lag case we may get devices from different eswitch instances.
- * If we failed to get vport num, it means, mostly, that we on the wrong
- * eswitch.
- */
- err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
- if (err != -ENOENT)
- return err;
-
- rcu_read_lock();
- devcom = out_priv->mdev->priv.devcom;
- esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV;
- rcu_read_unlock();
+ err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ if (!err)
+ return err;
+ if (!mlx5_lag_is_active(out_priv->mdev))
return err;
+
+ rcu_read_lock();
+ devcom = out_priv->mdev->priv.devcom;
+ err = -ENODEV;
+ mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ esw, i) {
+ err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ if (!err)
+ break;
}
+ rcu_read_unlock();
- return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ return err;
}
static int
@@ -1724,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack)
return 0;
}
+static bool
+has_encap_dests(struct mlx5_flow_attr *attr)
+{
+ struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
+ int out_index;
+
+ for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
+ if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+ return true;
+
+ return false;
+}
+
static int
post_process_attr(struct mlx5e_tc_flow *flow,
struct mlx5_flow_attr *attr,
@@ -1736,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow,
if (err)
goto err_out;
- err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
- if (err)
- goto err_out;
+ if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) {
+ err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
+ if (err)
+ goto err_out;
+ }
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr);
@@ -1927,13 +1943,10 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_flow_attr *attr = flow->attr;
- struct mlx5_esw_flow_attr *esw_attr;
- esw_attr = attr->esw_attr;
mlx5e_put_flow_tunnel_id(flow);
- if (flow_flag_test(flow, NOT_READY))
- remove_unready_flow(flow);
+ remove_unready_flow(flow);
if (mlx5e_is_offloaded_flow(flow)) {
if (flow_flag_test(flow, SLOW))
@@ -1951,12 +1964,6 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr);
- if (esw_attr->int_port)
- mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->int_port);
-
- if (esw_attr->dest_int_port)
- mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port);
-
if (flow_flag_test(flow, L3_TO_L2_DECAP))
mlx5e_detach_decap(priv, flow);
@@ -1987,47 +1994,59 @@ void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list)
mlx5e_flow_put(priv, flow);
}
-static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
+static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow,
+ int peer_index)
{
struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch;
+ struct mlx5e_tc_flow *peer_flow;
+ struct mlx5e_tc_flow *tmp;
if (!flow_flag_test(flow, ESWITCH) ||
!flow_flag_test(flow, DUP))
return;
mutex_lock(&esw->offloads.peer_mutex);
- list_del(&flow->peer);
+ list_del(&flow->peer[peer_index]);
mutex_unlock(&esw->offloads.peer_mutex);
- flow_flag_clear(flow, DUP);
-
- if (refcount_dec_and_test(&flow->peer_flow->refcnt)) {
- mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
- kfree(flow->peer_flow);
+ list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) {
+ if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev))
+ continue;
+ if (refcount_dec_and_test(&peer_flow->refcnt)) {
+ mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow);
+ list_del(&peer_flow->peer_flows);
+ kfree(peer_flow);
+ }
}
- flow->peer_flow = NULL;
+ if (list_empty(&flow->peer_flows))
+ flow_flag_clear(flow, DUP);
}
-static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow)
+static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow)
{
- struct mlx5_core_dev *dev = flow->priv->mdev;
- struct mlx5_devcom *devcom = dev->priv.devcom;
- struct mlx5_eswitch *peer_esw;
-
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
- return;
+ int i;
- __mlx5e_tc_del_fdb_peer_flow(flow);
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ for (i = 0; i < MLX5_MAX_PORTS; i++) {
+ if (i == mlx5_get_dev_index(flow->priv->mdev))
+ continue;
+ mlx5e_tc_del_fdb_peer_flow(flow, i);
+ }
}
static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
struct mlx5e_tc_flow *flow)
{
if (mlx5e_is_eswitch_flow(flow)) {
- mlx5e_tc_del_fdb_peer_flow(flow);
+ struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom;
+
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) {
+ mlx5e_tc_del_fdb_flow(priv, flow);
+ return;
+ }
+
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
mlx5e_tc_del_fdb_flow(priv, flow);
} else {
mlx5e_tc_del_nic_flow(priv, flow);
@@ -2503,6 +2522,12 @@ static int mlx5e_flower_parse_meta(struct net_device *filter_dev,
return 0;
flow_rule_match_meta(rule, &match);
+
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+
if (!match.mask->ingress_ifindex)
return 0;
@@ -3914,6 +3939,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state,
}
i_split = i + 1;
+ parse_state->if_count = 0;
list_add(&attr->list, &flow->attrs);
}
@@ -4198,8 +4224,8 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
flow_flag_test(flow, INGRESS);
bool act_is_encap = !!(attr->action &
MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT);
- bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS);
+ bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS);
if (!esw_paired)
return false;
@@ -4235,6 +4261,7 @@ static void
mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
{
struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
+ struct mlx5_esw_flow_attr *esw_attr;
if (!attr)
return;
@@ -4252,6 +4279,18 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr);
}
+ if (mlx5e_is_eswitch_flow(flow)) {
+ esw_attr = attr->esw_attr;
+
+ if (esw_attr->int_port)
+ mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+ esw_attr->int_port);
+
+ if (esw_attr->dest_int_port)
+ mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
+ esw_attr->dest_int_port);
+ }
+
mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
free_branch_attr(flow, attr->branch_true);
@@ -4290,6 +4329,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
INIT_LIST_HEAD(&flow->hairpin);
INIT_LIST_HEAD(&flow->l3_to_l2_reformat);
INIT_LIST_HEAD(&flow->attrs);
+ INIT_LIST_HEAD(&flow->peer_flows);
refcount_set(&flow->refcnt, 1);
init_completion(&flow->init_done);
init_completion(&flow->del_hw_done);
@@ -4398,22 +4438,19 @@ out:
static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
struct mlx5e_tc_flow *flow,
- unsigned long flow_flags)
+ unsigned long flow_flags,
+ struct mlx5_eswitch *peer_esw)
{
struct mlx5e_priv *priv = flow->priv, *peer_priv;
- struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw;
+ struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr;
- struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct mlx5e_tc_flow_parse_attr *parse_attr;
+ int i = mlx5_get_dev_index(peer_esw->dev);
struct mlx5e_rep_priv *peer_urpriv;
struct mlx5e_tc_flow *peer_flow;
struct mlx5_core_dev *in_mdev;
int err = 0;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
- return -ENODEV;
-
peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH);
peer_priv = netdev_priv(peer_urpriv->netdev);
@@ -4438,14 +4475,13 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f,
goto out;
}
- flow->peer_flow = peer_flow;
+ list_add_tail(&peer_flow->peer_flows, &flow->peer_flows);
flow_flag_set(flow, DUP);
mutex_lock(&esw->offloads.peer_mutex);
- list_add_tail(&flow->peer, &esw->offloads.peer_flows);
+ list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]);
mutex_unlock(&esw->offloads.peer_mutex);
out:
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return err;
}
@@ -4456,30 +4492,48 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
struct net_device *filter_dev,
struct mlx5e_tc_flow **__flow)
{
+ struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_eswitch_rep *in_rep = rpriv->rep;
struct mlx5_core_dev *in_mdev = priv->mdev;
+ struct mlx5_eswitch *peer_esw;
struct mlx5e_tc_flow *flow;
int err;
+ int i;
flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep,
in_mdev);
if (IS_ERR(flow))
return PTR_ERR(flow);
- if (is_peer_flow_needed(flow)) {
- err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags);
- if (err) {
- mlx5e_tc_del_fdb_flow(priv, flow);
- goto out;
- }
+ if (!is_peer_flow_needed(flow)) {
+ *__flow = flow;
+ return 0;
}
- *__flow = flow;
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) {
+ err = -ENODEV;
+ goto clean_flow;
+ }
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ peer_esw, i) {
+ err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw);
+ if (err)
+ goto peer_clean;
+ }
+
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+
+ *__flow = flow;
return 0;
-out:
+peer_clean:
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+clean_flow:
+ mlx5e_tc_del_fdb_flow(priv, flow);
return err;
}
@@ -4697,7 +4751,6 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
{
struct mlx5_devcom *devcom = priv->mdev->priv.devcom;
struct rhashtable *tc_ht = get_tc_ht(priv, flags);
- struct mlx5_eswitch *peer_esw;
struct mlx5e_tc_flow *flow;
struct mlx5_fc *counter;
u64 lastuse = 0;
@@ -4732,23 +4785,29 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
/* Under multipath it's possible for one rule to be currently
* un-offloaded while the other rule is offloaded.
*/
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
goto out;
- if (flow_flag_test(flow, DUP) &&
- flow_flag_test(flow->peer_flow, OFFLOADED)) {
- u64 bytes2;
- u64 packets2;
- u64 lastuse2;
+ if (flow_flag_test(flow, DUP)) {
+ struct mlx5e_tc_flow *peer_flow;
- if (flow_flag_test(flow, USE_ACT_STATS)) {
- f->use_act_stats = true;
- } else {
- counter = mlx5e_tc_get_counter(flow->peer_flow);
+ list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) {
+ u64 packets2;
+ u64 lastuse2;
+ u64 bytes2;
+
+ if (!flow_flag_test(peer_flow, OFFLOADED))
+ continue;
+ if (flow_flag_test(flow, USE_ACT_STATS)) {
+ f->use_act_stats = true;
+ break;
+ }
+
+ counter = mlx5e_tc_get_counter(peer_flow);
if (!counter)
goto no_peer_counter;
- mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
+ mlx5_fc_query_cached(counter, &bytes2, &packets2,
+ &lastuse2);
bytes += bytes2;
packets += packets2;
@@ -4757,7 +4816,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
}
no_peer_counter:
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
out:
flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
FLOW_ACTION_HW_STATS_DELAYED);
@@ -5275,9 +5334,14 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags)
void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
{
struct mlx5e_tc_flow *flow, *tmp;
+ int i;
- list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
- __mlx5e_tc_del_fdb_peer_flow(flow);
+ for (i = 0; i < MLX5_MAX_PORTS; i++) {
+ if (i == mlx5_get_dev_index(esw->dev))
+ continue;
+ list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i])
+ mlx5e_tc_del_fdb_peers_flow(flow);
+ }
}
void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
index fbb2d963fb7e..a7d9b7cb4297 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -207,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
}
ch_stats->aff_change++;
aff_change = true;
- if (budget && work_done == budget)
+ if (work_done == budget)
work_done--;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
index 2e504c7461c6..24b1ca4e4ff8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c
@@ -15,13 +15,27 @@ static void esw_acl_egress_ofld_fwd2vport_destroy(struct mlx5_vport *vport)
vport->egress.offloads.fwd_rule = NULL;
}
-static void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport)
+void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index)
{
- if (!vport->egress.offloads.bounce_rule)
+ struct mlx5_flow_handle *bounce_rule =
+ xa_load(&vport->egress.offloads.bounce_rules, rule_index);
+
+ if (!bounce_rule)
return;
- mlx5_del_flow_rules(vport->egress.offloads.bounce_rule);
- vport->egress.offloads.bounce_rule = NULL;
+ mlx5_del_flow_rules(bounce_rule);
+ xa_erase(&vport->egress.offloads.bounce_rules, rule_index);
+}
+
+static void esw_acl_egress_ofld_bounce_rules_destroy(struct mlx5_vport *vport)
+{
+ struct mlx5_flow_handle *bounce_rule;
+ unsigned long i;
+
+ xa_for_each(&vport->egress.offloads.bounce_rules, i, bounce_rule) {
+ mlx5_del_flow_rules(bounce_rule);
+ xa_erase(&vport->egress.offloads.bounce_rules, i);
+ }
}
static int esw_acl_egress_ofld_fwd2vport_create(struct mlx5_eswitch *esw,
@@ -96,7 +110,7 @@ static void esw_acl_egress_ofld_rules_destroy(struct mlx5_vport *vport)
{
esw_acl_egress_vlan_destroy(vport);
esw_acl_egress_ofld_fwd2vport_destroy(vport);
- esw_acl_egress_ofld_bounce_rule_destroy(vport);
+ esw_acl_egress_ofld_bounce_rules_destroy(vport);
}
static int esw_acl_egress_ofld_groups_create(struct mlx5_eswitch *esw,
@@ -194,6 +208,7 @@ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport
vport->egress.acl = NULL;
return err;
}
+ vport->egress.type = VPORT_EGRESS_ACL_TYPE_DEFAULT;
err = esw_acl_egress_ofld_groups_create(esw, vport);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
index 45b839116212..d599e50af346 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
@@ -35,7 +35,8 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns,
}
ft_attr.max_fte = size;
- ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
+ if (vport_num || mlx5_core_is_ecpf(esw->dev))
+ ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
acl = mlx5_create_vport_flow_table(root_ns, &ft_attr, vport_num);
if (IS_ERR(acl)) {
err = PTR_ERR(acl);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
index c9f8469e9a47..536b04e83618 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h
@@ -10,6 +10,7 @@
/* Eswitch acl egress external APIs */
int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
void esw_acl_egress_ofld_cleanup(struct mlx5_vport *vport);
+void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index);
int mlx5_esw_acl_egress_vport_bond(struct mlx5_eswitch *esw, u16 active_vport_num,
u16 passive_vport_num);
int mlx5_esw_acl_egress_vport_unbond(struct mlx5_eswitch *esw, u16 vport_num);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
index 1ba03e219111..f4fe1daa4afd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
@@ -647,22 +647,35 @@ mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr,
}
static struct mlx5_flow_handle *
-mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr,
+mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id,
+ const unsigned char *addr,
struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
struct mlx5_esw_bridge *bridge)
{
struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom;
+ struct mlx5_eswitch *tmp, *peer_esw = NULL;
static struct mlx5_flow_handle *handle;
- struct mlx5_eswitch *peer_esw;
+ int i;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
return ERR_PTR(-ENODEV);
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ tmp, i) {
+ if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) {
+ peer_esw = tmp;
+ break;
+ }
+ }
+ if (!peer_esw) {
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ return ERR_PTR(-ENODEV);
+ }
+
handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
bridge, peer_esw);
-
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return handle;
}
@@ -821,7 +834,7 @@ mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
return handle;
}
-static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
+static struct mlx5_esw_bridge *mlx5_esw_bridge_create(struct net_device *br_netdev,
struct mlx5_esw_bridge_offloads *br_offloads)
{
struct mlx5_esw_bridge *bridge;
@@ -845,11 +858,12 @@ static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
goto err_mdb_ht;
INIT_LIST_HEAD(&bridge->fdb_list);
- bridge->ifindex = ifindex;
+ bridge->ifindex = br_netdev->ifindex;
bridge->refcnt = 1;
bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
bridge->vlan_proto = ETH_P_8021Q;
list_add(&bridge->list, &br_offloads->bridges);
+ mlx5_esw_bridge_debugfs_init(br_netdev, bridge);
return bridge;
@@ -873,6 +887,7 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
if (--bridge->refcnt)
return;
+ mlx5_esw_bridge_debugfs_cleanup(bridge);
mlx5_esw_bridge_egress_table_cleanup(bridge);
mlx5_esw_bridge_mcast_disable(bridge);
list_del(&bridge->list);
@@ -885,14 +900,14 @@ static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
}
static struct mlx5_esw_bridge *
-mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads)
+mlx5_esw_bridge_lookup(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads)
{
struct mlx5_esw_bridge *bridge;
ASSERT_RTNL();
list_for_each_entry(bridge, &br_offloads->bridges, list) {
- if (bridge->ifindex == ifindex) {
+ if (bridge->ifindex == br_netdev->ifindex) {
mlx5_esw_bridge_get(bridge);
return bridge;
}
@@ -905,7 +920,7 @@ mlx5_esw_bridge_lookup(int ifindex, struct mlx5_esw_bridge_offloads *br_offloads
return ERR_PTR(err);
}
- bridge = mlx5_esw_bridge_create(ifindex, br_offloads);
+ bridge = mlx5_esw_bridge_create(br_netdev, br_offloads);
if (IS_ERR(bridge) && list_empty(&br_offloads->bridges))
mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
return bridge;
@@ -1369,8 +1384,9 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
entry->ingress_counter = counter;
handle = peer ?
- mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan,
- mlx5_fc_id(counter), bridge) :
+ mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id,
+ addr, vlan, mlx5_fc_id(counter),
+ bridge) :
mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan,
mlx5_fc_id(counter), bridge);
if (IS_ERR(handle)) {
@@ -1587,15 +1603,15 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off
return 0;
}
-static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
- u16 flags,
+static int mlx5_esw_bridge_vport_link_with_flags(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id, u16 flags,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
struct mlx5_esw_bridge *bridge;
int err;
- bridge = mlx5_esw_bridge_lookup(ifindex, br_offloads);
+ bridge = mlx5_esw_bridge_lookup(br_netdev, br_offloads);
if (IS_ERR(bridge)) {
NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex");
return PTR_ERR(bridge);
@@ -1613,15 +1629,16 @@ err_vport:
return err;
}
-int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
- return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0,
+ return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 0,
br_offloads, extack);
}
-int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
@@ -1633,7 +1650,7 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge");
return -EINVAL;
}
- if (port->bridge->ifindex != ifindex) {
+ if (port->bridge->ifindex != br_netdev->ifindex) {
NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge");
return -EINVAL;
}
@@ -1644,23 +1661,25 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
return err;
}
-int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
return 0;
- return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id,
+ return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id,
MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
br_offloads, extack);
}
-int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
- return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
+ return mlx5_esw_bridge_vport_unlink(br_netdev, vport_num, esw_owner_vhca_id, br_offloads,
extack);
}
@@ -1887,6 +1906,7 @@ struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw)
xa_init(&br_offloads->ports);
br_offloads->esw = esw;
esw->br_offloads = br_offloads;
+ mlx5_esw_bridge_debugfs_offloads_init(br_offloads);
return br_offloads;
}
@@ -1902,6 +1922,7 @@ void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw)
mlx5_esw_bridge_flush(br_offloads);
WARN_ON(!xa_empty(&br_offloads->ports));
+ mlx5_esw_bridge_debugfs_offloads_cleanup(br_offloads);
esw->br_offloads = NULL;
kvfree(br_offloads);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
index a9dd18c73d6a..c2c7c70d99eb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.h
@@ -10,6 +10,7 @@
#include <linux/xarray.h>
#include "eswitch.h"
+struct dentry;
struct mlx5_flow_table;
struct mlx5_flow_group;
@@ -17,6 +18,7 @@ struct mlx5_esw_bridge_offloads {
struct mlx5_eswitch *esw;
struct list_head bridges;
struct xarray ports;
+ struct dentry *debugfs_root;
struct notifier_block netdev_nb;
struct notifier_block nb_blk;
@@ -43,16 +45,18 @@ struct mlx5_esw_bridge_offloads {
struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw);
void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw);
-int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
-int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
+int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num,
+ u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
new file mode 100644
index 000000000000..dbd7cbe6cbf3
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <linux/debugfs.h>
+#include "bridge.h"
+#include "bridge_priv.h"
+
+static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos);
+static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos);
+static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v);
+static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v);
+
+static const struct seq_operations mlx5_esw_bridge_debugfs_sops = {
+ .start = mlx5_esw_bridge_debugfs_start,
+ .next = mlx5_esw_bridge_debugfs_next,
+ .stop = mlx5_esw_bridge_debugfs_stop,
+ .show = mlx5_esw_bridge_debugfs_show,
+};
+DEFINE_SEQ_ATTRIBUTE(mlx5_esw_bridge_debugfs);
+
+static void *mlx5_esw_bridge_debugfs_start(struct seq_file *seq, loff_t *pos)
+{
+ struct mlx5_esw_bridge *bridge = seq->private;
+
+ rtnl_lock();
+ return *pos ? seq_list_start(&bridge->fdb_list, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *mlx5_esw_bridge_debugfs_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct mlx5_esw_bridge *bridge = seq->private;
+
+ return seq_list_next(v == SEQ_START_TOKEN ? &bridge->fdb_list : v, &bridge->fdb_list, pos);
+}
+
+static void mlx5_esw_bridge_debugfs_stop(struct seq_file *seq, void *v)
+{
+ rtnl_unlock();
+}
+
+static int mlx5_esw_bridge_debugfs_show(struct seq_file *seq, void *v)
+{
+ struct mlx5_esw_bridge_fdb_entry *entry;
+ u64 packets, bytes, lastuse;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "%-16s %-17s %4s %20s %20s %20s %5s\n",
+ "DEV", "MAC", "VLAN", "PACKETS", "BYTES", "LASTUSE", "FLAGS");
+ return 0;
+ }
+
+ entry = list_entry(v, struct mlx5_esw_bridge_fdb_entry, list);
+ mlx5_fc_query_cached_raw(entry->ingress_counter, &bytes, &packets, &lastuse);
+ seq_printf(seq, "%-16s %-17pM %4d %20llu %20llu %20llu %#5x\n",
+ entry->dev->name, entry->key.addr, entry->key.vid, packets, bytes, lastuse,
+ entry->flags);
+ return 0;
+}
+
+void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge)
+{
+ if (!bridge->br_offloads->debugfs_root)
+ return;
+
+ bridge->debugfs_dir = debugfs_create_dir(br_netdev->name,
+ bridge->br_offloads->debugfs_root);
+ debugfs_create_file("fdb", 0400, bridge->debugfs_dir, bridge,
+ &mlx5_esw_bridge_debugfs_fops);
+}
+
+void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge)
+{
+ debugfs_remove_recursive(bridge->debugfs_dir);
+ bridge->debugfs_dir = NULL;
+}
+
+void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads)
+{
+ if (!br_offloads->esw->debugfs_root)
+ return;
+
+ br_offloads->debugfs_root = debugfs_create_dir("bridge", br_offloads->esw->debugfs_root);
+}
+
+void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads)
+{
+ debugfs_remove_recursive(br_offloads->debugfs_root);
+ br_offloads->debugfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
index 2eae594a5e80..2455f8b93c1e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c
@@ -540,16 +540,29 @@ static struct mlx5_flow_handle *
mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port)
{
struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom;
+ struct mlx5_eswitch *tmp, *peer_esw = NULL;
static struct mlx5_flow_handle *handle;
- struct mlx5_eswitch *peer_esw;
+ int i;
- peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
- if (!peer_esw)
+ if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
return ERR_PTR(-ENODEV);
+ mlx5_devcom_for_each_peer_entry(devcom,
+ MLX5_DEVCOM_ESW_OFFLOADS,
+ tmp, i) {
+ if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) {
+ peer_esw = tmp;
+ break;
+ }
+ }
+ if (!peer_esw) {
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ return ERR_PTR(-ENODEV);
+ }
+
handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw);
- mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
return handle;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
index c9595801bdb4..4911cc32161b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_priv.h
@@ -199,6 +199,7 @@ struct mlx5_esw_bridge {
int refcnt;
struct list_head list;
struct mlx5_esw_bridge_offloads *br_offloads;
+ struct dentry *debugfs_dir;
struct list_head fdb_list;
struct rhashtable fdb_ht;
@@ -241,4 +242,9 @@ void mlx5_esw_bridge_port_mdb_vlan_flush(struct mlx5_esw_bridge_port *port,
struct mlx5_esw_bridge_vlan *vlan);
void mlx5_esw_bridge_mdb_flush(struct mlx5_esw_bridge *bridge);
+void mlx5_esw_bridge_debugfs_offloads_init(struct mlx5_esw_bridge_offloads *br_offloads);
+void mlx5_esw_bridge_debugfs_offloads_cleanup(struct mlx5_esw_bridge_offloads *br_offloads);
+void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_bridge *bridge);
+void mlx5_esw_bridge_debugfs_cleanup(struct mlx5_esw_bridge *bridge);
+
#endif /* _MLX5_ESW_BRIDGE_PRIVATE_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index 084a910bb4e7..2170539461fa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -18,23 +18,21 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_
{
return vport_num == MLX5_VPORT_UPLINK ||
(mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) ||
- mlx5_eswitch_is_vf_vport(esw, vport_num);
+ mlx5_eswitch_is_vf_vport(esw, vport_num) ||
+ mlx5_core_is_ec_vf_vport(esw->dev, vport_num);
}
-static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num)
+static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch *esw,
+ u16 vport_num,
+ struct devlink_port *dl_port)
{
struct mlx5_core_dev *dev = esw->dev;
struct devlink_port_attrs attrs = {};
struct netdev_phys_item_id ppid = {};
- struct devlink_port *dl_port;
u32 controller_num = 0;
bool external;
u16 pfnum;
- dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
- if (!dl_port)
- return NULL;
-
mlx5_esw_get_port_parent_id(dev, &ppid);
pfnum = mlx5_get_dev_index(dev);
external = mlx5_core_is_ecpf_esw_manager(dev);
@@ -56,15 +54,57 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16
dl_port->attrs.switch_id.id_len = ppid.id_len;
devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
vport_num - 1, external);
+ } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) {
+ memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
+ dl_port->attrs.switch_id.id_len = ppid.id_len;
+ devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum,
+ vport_num - 1, false);
}
- return dl_port;
}
-static void mlx5_esw_dl_port_free(struct devlink_port *dl_port)
+int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num)
+{
+ struct devlink_port *dl_port;
+ struct mlx5_vport *vport;
+
+ if (!mlx5_esw_devlink_port_supported(esw, vport_num))
+ return 0;
+
+ vport = mlx5_eswitch_get_vport(esw, vport_num);
+ if (IS_ERR(vport))
+ return PTR_ERR(vport);
+
+ dl_port = kzalloc(sizeof(*dl_port), GFP_KERNEL);
+ if (!dl_port)
+ return -ENOMEM;
+
+ mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(esw, vport_num, dl_port);
+
+ vport->dl_port = dl_port;
+ return 0;
+}
+
+void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num)
{
- kfree(dl_port);
+ struct mlx5_vport *vport;
+
+ vport = mlx5_eswitch_get_vport(esw, vport_num);
+ if (IS_ERR(vport) || !vport->dl_port)
+ return;
+
+ kfree(vport->dl_port);
+ vport->dl_port = NULL;
}
+static const struct devlink_port_ops mlx5_esw_dl_port_ops = {
+ .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
+ .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
+ .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
+ .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
+ .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
+};
+
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num)
{
struct mlx5_core_dev *dev = esw->dev;
@@ -74,34 +114,29 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_
struct devlink *devlink;
int err;
- if (!mlx5_esw_devlink_port_supported(esw, vport_num))
- return 0;
-
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
return PTR_ERR(vport);
- dl_port = mlx5_esw_dl_port_alloc(esw, vport_num);
+ dl_port = vport->dl_port;
if (!dl_port)
- return -ENOMEM;
+ return 0;
devlink = priv_to_devlink(dev);
dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
- err = devl_port_register(devlink, dl_port, dl_port_index);
+ err = devl_port_register_with_ops(devlink, dl_port, dl_port_index,
+ &mlx5_esw_dl_port_ops);
if (err)
- goto reg_err;
+ return err;
err = devl_rate_leaf_create(dl_port, vport, NULL);
if (err)
goto rate_err;
- vport->dl_port = dl_port;
return 0;
rate_err:
devl_port_unregister(dl_port);
-reg_err:
- mlx5_esw_dl_port_free(dl_port);
return err;
}
@@ -109,11 +144,8 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vpo
{
struct mlx5_vport *vport;
- if (!mlx5_esw_devlink_port_supported(esw, vport_num))
- return;
-
vport = mlx5_eswitch_get_vport(esw, vport_num);
- if (IS_ERR(vport))
+ if (IS_ERR(vport) || !vport->dl_port)
return;
if (vport->dl_port->devlink_rate) {
@@ -122,8 +154,6 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vpo
}
devl_port_unregister(vport->dl_port);
- mlx5_esw_dl_port_free(vport->dl_port);
- vport->dl_port = NULL;
}
struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num)
@@ -134,6 +164,20 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1
return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port;
}
+static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = {
+#ifdef CONFIG_MLX5_SF_MANAGER
+ .port_del = mlx5_devlink_sf_port_del,
+#endif
+ .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get,
+ .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set,
+ .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
+ .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
+#ifdef CONFIG_MLX5_SF_MANAGER
+ .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get,
+ .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set,
+#endif
+};
+
int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port,
u16 vport_num, u32 controller, u32 sfnum)
{
@@ -156,7 +200,8 @@ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_p
devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller);
devlink = priv_to_devlink(dev);
dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num);
- err = devl_port_register(devlink, dl_port, dl_port_index);
+ err = devl_port_register_with_ops(devlink, dl_port, dl_port_index,
+ &mlx5_esw_dl_sf_port_ops);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
index fabe49a35a5c..255bc8b749f9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
@@ -285,9 +285,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
- } else {
- esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
}
+ esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
/* Star rule to forward all traffic to uplink vport */
memset(&dest, 0, sizeof(dest));
@@ -299,9 +298,8 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
- } else {
- esw->fdb_table.legacy.vepa_star_rule = flow_rule;
}
+ esw->fdb_table.legacy.vepa_star_rule = flow_rule;
out:
kvfree(spec);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 901c53751b0a..6e9b1b183190 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -31,6 +31,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/debugfs.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/mlx5/vport.h>
@@ -41,6 +42,7 @@
#include "esw/qos.h"
#include "mlx5_core.h"
#include "lib/eq.h"
+#include "lag/lag.h"
#include "eswitch.h"
#include "fs_core.h"
#include "devlink.h"
@@ -92,7 +94,7 @@ mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
{
struct mlx5_vport *vport;
- if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
+ if (!esw)
return ERR_PTR(-EPERM);
vport = xa_load(&esw->vports, vport_num);
@@ -113,7 +115,8 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
- MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
+ if (vport || mlx5_core_is_ecpf(dev))
+ MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
in, nic_vport_context);
@@ -309,11 +312,12 @@ static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
fdb_add:
/* SRIOV is enabled: Forward UC MAC to vport */
- if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY)
+ if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) {
vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
- esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
- vport, mac, vaddr->flow_rule);
+ esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
+ vport, mac, vaddr->flow_rule);
+ }
return 0;
}
@@ -710,6 +714,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport)
struct mlx5_eswitch *esw = dev->priv.eswitch;
u8 mac[ETH_ALEN];
+ if (!MLX5_CAP_GEN(dev, log_max_l2_table))
+ return;
+
mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac);
esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
vport->vport, mac);
@@ -800,6 +807,9 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce);
+ if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2))
+ goto out_free;
+
memset(query_ctx, 0, query_out_sz);
err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
MLX5_CAP_GENERAL_2);
@@ -946,7 +956,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
vport->enabled = false;
/* Disable events from this vport */
- arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
+ if (MLX5_CAP_GEN(esw->dev, log_max_l2_table))
+ arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
if (!mlx5_esw_is_manager_vport(esw, vport->vport) &&
MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
@@ -1045,6 +1056,18 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
}
}
+static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ memset(&vport->qos, 0, sizeof(vport->qos));
+ memset(&vport->info, 0, sizeof(vport->info));
+ vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+ }
+}
+
/* Public E-Switch API */
int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
enum mlx5_eswitch_vport_event enabled_events)
@@ -1055,7 +1078,7 @@ int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
if (err)
return err;
- err = esw_offloads_load_rep(esw, vport_num);
+ err = mlx5_esw_offloads_load_rep(esw, vport_num);
if (err)
goto err_rep;
@@ -1068,10 +1091,35 @@ err_rep:
void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
{
- esw_offloads_unload_rep(esw, vport_num);
+ mlx5_esw_offloads_unload_rep(esw, vport_num);
mlx5_esw_vport_disable(esw, vport_num);
}
+static int mlx5_eswitch_load_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num,
+ enum mlx5_eswitch_vport_event enabled_events)
+{
+ int err;
+
+ err = mlx5_esw_offloads_init_pf_vf_rep(esw, vport_num);
+ if (err)
+ return err;
+
+ err = mlx5_eswitch_load_vport(esw, vport_num, enabled_events);
+ if (err)
+ goto err_load;
+ return 0;
+
+err_load:
+ mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num);
+ return err;
+}
+
+static void mlx5_eswitch_unload_pf_vf_vport(struct mlx5_eswitch *esw, u16 vport_num)
+{
+ mlx5_eswitch_unload_vport(esw, vport_num);
+ mlx5_esw_offloads_cleanup_pf_vf_rep(esw, vport_num);
+}
+
void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
{
struct mlx5_vport *vport;
@@ -1080,7 +1128,20 @@ void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
if (!vport->enabled)
continue;
- mlx5_eswitch_unload_vport(esw, vport->vport);
+ mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport);
+ }
+}
+
+static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw,
+ u16 num_ec_vfs)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
+ if (!vport->enabled)
+ continue;
+ mlx5_eswitch_unload_pf_vf_vport(esw, vport->vport);
}
}
@@ -1092,7 +1153,7 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
int err;
mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
- err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events);
+ err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events);
if (err)
goto vf_err;
}
@@ -1104,6 +1165,26 @@ vf_err:
return err;
}
+static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs,
+ enum mlx5_eswitch_vport_event enabled_events)
+{
+ struct mlx5_vport *vport;
+ unsigned long i;
+ int err;
+
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) {
+ err = mlx5_eswitch_load_pf_vf_vport(esw, vport->vport, enabled_events);
+ if (err)
+ goto vf_err;
+ }
+
+ return 0;
+
+vf_err:
+ mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs);
+ return err;
+}
+
static int host_pf_enable_hca(struct mlx5_core_dev *dev)
{
if (!mlx5_core_is_ecpf(dev))
@@ -1131,12 +1212,19 @@ int
mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
enum mlx5_eswitch_vport_event enabled_events)
{
+ bool pf_needed;
int ret;
+ pf_needed = mlx5_core_is_ecpf_esw_manager(esw->dev) ||
+ esw->mode == MLX5_ESWITCH_LEGACY;
+
/* Enable PF vport */
- ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events);
- if (ret)
- return ret;
+ if (pf_needed) {
+ ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_PF,
+ enabled_events);
+ if (ret)
+ return ret;
+ }
/* Enable external host PF HCA */
ret = host_pf_enable_hca(esw->dev);
@@ -1145,9 +1233,15 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
/* Enable ECPF vport */
if (mlx5_ecpf_vport_exists(esw->dev)) {
- ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
+ ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events);
if (ret)
goto ecpf_err;
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs,
+ enabled_events);
+ if (ret)
+ goto ec_vf_err;
+ }
}
/* Enable VF vports */
@@ -1158,12 +1252,16 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
return 0;
vf_err:
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
+ec_vf_err:
if (mlx5_ecpf_vport_exists(esw->dev))
- mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
+ mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
ecpf_err:
host_pf_disable_hca(esw->dev);
pf_hca_err:
- mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
+ if (pf_needed)
+ mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF);
return ret;
}
@@ -1174,11 +1272,17 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
{
mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
- if (mlx5_ecpf_vport_exists(esw->dev))
- mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
+ if (mlx5_ecpf_vport_exists(esw->dev)) {
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs);
+ mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
+ }
host_pf_disable_hca(esw->dev);
- mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
+
+ if (mlx5_core_is_ecpf_esw_manager(esw->dev) ||
+ esw->mode == MLX5_ESWITCH_LEGACY)
+ mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF);
}
static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
@@ -1219,6 +1323,9 @@ mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
host_params_context.host_num_of_vfs);
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ esw->esw_funcs.num_ec_vfs = num_vfs;
+
kvfree(out);
}
@@ -1326,9 +1433,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
mlx5_eswitch_event_handlers_register(esw);
- esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
mlx5_esw_mode_change_notify(esw, esw->mode);
@@ -1350,7 +1457,7 @@ abort:
int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
{
bool toggle_lag;
- int ret;
+ int ret = 0;
if (!mlx5_esw_allowed(esw))
return 0;
@@ -1370,10 +1477,21 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ?
MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE;
- ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
- if (!ret)
- esw->esw_funcs.num_vfs = num_vfs;
+ /* If this is the ECPF the number of host VFs is managed via the
+ * eswitch function change event handler, and any num_vfs provided
+ * here are intended to be EC VFs.
+ */
+ if (!mlx5_core_is_ecpf(esw->dev)) {
+ ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events);
+ if (!ret)
+ esw->esw_funcs.num_vfs = num_vfs;
+ } else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events);
+ if (!ret)
+ esw->esw_funcs.num_ec_vfs = num_vfs;
+ }
}
+
up_write(&esw->mode_lock);
if (toggle_lag)
@@ -1393,16 +1511,22 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
/* If driver is unloaded, this function is called twice by remove_one()
* and mlx5_unload(). Prevent the second call.
*/
- if (!esw->esw_funcs.num_vfs && !clear_vf)
+ if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf)
goto unlock;
- esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
-
- mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
- if (clear_vf)
- mlx5_eswitch_clear_vf_vports_info(esw);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
+
+ if (!mlx5_core_is_ecpf(esw->dev)) {
+ mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
+ if (clear_vf)
+ mlx5_eswitch_clear_vf_vports_info(esw);
+ } else if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs);
+ if (clear_vf)
+ mlx5_eswitch_clear_ec_vf_vports_info(esw);
+ }
if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
struct devlink *devlink = priv_to_devlink(esw->dev);
@@ -1413,7 +1537,10 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
if (esw->mode == MLX5_ESWITCH_LEGACY)
mlx5_eswitch_disable_locked(esw);
- esw->esw_funcs.num_vfs = 0;
+ if (!mlx5_core_is_ecpf(esw->dev))
+ esw->esw_funcs.num_vfs = 0;
+ else
+ esw->esw_funcs.num_ec_vfs = 0;
unlock:
up_write(&esw->mode_lock);
@@ -1433,9 +1560,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
mlx5_eswitch_event_handlers_unregister(esw);
- esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
+ esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
- esw->esw_funcs.num_vfs, esw->enabled_vports);
+ esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) {
esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED;
@@ -1595,7 +1722,19 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
idx++;
}
- if (mlx5_ecpf_vport_exists(dev)) {
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev);
+
+ for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) {
+ err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i);
+ if (err)
+ goto err;
+ idx++;
+ }
+ }
+
+ if (mlx5_ecpf_vport_exists(dev) ||
+ mlx5_core_is_ecpf_esw_manager(dev)) {
err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF);
if (err)
goto err;
@@ -1611,22 +1750,60 @@ err:
return err;
}
+static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+ if (!MLX5_ESWITCH_MANAGER(dev))
+ return -EOPNOTSUPP;
+
+ if (ctx->val.vbool)
+ return mlx5_lag_mpesw_enable(dev);
+
+ mlx5_lag_mpesw_disable(dev);
+ return 0;
+}
+
+static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+ ctx->val.vbool = mlx5_lag_is_mpesw(dev);
+ return 0;
+}
+
+static const struct devlink_param mlx5_eswitch_params[] = {
+ DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT,
+ "esw_multiport", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ mlx5_devlink_esw_multiport_get,
+ mlx5_devlink_esw_multiport_set, NULL),
+};
+
int mlx5_eswitch_init(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw;
int err;
- if (!MLX5_VPORT_MANAGER(dev))
+ if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev))
return 0;
esw = kzalloc(sizeof(*esw), GFP_KERNEL);
if (!esw)
return -ENOMEM;
+ err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
+ if (err)
+ goto free_esw;
+
esw->dev = dev;
esw->manager_vport = mlx5_eswitch_manager_vport(dev);
esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
+ esw->debugfs_root = debugfs_create_dir("esw", mlx5_debugfs_get_dev_root(dev));
esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
if (!esw->work_queue) {
err = -ENOMEM;
@@ -1680,13 +1857,17 @@ reps_err:
abort:
if (esw->work_queue)
destroy_workqueue(esw->work_queue);
+ debugfs_remove_recursive(esw->debugfs_root);
+ devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
+free_esw:
kfree(esw);
return err;
}
void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
{
- if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
+ if (!esw)
return;
esw_info(esw->dev, "cleanup\n");
@@ -1703,6 +1884,9 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
mutex_destroy(&esw->offloads.decap_tbl_lock);
esw_offloads_cleanup(esw);
mlx5_esw_vports_cleanup(esw);
+ debugfs_remove_recursive(esw->debugfs_root);
+ devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params,
+ ARRAY_SIZE(mlx5_eswitch_params));
kfree(esw);
}
@@ -1763,12 +1947,6 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
static bool mlx5_esw_check_port_type(struct mlx5_eswitch *esw, u16 vport_num, xa_mark_t mark)
{
- struct mlx5_vport *vport;
-
- vport = mlx5_eswitch_get_vport(esw, vport_num);
- if (IS_ERR(vport))
- return false;
-
return xa_get_mark(&esw->vports, vport_num, mark);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index add6cfa432a5..56d9a261a5c8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -123,8 +123,14 @@ struct vport_ingress {
} offloads;
};
+enum vport_egress_acl_type {
+ VPORT_EGRESS_ACL_TYPE_DEFAULT,
+ VPORT_EGRESS_ACL_TYPE_SHARED_FDB,
+};
+
struct vport_egress {
struct mlx5_flow_table *acl;
+ enum vport_egress_acl_type type;
struct mlx5_flow_handle *allowed_vlan;
struct mlx5_flow_group *vlan_grp;
union {
@@ -136,7 +142,7 @@ struct vport_egress {
struct {
struct mlx5_flow_group *fwd_grp;
struct mlx5_flow_handle *fwd_rule;
- struct mlx5_flow_handle *bounce_rule;
+ struct xarray bounce_rules;
struct mlx5_flow_group *bounce_grp;
} offloads;
};
@@ -218,7 +224,7 @@ struct mlx5_eswitch_fdb {
struct mlx5_flow_group *send_to_vport_grp;
struct mlx5_flow_group *send_to_vport_meta_grp;
struct mlx5_flow_group *peer_miss_grp;
- struct mlx5_flow_handle **peer_miss_rules;
+ struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS];
struct mlx5_flow_group *miss_grp;
struct mlx5_flow_handle **send_to_vport_meta_rules;
struct mlx5_flow_handle *miss_rule_uni;
@@ -249,7 +255,7 @@ struct mlx5_esw_offload {
struct mlx5_flow_group *vport_rx_drop_group;
struct mlx5_flow_handle *vport_rx_drop_rule;
struct xarray vport_reps;
- struct list_head peer_flows;
+ struct list_head peer_flows[MLX5_MAX_PORTS];
struct mutex peer_mutex;
struct mutex encap_tbl_lock; /* protects encap_tbl */
DECLARE_HASHTABLE(encap_tbl, 8);
@@ -283,6 +289,7 @@ struct mlx5_host_work {
struct mlx5_esw_functions {
struct mlx5_nb nb;
u16 num_vfs;
+ u16 num_ec_vfs;
};
enum {
@@ -297,6 +304,8 @@ enum {
MLX5_ESW_FDB_CREATED = BIT(0),
};
+struct dentry;
+
struct mlx5_eswitch {
struct mlx5_core_dev *dev;
struct mlx5_nb nb;
@@ -305,6 +314,7 @@ struct mlx5_eswitch {
struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE];
struct esw_mc_addr mc_promisc;
/* end of legacy */
+ struct dentry *debugfs_root;
struct workqueue_struct *work_queue;
struct xarray vports;
u32 flags;
@@ -337,12 +347,13 @@ struct mlx5_eswitch {
int mode;
u16 manager_vport;
u16 first_host_vport;
+ u8 num_peers;
struct mlx5_esw_functions esw_funcs;
struct {
u32 large_group_num;
} params;
struct blocking_notifier_head n_head;
- bool paired[MLX5_MAX_PORTS];
+ struct xarray paired;
};
void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -506,12 +517,12 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
struct netlink_ext_ack *extack);
int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
enum devlink_eswitch_encap_mode *encap);
-int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
- u8 *hw_addr, int *hw_addr_len,
- struct netlink_ext_ack *extack);
-int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
- const u8 *hw_addr, int hw_addr_len,
- struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port,
+ const u8 *hw_addr, int hw_addr_len,
+ struct netlink_ext_ack *extack);
int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
struct netlink_ext_ack *extack);
int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
@@ -578,6 +589,13 @@ mlx5_esw_is_manager_vport(const struct mlx5_eswitch *esw, u16 vport_num)
return esw->manager_vport == vport_num;
}
+static inline bool mlx5_esw_is_owner(struct mlx5_eswitch *esw, u16 vport_num,
+ u16 esw_owner_vhca_id)
+{
+ return esw_owner_vhca_id == MLX5_CAP_GEN(esw->dev, vhca_id) ||
+ (vport_num == MLX5_VPORT_UPLINK && mlx5_lag_is_master(esw->dev));
+}
+
static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev)
{
return mlx5_core_is_ecpf_esw_manager(dev) ?
@@ -640,6 +658,19 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw);
#define mlx5_esw_for_each_host_func_vport(esw, index, vport, last) \
mlx5_esw_for_each_vport_marked(esw, index, vport, last, MLX5_ESW_VPT_HOST_FN)
+/* This macro should only be used if EC SRIOV is enabled.
+ *
+ * Because there were no more marks available on the xarray this uses a
+ * for_each_range approach. The range is only valid when EC SRIOV is enabled
+ */
+#define mlx5_esw_for_each_ec_vf_vport(esw, index, vport, last) \
+ xa_for_each_range(&((esw)->vports), \
+ index, \
+ vport, \
+ MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base), \
+ MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\
+ (last) - 1)
+
struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink);
struct mlx5_vport *__must_check
mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num);
@@ -686,8 +717,18 @@ mlx5_esw_vporttbl_put(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr
struct mlx5_flow_handle *
esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag);
-int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num);
-void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num);
+void mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
+ u32 *flow_group_in,
+ int match_params);
+
+void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw,
+ u16 vport,
+ struct mlx5_flow_spec *spec);
+
+int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num);
+void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num);
+int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num);
+void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num);
int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num);
void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num);
@@ -700,6 +741,8 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
enum mlx5_eswitch_vport_event enabled_events);
void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs);
+int mlx5_esw_offloads_pf_vf_devlink_port_init(struct mlx5_eswitch *esw, u16 vport_num);
+void mlx5_esw_offloads_pf_vf_devlink_port_cleanup(struct mlx5_eswitch *esw, u16 vport_num);
int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num);
void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 vport_num);
struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num);
@@ -740,9 +783,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport);
bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller);
-int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw);
-void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves);
+void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw);
int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw);
@@ -757,6 +800,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw)
return 0;
}
+static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw)
+{
+ if (mlx5_esw_allowed(esw))
+ return esw->num_peers;
+ return 0;
+}
+
static inline struct mlx5_flow_table *
mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw)
{
@@ -794,16 +844,18 @@ mlx5_esw_vport_to_devlink_port_index(const struct mlx5_core_dev *dev,
}
static inline int
-mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw)
+mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves)
{
return 0;
}
static inline void
-mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw) {}
+static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; }
+
static inline int
mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 8d19c20d3447..1ad5a72dcc3f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -55,13 +55,6 @@
#define mlx5_esw_for_each_rep(esw, i, rep) \
xa_for_each(&((esw)->offloads.vport_reps), i, rep)
-#define mlx5_esw_for_each_sf_rep(esw, i, rep) \
- xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF)
-
-#define mlx5_esw_for_each_vf_rep(esw, index, rep) \
- mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \
- rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF)
-
/* There are two match-all miss flows, one for unicast dst mac and
* one for multicast.
*/
@@ -838,6 +831,7 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
void *misc;
+ u16 vport;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec) {
@@ -847,20 +841,43 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw,
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn);
- /* source vport is the esw manager */
- MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport);
- if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
- MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
- MLX5_CAP_GEN(from_esw->dev, vhca_id));
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn);
- MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
- if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
- MLX5_SET_TO_ONES(fte_match_set_misc, misc,
- source_eswitch_owner_vhca_id);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+
+ /* source vport is the esw manager */
+ vport = from_esw->manager_vport;
+
+ if (mlx5_eswitch_vport_match_metadata_enabled(on_esw)) {
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
+ MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
+ mlx5_eswitch_get_vport_metadata_for_match(from_esw, vport));
+
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2);
+ MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
+ mlx5_eswitch_get_vport_metadata_mask());
+
+ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
+ } else {
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
+ MLX5_SET(fte_match_set_misc, misc, source_port, vport);
+
+ if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
+ MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
+ MLX5_CAP_GEN(from_esw->dev, vhca_id));
+
+ misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
+ MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
+
+ if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch))
+ MLX5_SET_TO_ONES(fte_match_set_misc, misc,
+ source_eswitch_owner_vhca_id);
+
+ spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
+ }
+
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport.num = rep->vport;
dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id);
@@ -1052,6 +1069,9 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
void *misc;
int err;
+ if (!MLX5_VPORT_MANAGER(esw->dev) && !mlx5_core_is_ecpf_esw_manager(esw->dev))
+ return 0;
+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -1108,11 +1128,32 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
flows[vport->index] = flow;
}
- esw->fdb_table.offloads.peer_miss_rules = flows;
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ if (i >= mlx5_core_max_ec_vfs(peer_dev))
+ break;
+ esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
+ spec, vport->vport);
+ flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
+ spec, &flow_act, &dest, 1);
+ if (IS_ERR(flow)) {
+ err = PTR_ERR(flow);
+ goto add_ec_vf_flow_err;
+ }
+ flows[vport->index] = flow;
+ }
+ }
+ esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)] = flows;
kvfree(spec);
return 0;
+add_ec_vf_flow_err:
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ if (!flows[vport->index])
+ continue;
+ mlx5_del_flow_rules(flows[vport->index]);
+ }
add_vf_flow_err:
mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
if (!flows[vport->index])
@@ -1136,13 +1177,28 @@ alloc_flows_err:
return err;
}
-static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
+static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
+ struct mlx5_core_dev *peer_dev)
{
+ u16 peer_index = mlx5_get_dev_index(peer_dev);
struct mlx5_flow_handle **flows;
struct mlx5_vport *vport;
unsigned long i;
- flows = esw->fdb_table.offloads.peer_miss_rules;
+ flows = esw->fdb_table.offloads.peer_miss_rules[peer_index];
+ if (!flows)
+ return;
+
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
+ /* The flow for a particular vport could be NULL if the other ECPF
+ * has fewer or no VFs enabled
+ */
+ if (!flows[vport->index])
+ continue;
+ mlx5_del_flow_rules(flows[vport->index]);
+ }
+ }
mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev))
mlx5_del_flow_rules(flows[vport->index]);
@@ -1156,7 +1212,9 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
mlx5_del_flow_rules(flows[vport->index]);
}
+
kvfree(flows);
+ esw->fdb_table.offloads.peer_miss_rules[peer_index] = NULL;
}
static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
@@ -1269,8 +1327,10 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag)
#define MAX_PF_SQ 256
#define MAX_SQ_NVPORTS 32
-static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
- u32 *flow_group_in)
+void
+mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
+ u32 *flow_group_in,
+ int match_params)
{
void *match_criteria = MLX5_ADDR_OF(create_flow_group_in,
flow_group_in,
@@ -1279,7 +1339,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
MLX5_SET(create_flow_group_in, flow_group_in,
match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS_2);
+ MLX5_MATCH_MISC_PARAMETERS_2 | match_params);
MLX5_SET(fte_match_param, match_criteria,
misc_parameters_2.metadata_reg_c_0,
@@ -1287,7 +1347,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw,
} else {
MLX5_SET(create_flow_group_in, flow_group_in,
match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
+ MLX5_MATCH_MISC_PARAMETERS | match_params);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
misc_parameters.source_port);
@@ -1376,7 +1436,6 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
esw_init_chains_offload_flags(esw, &attr.flags);
attr.ns = MLX5_FLOW_NAMESPACE_FDB;
- attr.fs_base_prio = FDB_TC_OFFLOAD;
attr.max_grp_num = esw->params.large_group_num;
attr.default_ft = miss_fdb;
attr.mapping = esw->offloads.reg_c0_obj_pool;
@@ -1463,14 +1522,13 @@ esw_create_send_to_vport_group(struct mlx5_eswitch *esw,
memset(flow_group_in, 0, inlen);
- MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, MLX5_MATCH_MISC_PARAMETERS);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
-
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn);
- MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
- if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
+
+ if (!mlx5_eswitch_vport_match_metadata_enabled(esw) &&
+ MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
misc_parameters.source_eswitch_owner_vhca_id);
MLX5_SET(create_flow_group_in, flow_group_in,
@@ -1548,6 +1606,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
u32 *flow_group_in,
int *ix)
{
+ int max_peer_ports = (esw->total_vports - 1) * (MLX5_MAX_PORTS - 1);
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_flow_group *g;
void *match_criteria;
@@ -1558,7 +1617,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
memset(flow_group_in, 0, inlen);
- esw_set_flow_group_source_port(esw, flow_group_in);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
match_criteria = MLX5_ADDR_OF(create_flow_group_in,
@@ -1574,8 +1633,8 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
- *ix + esw->total_vports - 1);
- *ix += esw->total_vports;
+ *ix + max_peer_ports);
+ *ix += max_peer_ports + 1;
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
@@ -1677,7 +1736,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
* total vports of the peer (currently is also uses esw->total_vports).
*/
table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) +
- esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS;
+ esw->total_vports * MLX5_MAX_PORTS + MLX5_ESW_MISS_FLOWS;
/* create the slow path fdb with encap set, so further table instances
* can be created at run time while VFs are probed if the FW allows that.
@@ -1844,8 +1903,7 @@ static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
if (!flow_group_in)
return -ENOMEM;
- /* create vport rx group */
- esw_set_flow_group_source_port(esw, flow_group_in);
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1);
@@ -1915,21 +1973,13 @@ static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw)
mlx5_destroy_flow_group(esw->offloads.vport_rx_drop_group);
}
-struct mlx5_flow_handle *
-mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
- struct mlx5_flow_destination *dest)
+void
+mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw,
+ u16 vport,
+ struct mlx5_flow_spec *spec)
{
- struct mlx5_flow_act flow_act = {0};
- struct mlx5_flow_handle *flow_rule;
- struct mlx5_flow_spec *spec;
void *misc;
- spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
- if (!spec) {
- flow_rule = ERR_PTR(-ENOMEM);
- goto out;
- }
-
if (mlx5_eswitch_vport_match_metadata_enabled(esw)) {
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2);
MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0,
@@ -1949,6 +1999,23 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
}
+}
+
+struct mlx5_flow_handle *
+mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
+ struct mlx5_flow_destination *dest)
+{
+ struct mlx5_flow_act flow_act = {0};
+ struct mlx5_flow_handle *flow_rule;
+ struct mlx5_flow_spec *spec;
+
+ spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec) {
+ flow_rule = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ mlx5_esw_set_spec_source_port(esw, vport, spec);
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
@@ -2142,6 +2209,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Failed setting eswitch to offloads");
esw->mode = MLX5_ESWITCH_LEGACY;
mlx5_rescan_drivers(esw->dev);
+ return err;
}
if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
if (mlx5_eswitch_inline_mode_get(esw,
@@ -2151,19 +2219,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Inline mode is different between vports");
}
}
- return err;
-}
-
-static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
- struct mlx5_eswitch_rep *rep,
- xa_mark_t mark)
-{
- bool mark_set;
-
- /* Copy the mark from vport to its rep */
- mark_set = xa_get_mark(&esw->vports, rep->vport, mark);
- if (mark_set)
- xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark);
+ return 0;
}
static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport)
@@ -2185,9 +2241,6 @@ static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx
if (err)
goto insert_err;
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN);
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF);
- mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF);
return 0;
insert_err:
@@ -2328,37 +2381,13 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
esw->offloads.rep_ops[rep_type]->unload(rep);
}
-static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type)
-{
- struct mlx5_eswitch_rep *rep;
- unsigned long i;
-
- mlx5_esw_for_each_sf_rep(esw, i, rep)
- __esw_offloads_unload_rep(esw, rep, rep_type);
-}
-
static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type)
{
struct mlx5_eswitch_rep *rep;
unsigned long i;
- __unload_reps_sf_vport(esw, rep_type);
-
- mlx5_esw_for_each_vf_rep(esw, i, rep)
- __esw_offloads_unload_rep(esw, rep, rep_type);
-
- if (mlx5_ecpf_vport_exists(esw->dev)) {
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
- __esw_offloads_unload_rep(esw, rep, rep_type);
- }
-
- if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+ mlx5_esw_for_each_rep(esw, i, rep)
__esw_offloads_unload_rep(esw, rep, rep_type);
- }
-
- rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
- __esw_offloads_unload_rep(esw, rep, rep_type);
}
int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
@@ -2395,7 +2424,23 @@ void mlx5_esw_offloads_rep_unload(struct mlx5_eswitch *esw, u16 vport_num)
__esw_offloads_unload_rep(esw, rep, rep_type);
}
-int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
+int mlx5_esw_offloads_init_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num)
+{
+ if (esw->mode != MLX5_ESWITCH_OFFLOADS)
+ return 0;
+
+ return mlx5_esw_offloads_pf_vf_devlink_port_init(esw, vport_num);
+}
+
+void mlx5_esw_offloads_cleanup_pf_vf_rep(struct mlx5_eswitch *esw, u16 vport_num)
+{
+ if (esw->mode != MLX5_ESWITCH_OFFLOADS)
+ return;
+
+ mlx5_esw_offloads_pf_vf_devlink_port_cleanup(esw, vport_num);
+}
+
+int mlx5_esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num)
{
int err;
@@ -2419,7 +2464,7 @@ load_err:
return err;
}
-void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num)
+void mlx5_esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num)
{
if (esw->mode != MLX5_ESWITCH_OFFLOADS)
return;
@@ -2476,6 +2521,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
struct mlx5_vport *vport,
struct mlx5_flow_table *acl)
{
+ u16 slave_index = MLX5_CAP_GEN(slave, vhca_id);
struct mlx5_flow_handle *flow_rule = NULL;
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {};
@@ -2491,8 +2537,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
- MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id,
- MLX5_CAP_GEN(slave, vhca_id));
+ MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, slave_index);
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
@@ -2507,49 +2552,43 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master,
flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act,
&dest, 1);
- if (IS_ERR(flow_rule))
+ if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
- else
- vport->egress.offloads.bounce_rule = flow_rule;
+ } else {
+ err = xa_insert(&vport->egress.offloads.bounce_rules,
+ slave_index, flow_rule, GFP_KERNEL);
+ if (err)
+ mlx5_del_flow_rules(flow_rule);
+ }
kvfree(spec);
return err;
}
-static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
- struct mlx5_core_dev *slave)
+static int esw_master_egress_create_resources(struct mlx5_eswitch *esw,
+ struct mlx5_flow_namespace *egress_ns,
+ struct mlx5_vport *vport, size_t count)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
- struct mlx5_eswitch *esw = master->priv.eswitch;
struct mlx5_flow_table_attr ft_attr = {
- .max_fte = 1, .prio = 0, .level = 0,
- .flags = MLX5_FLOW_TABLE_OTHER_VPORT,
+ .max_fte = count, .prio = 0, .level = 0,
};
- struct mlx5_flow_namespace *egress_ns;
struct mlx5_flow_table *acl;
struct mlx5_flow_group *g;
- struct mlx5_vport *vport;
void *match_criteria;
u32 *flow_group_in;
int err;
- vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
- if (IS_ERR(vport))
- return PTR_ERR(vport);
-
- egress_ns = mlx5_get_flow_vport_acl_namespace(master,
- MLX5_FLOW_NAMESPACE_ESW_EGRESS,
- vport->index);
- if (!egress_ns)
- return -EINVAL;
-
if (vport->egress.acl)
- return -EINVAL;
+ return 0;
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;
+ if (vport->vport || mlx5_core_is_ecpf(esw->dev))
+ ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
+
acl = mlx5_create_vport_flow_table(egress_ns, &ft_attr, vport->vport);
if (IS_ERR(acl)) {
err = PTR_ERR(acl);
@@ -2568,7 +2607,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
MLX5_SET(create_flow_group_in, flow_group_in,
source_eswitch_owner_vhca_id_valid, 1);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
- MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
+ MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, count);
g = mlx5_create_flow_group(acl, flow_group_in);
if (IS_ERR(g)) {
@@ -2576,19 +2615,15 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
goto err_group;
}
- err = __esw_set_master_egress_rule(master, slave, vport, acl);
- if (err)
- goto err_rule;
-
vport->egress.acl = acl;
vport->egress.offloads.bounce_grp = g;
+ vport->egress.type = VPORT_EGRESS_ACL_TYPE_SHARED_FDB;
+ xa_init_flags(&vport->egress.offloads.bounce_rules, XA_FLAGS_ALLOC);
kvfree(flow_group_in);
return 0;
-err_rule:
- mlx5_destroy_flow_group(g);
err_group:
mlx5_destroy_flow_table(acl);
out:
@@ -2596,18 +2631,74 @@ out:
return err;
}
-static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev)
+static void esw_master_egress_destroy_resources(struct mlx5_vport *vport)
+{
+ if (!xa_empty(&vport->egress.offloads.bounce_rules))
+ return;
+ mlx5_destroy_flow_group(vport->egress.offloads.bounce_grp);
+ vport->egress.offloads.bounce_grp = NULL;
+ mlx5_destroy_flow_table(vport->egress.acl);
+ vport->egress.acl = NULL;
+}
+
+static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
+ struct mlx5_core_dev *slave, size_t count)
+{
+ struct mlx5_eswitch *esw = master->priv.eswitch;
+ u16 slave_index = MLX5_CAP_GEN(slave, vhca_id);
+ struct mlx5_flow_namespace *egress_ns;
+ struct mlx5_vport *vport;
+ int err;
+
+ vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
+ if (IS_ERR(vport))
+ return PTR_ERR(vport);
+
+ egress_ns = mlx5_get_flow_vport_acl_namespace(master,
+ MLX5_FLOW_NAMESPACE_ESW_EGRESS,
+ vport->index);
+ if (!egress_ns)
+ return -EINVAL;
+
+ if (vport->egress.acl && vport->egress.type != VPORT_EGRESS_ACL_TYPE_SHARED_FDB)
+ return 0;
+
+ err = esw_master_egress_create_resources(esw, egress_ns, vport, count);
+ if (err)
+ return err;
+
+ if (xa_load(&vport->egress.offloads.bounce_rules, slave_index))
+ return -EINVAL;
+
+ err = __esw_set_master_egress_rule(master, slave, vport, vport->egress.acl);
+ if (err)
+ goto err_rule;
+
+ return 0;
+
+err_rule:
+ esw_master_egress_destroy_resources(vport);
+ return err;
+}
+
+static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev,
+ struct mlx5_core_dev *slave_dev)
{
struct mlx5_vport *vport;
vport = mlx5_eswitch_get_vport(dev->priv.eswitch,
dev->priv.eswitch->manager_vport);
- esw_acl_egress_ofld_cleanup(vport);
+ esw_acl_egress_ofld_bounce_rule_destroy(vport, MLX5_CAP_GEN(slave_dev, vhca_id));
+
+ if (xa_empty(&vport->egress.offloads.bounce_rules)) {
+ esw_acl_egress_ofld_cleanup(vport);
+ xa_destroy(&vport->egress.offloads.bounce_rules);
+ }
}
-int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
- struct mlx5_eswitch *slave_esw)
+int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves)
{
int err;
@@ -2617,7 +2708,7 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
return err;
err = esw_set_master_egress_rule(master_esw->dev,
- slave_esw->dev);
+ slave_esw->dev, max_slaves);
if (err)
goto err_acl;
@@ -2625,21 +2716,21 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw,
err_acl:
esw_set_slave_root_fdb(NULL, slave_esw->dev);
-
return err;
}
-void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw,
+void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw)
{
- esw_unset_master_egress_rule(master_esw->dev);
esw_set_slave_root_fdb(NULL, slave_esw->dev);
+ esw_unset_master_egress_rule(master_esw->dev, slave_esw->dev);
}
#define ESW_OFFLOADS_DEVCOM_PAIR (0)
#define ESW_OFFLOADS_DEVCOM_UNPAIR (1)
-static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
+static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch *peer_esw)
{
const struct mlx5_eswitch_rep_ops *ops;
struct mlx5_eswitch_rep *rep;
@@ -2652,18 +2743,19 @@ static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw)
ops = esw->offloads.rep_ops[rep_type];
if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED &&
ops->event)
- ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL);
+ ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, peer_esw);
}
}
}
-static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw)
+static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch *peer_esw)
{
#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
mlx5e_tc_clean_fdb_peer_flows(esw);
#endif
- mlx5_esw_offloads_rep_event_unpair(esw);
- esw_del_fdb_peer_miss_rules(esw);
+ mlx5_esw_offloads_rep_event_unpair(esw, peer_esw);
+ esw_del_fdb_peer_miss_rules(esw, peer_esw->dev);
}
static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
@@ -2694,7 +2786,7 @@ static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw,
return 0;
err_out:
- mlx5_esw_offloads_unpair(esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
return err;
}
@@ -2702,6 +2794,8 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
struct mlx5_eswitch *peer_esw,
bool pair)
{
+ u16 peer_vhca_id = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ u16 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
struct mlx5_flow_root_namespace *peer_ns;
struct mlx5_flow_root_namespace *ns;
int err;
@@ -2710,18 +2804,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
ns = esw->dev->priv.steering->fdb_root_ns;
if (pair) {
- err = mlx5_flow_namespace_set_peer(ns, peer_ns);
+ err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_vhca_id);
if (err)
return err;
- err = mlx5_flow_namespace_set_peer(peer_ns, ns);
+ err = mlx5_flow_namespace_set_peer(peer_ns, ns, vhca_id);
if (err) {
- mlx5_flow_namespace_set_peer(ns, NULL);
+ mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
return err;
}
} else {
- mlx5_flow_namespace_set_peer(ns, NULL);
- mlx5_flow_namespace_set_peer(peer_ns, NULL);
+ mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
+ mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id);
}
return 0;
@@ -2734,15 +2828,21 @@ static int mlx5_esw_offloads_devcom_event(int event,
struct mlx5_eswitch *esw = my_data;
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
struct mlx5_eswitch *peer_esw = event_data;
+ u16 esw_i, peer_esw_i;
+ bool esw_paired;
int err;
+ peer_esw_i = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+ esw_i = MLX5_CAP_GEN(esw->dev, vhca_id);
+ esw_paired = !!xa_load(&esw->paired, peer_esw_i);
+
switch (event) {
case ESW_OFFLOADS_DEVCOM_PAIR:
if (mlx5_eswitch_vport_match_metadata_enabled(esw) !=
mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
break;
- if (esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+ if (esw_paired)
break;
err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
@@ -2756,28 +2856,43 @@ static int mlx5_esw_offloads_devcom_event(int event,
if (err)
goto err_pair;
- esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true;
- peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true;
- mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
+ err = xa_insert(&esw->paired, peer_esw_i, peer_esw, GFP_KERNEL);
+ if (err)
+ goto err_xa;
+
+ err = xa_insert(&peer_esw->paired, esw_i, esw, GFP_KERNEL);
+ if (err)
+ goto err_peer_xa;
+
+ esw->num_peers++;
+ peer_esw->num_peers++;
+ mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
break;
case ESW_OFFLOADS_DEVCOM_UNPAIR:
- if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+ if (!esw_paired)
break;
- mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
- esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false;
- peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false;
- mlx5_esw_offloads_unpair(peer_esw);
- mlx5_esw_offloads_unpair(esw);
+ peer_esw->num_peers--;
+ esw->num_peers--;
+ if (!esw->num_peers && !peer_esw->num_peers)
+ mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
+ xa_erase(&peer_esw->paired, esw_i);
+ xa_erase(&esw->paired, peer_esw_i);
+ mlx5_esw_offloads_unpair(peer_esw, esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
break;
}
return 0;
+err_peer_xa:
+ xa_erase(&esw->paired, peer_esw_i);
+err_xa:
+ mlx5_esw_offloads_unpair(peer_esw, esw);
err_pair:
- mlx5_esw_offloads_unpair(esw);
+ mlx5_esw_offloads_unpair(esw, peer_esw);
err_peer:
mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
err_out:
@@ -2789,24 +2904,29 @@ err_out:
void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw)
{
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
+ int i;
- INIT_LIST_HEAD(&esw->offloads.peer_flows);
+ for (i = 0; i < MLX5_MAX_PORTS; i++)
+ INIT_LIST_HEAD(&esw->offloads.peer_flows[i]);
mutex_init(&esw->offloads.peer_mutex);
if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
return;
- if (!mlx5_is_lag_supported(esw->dev))
+ if (!mlx5_lag_is_supported(esw->dev))
return;
+ xa_init(&esw->paired);
mlx5_devcom_register_component(devcom,
MLX5_DEVCOM_ESW_OFFLOADS,
mlx5_esw_offloads_devcom_event,
esw);
+ esw->num_peers = 0;
mlx5_devcom_send_event(devcom,
MLX5_DEVCOM_ESW_OFFLOADS,
- ESW_OFFLOADS_DEVCOM_PAIR, esw);
+ ESW_OFFLOADS_DEVCOM_PAIR,
+ ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
}
void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
@@ -2816,13 +2936,15 @@ void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
return;
- if (!mlx5_is_lag_supported(esw->dev))
+ if (!mlx5_lag_is_supported(esw->dev))
return;
mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS,
+ ESW_OFFLOADS_DEVCOM_UNPAIR,
ESW_OFFLOADS_DEVCOM_UNPAIR, esw);
mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+ xa_destroy(&esw->paired);
}
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
@@ -2834,9 +2956,6 @@ bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
MLX5_FDB_TO_VPORT_REG_C_0))
return false;
- if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
- return false;
-
return true;
}
@@ -2973,26 +3092,47 @@ esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
esw_acl_ingress_ofld_cleanup(esw, vport);
}
-static int esw_create_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
+static int esw_create_offloads_acl_tables(struct mlx5_eswitch *esw)
{
- struct mlx5_vport *vport;
+ struct mlx5_vport *uplink, *manager;
+ int ret;
- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
- if (IS_ERR(vport))
- return PTR_ERR(vport);
+ uplink = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
+ if (IS_ERR(uplink))
+ return PTR_ERR(uplink);
+
+ ret = esw_vport_create_offloads_acl_tables(esw, uplink);
+ if (ret)
+ return ret;
- return esw_vport_create_offloads_acl_tables(esw, vport);
+ manager = mlx5_eswitch_get_vport(esw, esw->manager_vport);
+ if (IS_ERR(manager)) {
+ ret = PTR_ERR(manager);
+ goto err_manager;
+ }
+
+ ret = esw_vport_create_offloads_acl_tables(esw, manager);
+ if (ret)
+ goto err_manager;
+
+ return 0;
+
+err_manager:
+ esw_vport_destroy_offloads_acl_tables(esw, uplink);
+ return ret;
}
-static void esw_destroy_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
+static void esw_destroy_offloads_acl_tables(struct mlx5_eswitch *esw)
{
struct mlx5_vport *vport;
- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
- if (IS_ERR(vport))
- return;
+ vport = mlx5_eswitch_get_vport(esw, esw->manager_vport);
+ if (!IS_ERR(vport))
+ esw_vport_destroy_offloads_acl_tables(esw, vport);
- esw_vport_destroy_offloads_acl_tables(esw, vport);
+ vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_UPLINK);
+ if (!IS_ERR(vport))
+ esw_vport_destroy_offloads_acl_tables(esw, vport);
}
int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
@@ -3037,7 +3177,7 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
}
esw->fdb_table.offloads.indir = indir;
- err = esw_create_uplink_offloads_acl_tables(esw);
+ err = esw_create_offloads_acl_tables(esw);
if (err)
goto create_acl_err;
@@ -3078,7 +3218,7 @@ create_fdb_err:
create_restore_err:
esw_destroy_offloads_table(esw);
create_offloads_err:
- esw_destroy_uplink_offloads_acl_tables(esw);
+ esw_destroy_offloads_acl_tables(esw);
create_acl_err:
mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
create_indir_err:
@@ -3094,7 +3234,7 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
esw_destroy_offloads_fdb_tables(esw);
esw_destroy_restore_table(esw);
esw_destroy_offloads_table(esw);
- esw_destroy_uplink_offloads_acl_tables(esw);
+ esw_destroy_offloads_acl_tables(esw);
mlx5_esw_indir_table_destroy(esw->fdb_table.offloads.indir);
mutex_destroy(&esw->fdb_table.offloads.vports.lock);
}
@@ -3247,9 +3387,12 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
/* Representor will control the vport link state */
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
+ if (mlx5_core_ec_sriov_enabled(esw->dev))
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs)
+ vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN;
/* Uplink vport rep must load first. */
- err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK);
+ err = mlx5_esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK);
if (err)
goto err_uplink;
@@ -3260,7 +3403,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
return 0;
err_vports:
- esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
+ mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
err_uplink:
esw_offloads_steering_cleanup(esw);
err_steering_init:
@@ -3285,7 +3428,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
/* If changing from switchdev to legacy mode without sriov enabled,
* no need to create legacy fdb.
*/
- if (!mlx5_sriov_is_enabled(esw->dev))
+ if (!mlx5_core_is_pf(esw->dev) || !mlx5_sriov_is_enabled(esw->dev))
return 0;
err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS);
@@ -3298,7 +3441,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
void esw_offloads_disable(struct mlx5_eswitch *esw)
{
mlx5_eswitch_disable_pf_vf_vports(esw);
- esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
+ mlx5_esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
esw_set_passing_vport_metadata(esw, false);
esw_offloads_steering_cleanup(esw);
mapping_destroy(esw->offloads.reg_c0_obj_pool);
@@ -3484,8 +3627,27 @@ static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
goto revert_inline_mode;
}
}
+ if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode);
+ if (err) {
+ err_vport_num = vport->vport;
+ NL_SET_ERR_MSG_MOD(extack,
+ "Failed to set min inline on vport");
+ goto revert_ec_vf_inline_mode;
+ }
+ }
+ }
return 0;
+revert_ec_vf_inline_mode:
+ mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
+ if (vport->vport == err_vport_num)
+ break;
+ mlx5_modify_nic_vport_min_inline(dev,
+ vport->vport,
+ esw->offloads.inline_mode);
+ }
revert_inline_mode:
mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
if (vport->vport == err_vport_num)
@@ -3835,9 +3997,6 @@ static int mlx5_esw_query_vport_vhca_id(struct mlx5_eswitch *esw, u16 vport_num,
int err;
*vhca_id = 0;
- if (mlx5_esw_is_manager_vport(esw, vport_num) ||
- !MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
- return -EPERM;
query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
if (!query_ctx)
@@ -3926,9 +4085,9 @@ is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num)
mlx5_esw_is_sf_vport(esw, vport_num);
}
-int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
- u8 *hw_addr, int *hw_addr_len,
- struct netlink_ext_ack *extack)
+int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port,
+ u8 *hw_addr, int *hw_addr_len,
+ struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
@@ -3955,9 +4114,9 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
return 0;
}
-int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
- const u8 *hw_addr, int hw_addr_len,
- struct netlink_ext_ack *extack)
+int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port,
+ const u8 *hw_addr, int hw_addr_len,
+ struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw;
u16 vport_num;
@@ -4073,7 +4232,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
}
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
- MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
+ MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, enable);
err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
index 718cf09c28ce..3ec892d51f57 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
@@ -5,7 +5,7 @@
#include "mlx5_core.h"
#include "lib/eq.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
struct mlx5_event_nb {
struct mlx5_nb nb;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index ec83e6483d1a..244cfd470903 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -139,7 +139,8 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace
}
static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
return 0;
}
@@ -243,16 +244,30 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
ft->type == FS_FT_FDB &&
mlx5_lag_is_shared_fdb(dev) &&
mlx5_lag_is_master(dev)) {
- err = mlx5_cmd_set_slave_root_fdb(dev,
- mlx5_lag_get_peer_mdev(dev),
- !disconnect, (!disconnect) ?
- ft->id : 0);
- if (err && !disconnect) {
- MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
- MLX5_SET(set_flow_table_root_in, in, table_id,
- ns->root_ft->id);
- mlx5_cmd_exec_in(dev, set_flow_table_root, in);
+ struct mlx5_core_dev *peer_dev;
+ int i, j;
+
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
+ err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect,
+ (!disconnect) ? ft->id : 0);
+ if (err && !disconnect) {
+ mlx5_lag_for_each_peer_mdev(dev, peer_dev, j) {
+ if (j < i)
+ mlx5_cmd_set_slave_root_fdb(dev, peer_dev, 1,
+ ns->root_ft->id);
+ else
+ break;
+ }
+
+ MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
+ MLX5_SET(set_flow_table_root_in, in, table_id,
+ ns->root_ft->id);
+ mlx5_cmd_exec_in(dev, set_flow_table_root, in);
+ }
+ if (err)
+ break;
}
+
}
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
index 8ef4254b9ea1..7790ae5531e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
@@ -93,7 +93,8 @@ struct mlx5_flow_cmds {
struct mlx5_modify_hdr *modify_hdr);
int (*set_peer)(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns);
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id);
int (*create_ns)(struct mlx5_flow_root_namespace *ns);
int (*destroy_ns)(struct mlx5_flow_root_namespace *ns);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 19da02c41616..6b069fa411c5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -889,7 +889,7 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root,
struct fs_node *iter = list_entry(start, struct fs_node, list);
struct mlx5_flow_table *ft = NULL;
- if (!root || root->type == FS_TYPE_PRIO_CHAINS)
+ if (!root)
return NULL;
list_for_each_advance_continue(iter, &root->children, reverse) {
@@ -905,20 +905,42 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root,
return ft;
}
-/* If reverse is false then return the first flow table in next priority of
- * prio in the tree, else return the last flow table in the previous priority
- * of prio in the tree.
+static struct fs_node *find_prio_chains_parent(struct fs_node *parent,
+ struct fs_node **child)
+{
+ struct fs_node *node = NULL;
+
+ while (parent && parent->type != FS_TYPE_PRIO_CHAINS) {
+ node = parent;
+ parent = parent->parent;
+ }
+
+ if (child)
+ *child = node;
+
+ return parent;
+}
+
+/* If reverse is false then return the first flow table next to the passed node
+ * in the tree, else return the last flow table before the node in the tree.
+ * If skip is true, skip the flow tables in the same prio_chains prio.
*/
-static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
+static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse,
+ bool skip)
{
+ struct fs_node *prio_chains_parent = NULL;
struct mlx5_flow_table *ft = NULL;
struct fs_node *curr_node;
struct fs_node *parent;
- parent = prio->node.parent;
- curr_node = &prio->node;
+ if (skip)
+ prio_chains_parent = find_prio_chains_parent(node, NULL);
+ parent = node->parent;
+ curr_node = node;
while (!ft && parent) {
- ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
+ if (parent != prio_chains_parent)
+ ft = find_closest_ft_recursive(parent, &curr_node->list,
+ reverse);
curr_node = parent;
parent = curr_node->parent;
}
@@ -926,15 +948,15 @@ static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool revers
}
/* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node)
{
- return find_closest_ft(prio, false);
+ return find_closest_ft(node, false, true);
}
/* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node)
{
- return find_closest_ft(prio, true);
+ return find_closest_ft(node, true, true);
}
static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
@@ -946,7 +968,7 @@ static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent);
- return find_next_chained_ft(prio);
+ return find_next_chained_ft(&prio->node);
}
static int connect_fts_in_prio(struct mlx5_core_dev *dev,
@@ -970,21 +992,55 @@ static int connect_fts_in_prio(struct mlx5_core_dev *dev,
return 0;
}
+static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node,
+ struct fs_node *parent,
+ struct fs_node **child,
+ bool reverse)
+{
+ struct mlx5_flow_table *ft;
+
+ ft = find_closest_ft(node, reverse, false);
+
+ if (ft && parent == find_prio_chains_parent(&ft->node, child))
+ return ft;
+
+ return NULL;
+}
+
/* Connect flow tables from previous priority of prio to ft */
static int connect_prev_fts(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft,
struct fs_prio *prio)
{
+ struct fs_node *prio_parent, *parent = NULL, *child, *node;
struct mlx5_flow_table *prev_ft;
+ int err = 0;
+
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+ /* return directly if not under the first sub ns of prio_chains prio */
+ if (prio_parent && !list_is_first(&child->list, &prio_parent->children))
+ return 0;
- prev_ft = find_prev_chained_ft(prio);
- if (prev_ft) {
+ prev_ft = find_prev_chained_ft(&prio->node);
+ while (prev_ft) {
struct fs_prio *prev_prio;
fs_get_obj(prev_prio, prev_ft->node.parent);
- return connect_fts_in_prio(dev, prev_prio, ft);
+ err = connect_fts_in_prio(dev, prev_prio, ft);
+ if (err)
+ break;
+
+ if (!parent) {
+ parent = find_prio_chains_parent(&prev_prio->node, &child);
+ if (!parent)
+ break;
+ }
+
+ node = child;
+ prev_ft = find_closet_ft_prio_chains(node, parent, &child, true);
}
- return 0;
+ return err;
}
static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
@@ -1123,7 +1179,7 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table
if (err)
return err;
- next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
+ next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node);
err = connect_fwd_rules(dev, ft, next_ft);
if (err)
return err;
@@ -1198,7 +1254,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
next_ft = unmanaged ? ft_attr->next_ft :
- find_next_chained_ft(fs_prio);
+ find_next_chained_ft(&fs_prio->node);
ft->def_miss_action = ns->def_miss_action;
ft->ns = ns;
err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft);
@@ -2195,13 +2251,20 @@ EXPORT_SYMBOL(mlx5_del_flow_rules);
/* Assuming prio->node.children(flow tables) is sorted by level */
static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
{
+ struct fs_node *prio_parent, *child;
struct fs_prio *prio;
fs_get_obj(prio, ft->node.parent);
if (!list_is_last(&ft->node.list, &prio->node.children))
return list_next_entry(ft, node.list);
- return find_next_chained_ft(prio);
+
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+ if (prio_parent && list_is_first(&child->list, &prio_parent->children))
+ return find_closest_ft(&prio->node, false, false);
+
+ return find_next_chained_ft(&prio->node);
}
static int update_root_ft_destroy(struct mlx5_flow_table *ft)
@@ -3620,7 +3683,8 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev,
}
int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
if (peer_ns && ns->mode != peer_ns->mode) {
mlx5_core_err(ns->dev,
@@ -3628,7 +3692,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
return -EINVAL;
}
- return ns->cmds->set_peer(ns, peer_ns);
+ return ns->cmds->set_peer(ns, peer_ns, peer_vhca_id);
}
/* This function should be called only at init stage of the namespace.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
index b043190e50a8..4aed1768b85f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
@@ -302,7 +302,8 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void);
int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns);
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id);
int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
enum mlx5_flow_steering_mode mode);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
index 7bb7be01225a..fb2035a5ec99 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c
@@ -196,14 +196,11 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev)
return err;
}
- if (MLX5_CAP_GEN(dev, vport_group_manager) &&
- MLX5_ESWITCH_MANAGER(dev)) {
+ if (MLX5_ESWITCH_MANAGER(dev)) {
err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE);
if (err)
return err;
- }
- if (MLX5_ESWITCH_MANAGER(dev)) {
err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
index 50022e7565f1..99dcbd006357 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -21,6 +21,7 @@ struct mlx5_fw_reset {
struct workqueue_struct *wq;
struct work_struct fw_live_patch_work;
struct work_struct reset_request_work;
+ struct work_struct reset_unload_work;
struct work_struct reset_reload_work;
struct work_struct reset_now_work;
struct work_struct reset_abort_work;
@@ -30,6 +31,26 @@ struct mlx5_fw_reset {
int ret;
};
+enum {
+ MLX5_FW_RST_STATE_IDLE = 0,
+ MLX5_FW_RST_STATE_TOGGLE_REQ = 4,
+};
+
+enum {
+ MLX5_RST_STATE_BIT_NUM = 12,
+ MLX5_RST_ACK_BIT_NUM = 22,
+};
+
+static u8 mlx5_get_fw_rst_state(struct mlx5_core_dev *dev)
+{
+ return (ioread32be(&dev->iseg->initializing) >> MLX5_RST_STATE_BIT_NUM) & 0xF;
+}
+
+static void mlx5_set_fw_rst_ack(struct mlx5_core_dev *dev)
+{
+ iowrite32be(BIT(MLX5_RST_ACK_BIT_NUM), &dev->iseg->initializing);
+}
+
static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
@@ -155,7 +176,7 @@ int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev)
return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false);
}
-static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
+static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded)
{
struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
@@ -163,7 +184,8 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev)
if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
complete(&fw_reset->done);
} else {
- mlx5_unload_one(dev, false);
+ if (!unloaded)
+ mlx5_unload_one(dev, false);
if (mlx5_health_wait_pci_up(dev))
mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
else
@@ -204,7 +226,7 @@ static void mlx5_sync_reset_reload_work(struct work_struct *work)
mlx5_sync_reset_clear_reset_requested(dev, false);
mlx5_enter_error_state(dev, true);
- mlx5_fw_reset_complete_reload(dev);
+ mlx5_fw_reset_complete_reload(dev, false);
}
#define MLX5_RESET_POLL_INTERVAL (HZ / 10)
@@ -276,6 +298,44 @@ static void mlx5_fw_live_patch_event(struct work_struct *work)
mlx5_core_err(dev, "Failed to reload FW tracer\n");
}
+static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id)
+{
+ struct pci_bus *bridge_bus = dev->pdev->bus;
+ struct pci_dev *sdev;
+ u16 sdev_id;
+ int err;
+
+ /* Check that all functions under the pci bridge are PFs of
+ * this device otherwise fail this function.
+ */
+ list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
+ err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id);
+ if (err)
+ return err;
+ if (sdev_id != dev_id) {
+ mlx5_core_warn(dev, "unrecognized dev_id (0x%x)\n", sdev_id);
+ return -EPERM;
+ }
+ }
+ return 0;
+}
+
+static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev)
+{
+ u16 dev_id;
+ int err;
+
+ if (!MLX5_CAP_GEN(dev, fast_teardown)) {
+ mlx5_core_warn(dev, "fast teardown is not supported by firmware\n");
+ return false;
+ }
+
+ err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
+ if (err)
+ return false;
+ return (!mlx5_check_dev_ids(dev, dev_id));
+}
+
static void mlx5_sync_reset_request_event(struct work_struct *work)
{
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
@@ -283,7 +343,8 @@ static void mlx5_sync_reset_request_event(struct work_struct *work)
struct mlx5_core_dev *dev = fw_reset->dev;
int err;
- if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags)) {
+ if (test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, &fw_reset->reset_flags) ||
+ !mlx5_is_reset_now_capable(dev)) {
err = mlx5_fw_reset_set_reset_sync_nack(dev);
mlx5_core_warn(dev, "PCI Sync FW Update Reset Nack %s",
err ? "Failed" : "Sent");
@@ -303,26 +364,17 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
{
struct pci_bus *bridge_bus = dev->pdev->bus;
struct pci_dev *bridge = bridge_bus->self;
- u16 reg16, dev_id, sdev_id;
unsigned long timeout;
struct pci_dev *sdev;
+ u16 reg16, dev_id;
int cap, err;
- u32 reg32;
- /* Check that all functions under the pci bridge are PFs of
- * this device otherwise fail this function.
- */
err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
if (err)
return err;
- list_for_each_entry(sdev, &bridge_bus->devices, bus_list) {
- err = pci_read_config_word(sdev, PCI_DEVICE_ID, &sdev_id);
- if (err)
- return err;
- if (sdev_id != dev_id)
- return -EPERM;
- }
-
+ err = mlx5_check_dev_ids(dev, dev_id);
+ if (err)
+ return err;
cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
if (!cap)
return -EOPNOTSUPP;
@@ -332,25 +384,17 @@ static int mlx5_pci_link_toggle(struct mlx5_core_dev *dev)
pci_cfg_access_lock(sdev);
}
/* PCI link toggle */
- err = pci_read_config_word(bridge, cap + PCI_EXP_LNKCTL, &reg16);
- if (err)
- return err;
- reg16 |= PCI_EXP_LNKCTL_LD;
- err = pci_write_config_word(bridge, cap + PCI_EXP_LNKCTL, reg16);
+ err = pcie_capability_set_word(bridge, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_LD);
if (err)
return err;
msleep(500);
- reg16 &= ~PCI_EXP_LNKCTL_LD;
- err = pci_write_config_word(bridge, cap + PCI_EXP_LNKCTL, reg16);
+ err = pcie_capability_clear_word(bridge, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_LD);
if (err)
return err;
/* Check link */
- err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, &reg32);
- if (err)
- return err;
- if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) {
- mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32);
+ if (!bridge->link_active_reporting) {
+ mlx5_core_warn(dev, "No PCI link reporting capability\n");
msleep(1000);
goto restore;
}
@@ -427,7 +471,70 @@ static void mlx5_sync_reset_now_event(struct work_struct *work)
mlx5_enter_error_state(dev, true);
done:
fw_reset->ret = err;
- mlx5_fw_reset_complete_reload(dev);
+ mlx5_fw_reset_complete_reload(dev, false);
+}
+
+static void mlx5_sync_reset_unload_event(struct work_struct *work)
+{
+ struct mlx5_fw_reset *fw_reset;
+ struct mlx5_core_dev *dev;
+ unsigned long timeout;
+ bool reset_action;
+ u8 rst_state;
+ int err;
+
+ fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work);
+ dev = fw_reset->dev;
+
+ if (mlx5_sync_reset_clear_reset_requested(dev, false))
+ return;
+
+ mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n");
+
+ err = mlx5_cmd_fast_teardown_hca(dev);
+ if (err)
+ mlx5_core_warn(dev, "Fast teardown failed, unloading, err %d\n", err);
+ else
+ mlx5_enter_error_state(dev, true);
+
+ if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags))
+ mlx5_unload_one_devl_locked(dev, false);
+ else
+ mlx5_unload_one(dev, false);
+
+ mlx5_set_fw_rst_ack(dev);
+ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n");
+
+ reset_action = false;
+ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD));
+ do {
+ rst_state = mlx5_get_fw_rst_state(dev);
+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ ||
+ rst_state == MLX5_FW_RST_STATE_IDLE) {
+ reset_action = true;
+ break;
+ }
+ msleep(20);
+ } while (!time_after(jiffies, timeout));
+
+ if (!reset_action) {
+ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n",
+ rst_state);
+ fw_reset->ret = -ETIMEDOUT;
+ goto done;
+ }
+
+ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state);
+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) {
+ err = mlx5_pci_link_toggle(dev);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, err %d\n", err);
+ fw_reset->ret = err;
+ }
+ }
+
+done:
+ mlx5_fw_reset_complete_reload(dev, true);
}
static void mlx5_sync_reset_abort_event(struct work_struct *work)
@@ -452,6 +559,9 @@ static void mlx5_sync_reset_events_handle(struct mlx5_fw_reset *fw_reset, struct
case MLX5_SYNC_RST_STATE_RESET_REQUEST:
queue_work(fw_reset->wq, &fw_reset->reset_request_work);
break;
+ case MLX5_SYNC_RST_STATE_RESET_UNLOAD:
+ queue_work(fw_reset->wq, &fw_reset->reset_unload_work);
+ break;
case MLX5_SYNC_RST_STATE_RESET_NOW:
queue_work(fw_reset->wq, &fw_reset->reset_now_work);
break;
@@ -486,10 +596,13 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti
int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev)
{
unsigned long pci_sync_update_timeout = mlx5_tout_ms(dev, PCI_SYNC_UPDATE);
- unsigned long timeout = msecs_to_jiffies(pci_sync_update_timeout);
struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
+ unsigned long timeout;
int err;
+ if (MLX5_CAP_GEN(dev, pci_sync_for_fw_update_with_driver_unload))
+ pci_sync_update_timeout += mlx5_tout_ms(dev, RESET_UNLOAD);
+ timeout = msecs_to_jiffies(pci_sync_update_timeout);
if (!wait_for_completion_timeout(&fw_reset->done, timeout)) {
mlx5_core_warn(dev, "FW sync reset timeout after %lu seconds\n",
pci_sync_update_timeout / 1000);
@@ -526,6 +639,7 @@ void mlx5_drain_fw_reset(struct mlx5_core_dev *dev)
set_bit(MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, &fw_reset->reset_flags);
cancel_work_sync(&fw_reset->fw_live_patch_work);
cancel_work_sync(&fw_reset->reset_request_work);
+ cancel_work_sync(&fw_reset->reset_unload_work);
cancel_work_sync(&fw_reset->reset_reload_work);
cancel_work_sync(&fw_reset->reset_now_work);
cancel_work_sync(&fw_reset->reset_abort_work);
@@ -564,6 +678,7 @@ int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event);
INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event);
+ INIT_WORK(&fw_reset->reset_unload_work, mlx5_sync_reset_unload_event);
INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work);
INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c
index 871c32dda66e..187cb2c464f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -39,6 +39,7 @@
#include "mlx5_core.h"
#include "lib/eq.h"
#include "lib/mlx5.h"
+#include "lib/events.h"
#include "lib/pci_vsc.h"
#include "lib/tout.h"
#include "diag/fw_tracer.h"
@@ -719,7 +720,7 @@ static const struct devlink_health_reporter_ops mlx5_fw_fatal_reporter_ops = {
#define MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD 30000
#define MLX5_FW_REPORTER_DEFAULT_GRACEFUL_PERIOD MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD
-static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
+void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
struct devlink *devlink = priv_to_devlink(dev);
@@ -735,17 +736,17 @@ static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev)
}
health->fw_reporter =
- devlink_health_reporter_create(devlink, &mlx5_fw_reporter_ops,
- 0, dev);
+ devl_health_reporter_create(devlink, &mlx5_fw_reporter_ops,
+ 0, dev);
if (IS_ERR(health->fw_reporter))
mlx5_core_warn(dev, "Failed to create fw reporter, err = %ld\n",
PTR_ERR(health->fw_reporter));
health->fw_fatal_reporter =
- devlink_health_reporter_create(devlink,
- &mlx5_fw_fatal_reporter_ops,
- grace_period,
- dev);
+ devl_health_reporter_create(devlink,
+ &mlx5_fw_fatal_reporter_ops,
+ grace_period,
+ dev);
if (IS_ERR(health->fw_fatal_reporter))
mlx5_core_warn(dev, "Failed to create fw fatal reporter, err = %ld\n",
PTR_ERR(health->fw_fatal_reporter));
@@ -777,7 +778,8 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev)
{
struct mlx5_core_health *health = &dev->priv.health;
- queue_work(health->wq, &health->fatal_report_work);
+ if (!mlx5_dev_is_lightweight(dev))
+ queue_work(health->wq, &health->fatal_report_work);
}
#define MLX5_MSEC_PER_HOUR (MSEC_PER_SEC * 60 * 60)
@@ -905,10 +907,15 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev)
int mlx5_health_init(struct mlx5_core_dev *dev)
{
+ struct devlink *devlink = priv_to_devlink(dev);
struct mlx5_core_health *health;
char *name;
- mlx5_fw_reporters_create(dev);
+ if (!mlx5_dev_is_lightweight(dev)) {
+ devl_lock(devlink);
+ mlx5_fw_reporters_create(dev);
+ devl_unlock(devlink);
+ }
mlx5_reporter_vnic_create(dev);
health = &dev->priv.health;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 5d331b940f4d..f0a074b2fcdf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
return;
if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
- tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH)
+ tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
+ if (ldev->ports > 2)
+ ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
+ }
}
static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode,
@@ -550,6 +553,29 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
}
}
+static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
+{
+ struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
+ int err;
+ int i;
+
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch;
+
+ err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw,
+ slave_esw, ldev->ports);
+ if (err)
+ goto err;
+ }
+ return 0;
+err:
+ for (; i > MLX5_LAG_P1; i--)
+ mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
+ ldev->pf[i].dev->priv.eswitch);
+ return err;
+}
+
static int mlx5_create_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker,
enum mlx5_lag_mode mode,
@@ -557,7 +583,6 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
{
bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
int err;
@@ -575,8 +600,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
}
if (shared_fdb) {
- err = mlx5_eswitch_offloads_config_single_fdb(dev0->priv.eswitch,
- dev1->priv.eswitch);
+ err = mlx5_lag_create_single_fdb(ldev);
if (err)
mlx5_core_err(dev0, "Can't enable single FDB mode\n");
else
@@ -647,19 +671,21 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
int mlx5_deactivate_lag(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
+ struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
bool roce_lag = __mlx5_lag_is_roce(ldev);
unsigned long flags = ldev->mode_flags;
int err;
+ int i;
ldev->mode = MLX5_LAG_MODE_NONE;
ldev->mode_flags = 0;
mlx5_lag_mp_reset(ldev);
if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
- mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch,
- dev1->priv.eswitch);
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++)
+ mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
+ ldev->pf[i].dev->priv.eswitch);
clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
}
@@ -685,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
return 0;
}
-#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2
+#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4
bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
{
#ifdef CONFIG_MLX5_ESWITCH
@@ -711,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
return false;
- if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
+ if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
return false;
#else
for (i = 0; i < ldev->ports; i++)
@@ -759,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
{
bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
bool roce_lag;
int err;
int i;
@@ -784,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
if (shared_fdb || roce_lag)
mlx5_lag_add_devices(ldev);
- if (shared_fdb) {
- if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
- mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
- mlx5_eswitch_reload_reps(dev1->priv.eswitch);
- }
+ if (shared_fdb)
+ for (i = 0; i < ldev->ports; i++)
+ if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
+ mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
}
-bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
+static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
-
- if (is_mdev_switchdev_mode(dev0) &&
- is_mdev_switchdev_mode(dev1) &&
- mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) &&
- mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) &&
- mlx5_devcom_is_paired(dev0->priv.devcom,
- MLX5_DEVCOM_ESW_OFFLOADS) &&
- MLX5_CAP_GEN(dev1, lag_native_fdb_selection) &&
- MLX5_CAP_ESW(dev1, root_ft_on_other_esw) &&
- MLX5_CAP_ESW(dev0, esw_shared_ingress_acl))
+ struct mlx5_core_dev *dev;
+ int i;
+
+ for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ dev = ldev->pf[i].dev;
+ if (is_mdev_switchdev_mode(dev) &&
+ mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
+ MLX5_CAP_GEN(dev, lag_native_fdb_selection) &&
+ MLX5_CAP_ESW(dev, root_ft_on_other_esw) &&
+ mlx5_eswitch_get_npeers(dev->priv.eswitch) ==
+ MLX5_CAP_GEN(dev, num_lag_ports) - 1)
+ continue;
+ return false;
+ }
+
+ dev = ldev->pf[MLX5_LAG_P1].dev;
+ if (is_mdev_switchdev_mode(dev) &&
+ mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
+ mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) &&
+ MLX5_CAP_ESW(dev, esw_shared_ingress_acl) &&
+ mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1)
return true;
return false;
@@ -842,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
static void mlx5_do_bond(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
struct lag_tracker tracker = { };
bool do_bond, roce_lag;
int err;
@@ -883,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
for (i = 1; i < ldev->ports; i++)
mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
} else if (shared_fdb) {
+ int i;
+
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
- err = mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- if (!err)
- err = mlx5_eswitch_reload_reps(dev1->priv.eswitch);
+ for (i = 0; i < ldev->ports; i++) {
+ err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
+ if (err)
+ break;
+ }
if (err) {
dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
mlx5_deactivate_lag(ldev);
mlx5_lag_add_devices(ldev);
- mlx5_eswitch_reload_reps(dev0->priv.eswitch);
- mlx5_eswitch_reload_reps(dev1->priv.eswitch);
+ for (i = 0; i < ldev->ports; i++)
+ mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_core_err(dev0, "Failed to enable lag\n");
return;
}
@@ -1233,14 +1268,21 @@ recheck:
mlx5_ldev_put(ldev);
}
+bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
+{
+ if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
+ !MLX5_CAP_GEN(dev, lag_master) ||
+ MLX5_CAP_GEN(dev, num_lag_ports) < 2 ||
+ MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS)
+ return false;
+ return true;
+}
+
void mlx5_lag_add_mdev(struct mlx5_core_dev *dev)
{
int err;
- if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
- !MLX5_CAP_GEN(dev, lag_master) ||
- (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS ||
- MLX5_CAP_GEN(dev, num_lag_ports) <= 1))
+ if (!mlx5_lag_is_supported(dev))
return;
recheck:
@@ -1496,26 +1538,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev)
}
EXPORT_SYMBOL(mlx5_lag_get_num_ports);
-struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
+struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i)
{
struct mlx5_core_dev *peer_dev = NULL;
struct mlx5_lag *ldev;
unsigned long flags;
+ int idx;
spin_lock_irqsave(&lag_lock, flags);
ldev = mlx5_lag_dev(dev);
if (!ldev)
goto unlock;
- peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ?
- ldev->pf[MLX5_LAG_P2].dev :
- ldev->pf[MLX5_LAG_P1].dev;
+ if (*i == ldev->ports)
+ goto unlock;
+ for (idx = *i; idx < ldev->ports; idx++)
+ if (ldev->pf[idx].dev != dev)
+ break;
+
+ if (idx == ldev->ports) {
+ *i = idx;
+ goto unlock;
+ }
+ *i = idx + 1;
+
+ peer_dev = ldev->pf[idx].dev;
unlock:
spin_unlock_irqrestore(&lag_lock, flags);
return peer_dev;
}
-EXPORT_SYMBOL(mlx5_lag_get_peer_mdev);
+EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev);
int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
u64 *values,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index bc1f1dd3e283..a061b1873e27 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -74,15 +74,7 @@ struct mlx5_lag {
struct lag_mpesw lag_mpesw;
};
-static inline bool mlx5_is_lag_supported(struct mlx5_core_dev *dev)
-{
- if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
- !MLX5_CAP_GEN(dev, lag_master) ||
- MLX5_CAP_GEN(dev, num_lag_ports) < 2 ||
- MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS)
- return false;
- return true;
-}
+bool mlx5_lag_is_supported(struct mlx5_core_dev *dev);
static inline struct mlx5_lag *
mlx5_lag_dev(struct mlx5_core_dev *dev)
@@ -111,7 +103,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
bool shared_fdb);
int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
struct net_device *ndev);
-bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev);
char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags);
void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
index d85a8dfc153d..b1aa494c76ba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -7,13 +7,14 @@
#include "lag/mp.h"
#include "mlx5_core.h"
#include "eswitch.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
{
return ldev->mode == MLX5_LAG_MODE_MULTIPATH;
}
+#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2
static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
{
if (!mlx5_lag_is_ready(ldev))
@@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev))
return false;
+ if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS)
+ return false;
+
return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
ldev->pf[MLX5_LAG_P2].dev);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
index 0c0ef600f643..4bf15391525c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -6,7 +6,7 @@
#include "lag/lag.h"
#include "eswitch.h"
#include "esw/acl/ofld.h"
-#include "lib/mlx5.h"
+#include "lib/events.h"
static void mlx5_mpesw_metadata_cleanup(struct mlx5_lag *ldev)
{
@@ -65,6 +65,7 @@ err_metadata:
return err;
}
+#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2
static int enable_mpesw(struct mlx5_lag *ldev)
{
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
@@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev)
if (ldev->mode != MLX5_LAG_MODE_NONE)
return -EINVAL;
+ if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS)
+ return -EOPNOTSUPP;
+
if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS ||
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) ||
!MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) ||
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
index d3a3fe4ce670..7d9bbb494d95 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
@@ -574,7 +574,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
for (i = 0; i < ldev->ports; i++) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
- if (ldev->v2p_map[i] == ports[i])
+ if (ldev->v2p_map[idx] == ports[idx])
continue;
dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index 932fbc843c69..aa29f09e8356 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -32,6 +32,7 @@
#include <linux/clocksource.h>
#include <linux/highmem.h>
+#include <linux/log2.h>
#include <linux/ptp_clock_kernel.h>
#include <rdma/mlx5-abi.h>
#include "lib/eq.h"
@@ -39,10 +40,6 @@
#include "clock.h"
enum {
- MLX5_CYCLES_SHIFT = 31
-};
-
-enum {
MLX5_PIN_MODE_IN = 0x0,
MLX5_PIN_MODE_OUT = 0x1,
};
@@ -93,17 +90,48 @@ static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev)
return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify);
}
-static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta)
+static u32 mlx5_ptp_shift_constant(u32 dev_freq_khz)
{
- s64 min = MLX5_MTUTC_OPERATION_ADJUST_TIME_MIN;
- s64 max = MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX;
+ /* Optimal shift constant leads to corrections above just 1 scaled ppm.
+ *
+ * Two sets of equations are needed to derive the optimal shift
+ * constant for the cyclecounter.
+ *
+ * dev_freq_khz * 1000 / 2^shift_constant = 1 scaled_ppm
+ * ppb = scaled_ppm * 1000 / 2^16
+ *
+ * Using the two equations together
+ *
+ * dev_freq_khz * 1000 / 1 scaled_ppm = 2^shift_constant
+ * dev_freq_khz * 2^16 / 1 ppb = 2^shift_constant
+ * dev_freq_khz = 2^(shift_constant - 16)
+ *
+ * then yields
+ *
+ * shift_constant = ilog2(dev_freq_khz) + 16
+ */
- if (MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range)) {
- min = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MIN;
- max = MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX;
- }
+ return min(ilog2(dev_freq_khz) + 16,
+ ilog2((U32_MAX / NSEC_PER_MSEC) * dev_freq_khz));
+}
+
+static s32 mlx5_ptp_getmaxphase(struct ptp_clock_info *ptp)
+{
+ struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
+ struct mlx5_core_dev *mdev;
+
+ mdev = container_of(clock, struct mlx5_core_dev, clock);
+
+ return MLX5_CAP_MCAM_FEATURE(mdev, mtutc_time_adjustment_extended_range) ?
+ MLX5_MTUTC_OPERATION_ADJUST_TIME_EXTENDED_MAX :
+ MLX5_MTUTC_OPERATION_ADJUST_TIME_MAX;
+}
+
+static bool mlx5_is_mtutc_time_adj_cap(struct mlx5_core_dev *mdev, s64 delta)
+{
+ s64 max = mlx5_ptp_getmaxphase(&mdev->clock.ptp_info);
- if (delta < min || delta > max)
+ if (delta < -max || delta > max)
return false;
return true;
@@ -221,10 +249,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
clock = container_of(timer, struct mlx5_clock, timer);
mdev = container_of(clock, struct mlx5_core_dev, clock);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ goto out;
+
write_seqlock_irqsave(&clock->lock, flags);
timecounter_read(&timer->tc);
mlx5_update_clock_info_page(mdev);
write_sequnlock_irqrestore(&clock->lock, flags);
+
+out:
schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
}
@@ -351,14 +384,6 @@ static int mlx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
static int mlx5_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta)
{
- struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info);
- struct mlx5_core_dev *mdev;
-
- mdev = container_of(clock, struct mlx5_core_dev, clock);
-
- if (!mlx5_is_mtutc_time_adj_cap(mdev, delta))
- return -ERANGE;
-
return mlx5_ptp_adjtime(ptp, delta);
}
@@ -734,6 +759,7 @@ static const struct ptp_clock_info mlx5_ptp_clock_info = {
.pps = 0,
.adjfine = mlx5_ptp_adjfine,
.adjphase = mlx5_ptp_adjphase,
+ .getmaxphase = mlx5_ptp_getmaxphase,
.adjtime = mlx5_ptp_adjtime,
.gettimex64 = mlx5_ptp_gettimex,
.settime64 = mlx5_ptp_settime,
@@ -905,7 +931,7 @@ static void mlx5_timecounter_init(struct mlx5_core_dev *mdev)
dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz);
timer->cycles.read = read_internal_timer;
- timer->cycles.shift = MLX5_CYCLES_SHIFT;
+ timer->cycles.shift = mlx5_ptp_shift_constant(dev_freq);
timer->cycles.mult = clocksource_khz2mult(dev_freq,
timer->cycles.shift);
timer->nominal_c_mult = timer->cycles.mult;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
index b7d779d08d83..78c94b22bdc0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
@@ -19,7 +19,7 @@ struct mlx5_devcom_component {
mlx5_devcom_event_handler_t handler;
struct rw_semaphore sem;
- bool paired;
+ bool ready;
};
struct mlx5_devcom_list {
@@ -75,13 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
if (!mlx5_core_is_pf(dev))
return NULL;
- if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
+ if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED)
return NULL;
mlx5_dev_list_lock();
sguid0 = mlx5_query_nic_system_image_guid(dev);
list_for_each_entry(iter, &devcom_list, list) {
- struct mlx5_core_dev *tmp_dev = NULL;
+ /* There is at least one device in iter */
+ struct mlx5_core_dev *tmp_dev;
idx = -1;
for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
@@ -193,7 +194,7 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id,
- int event,
+ int event, int rollback_event,
void *event_data)
{
struct mlx5_devcom_component *comp;
@@ -210,84 +211,134 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
if (i != devcom->idx && data) {
err = comp->handler(event, data, event_data);
- break;
+ if (err)
+ goto rollback;
}
}
up_write(&comp->sem);
+ return 0;
+
+rollback:
+ while (i--) {
+ void *data = rcu_dereference_protected(comp->device[i].data,
+ lockdep_is_held(&comp->sem));
+
+ if (i != devcom->idx && data)
+ comp->handler(rollback_event, data, event_data);
+ }
+
+ up_write(&comp->sem);
return err;
}
-void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id,
- bool paired)
+void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ bool ready)
{
struct mlx5_devcom_component *comp;
comp = &devcom->priv->components[id];
WARN_ON(!rwsem_is_locked(&comp->sem));
- WRITE_ONCE(comp->paired, paired);
+ WRITE_ONCE(comp->ready, ready);
}
-bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
{
if (IS_ERR_OR_NULL(devcom))
return false;
- return READ_ONCE(devcom->priv->components[id].paired);
+ return READ_ONCE(devcom->priv->components[id].ready);
}
-void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
{
struct mlx5_devcom_component *comp;
- int i;
if (IS_ERR_OR_NULL(devcom))
- return NULL;
+ return false;
comp = &devcom->priv->components[id];
down_read(&comp->sem);
- if (!READ_ONCE(comp->paired)) {
+ if (!READ_ONCE(comp->ready)) {
up_read(&comp->sem);
- return NULL;
+ return false;
}
- for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
- if (i != devcom->idx)
- break;
+ return true;
+}
+
+void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id)
+{
+ struct mlx5_devcom_component *comp = &devcom->priv->components[id];
- return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem));
+ up_read(&comp->sem);
}
-void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id)
+void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ int *i)
{
struct mlx5_devcom_component *comp;
- int i;
+ void *ret;
+ int idx;
- if (IS_ERR_OR_NULL(devcom))
- return NULL;
+ comp = &devcom->priv->components[id];
- for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
- if (i != devcom->idx)
- break;
+ if (*i == MLX5_DEVCOM_PORTS_SUPPORTED)
+ return NULL;
+ for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) {
+ if (idx != devcom->idx) {
+ ret = rcu_dereference_protected(comp->device[idx].data,
+ lockdep_is_held(&comp->sem));
+ if (ret)
+ break;
+ }
+ }
- comp = &devcom->priv->components[id];
- /* This can change concurrently, however 'data' pointer will remain
- * valid for the duration of RCU read section.
- */
- if (!READ_ONCE(comp->paired))
+ if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) {
+ *i = idx;
return NULL;
+ }
+ *i = idx + 1;
- return rcu_dereference(comp->device[i].data);
+ return ret;
}
-void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id)
+void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ int *i)
{
- struct mlx5_devcom_component *comp = &devcom->priv->components[id];
+ struct mlx5_devcom_component *comp;
+ void *ret;
+ int idx;
- up_read(&comp->sem);
+ comp = &devcom->priv->components[id];
+
+ if (*i == MLX5_DEVCOM_PORTS_SUPPORTED)
+ return NULL;
+ for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) {
+ if (idx != devcom->idx) {
+ /* This can change concurrently, however 'data' pointer will remain
+ * valid for the duration of RCU read section.
+ */
+ if (!READ_ONCE(comp->ready))
+ return NULL;
+ ret = rcu_dereference(comp->device[idx].data);
+ if (ret)
+ break;
+ }
+ }
+
+ if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) {
+ *i = idx;
+ return NULL;
+ }
+ *i = idx + 1;
+
+ return ret;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
index 9a496f4722da..d953a01b8eaa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
@@ -6,7 +6,7 @@
#include <linux/mlx5/driver.h>
-#define MLX5_DEVCOM_PORTS_SUPPORTED 2
+#define MLX5_DEVCOM_PORTS_SUPPORTED 4
enum mlx5_devcom_components {
MLX5_DEVCOM_ESW_OFFLOADS,
@@ -30,20 +30,33 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id,
- int event,
+ int event, int rollback_event,
void *event_data);
-void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id,
- bool paired);
-bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id);
+void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id,
+ bool ready);
+bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id);
-void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
- enum mlx5_devcom_components id);
-void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id);
-void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
+bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id);
+void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom,
enum mlx5_devcom_components id);
+void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id, int *i);
-#endif
+#define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \
+ for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \
+ data; \
+ data = mlx5_devcom_get_next_peer_data(devcom, id, &i))
+
+void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom,
+ enum mlx5_devcom_components id, int *i);
+#define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \
+ for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \
+ data; \
+ data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i))
+
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h
new file mode 100644
index 000000000000..a0f7faea317b
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/events.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef __LIB_EVENTS_H__
+#define __LIB_EVENTS_H__
+
+#include "mlx5_core.h"
+
+#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
+#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF
+
+enum port_module_event_status_type {
+ MLX5_MODULE_STATUS_PLUGGED = 0x1,
+ MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
+ MLX5_MODULE_STATUS_ERROR = 0x3,
+ MLX5_MODULE_STATUS_DISABLED = 0x4,
+ MLX5_MODULE_STATUS_NUM,
+};
+
+enum port_module_event_error_type {
+ MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0,
+ MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1,
+ MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2,
+ MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3,
+ MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4,
+ MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5,
+ MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6,
+ MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7,
+ MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc,
+ MLX5_MODULE_EVENT_ERROR_NUM,
+};
+
+struct mlx5_pme_stats {
+ u64 status_counters[MLX5_MODULE_STATUS_NUM];
+ u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
+};
+
+void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats);
+int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data);
+#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
index db9df9798ffa..a80ecb672f33 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
@@ -178,7 +178,7 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
if (!mlx5_chains_ignore_flow_level_supported(chains) ||
(chain == 0 && prio == 1 && level == 0)) {
ft_attr.level = chains->fs_base_level;
- ft_attr.prio = chains->fs_base_prio;
+ ft_attr.prio = chains->fs_base_prio + prio - 1;
ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ?
mlx5_get_fdb_sub_ns(chains->dev, chain) :
mlx5_get_flow_namespace(chains->dev, chains->ns);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
index ccf12f7db6f0..2b5826a785c4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
@@ -45,40 +45,6 @@ int mlx5_crdump_enable(struct mlx5_core_dev *dev);
void mlx5_crdump_disable(struct mlx5_core_dev *dev);
int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data);
-/* TODO move to lib/events.h */
-
-#define PORT_MODULE_EVENT_MODULE_STATUS_MASK 0xF
-#define PORT_MODULE_EVENT_ERROR_TYPE_MASK 0xF
-
-enum port_module_event_status_type {
- MLX5_MODULE_STATUS_PLUGGED = 0x1,
- MLX5_MODULE_STATUS_UNPLUGGED = 0x2,
- MLX5_MODULE_STATUS_ERROR = 0x3,
- MLX5_MODULE_STATUS_DISABLED = 0x4,
- MLX5_MODULE_STATUS_NUM,
-};
-
-enum port_module_event_error_type {
- MLX5_MODULE_EVENT_ERROR_POWER_BUDGET_EXCEEDED = 0x0,
- MLX5_MODULE_EVENT_ERROR_LONG_RANGE_FOR_NON_MLNX = 0x1,
- MLX5_MODULE_EVENT_ERROR_BUS_STUCK = 0x2,
- MLX5_MODULE_EVENT_ERROR_NO_EEPROM_RETRY_TIMEOUT = 0x3,
- MLX5_MODULE_EVENT_ERROR_ENFORCE_PART_NUMBER_LIST = 0x4,
- MLX5_MODULE_EVENT_ERROR_UNKNOWN_IDENTIFIER = 0x5,
- MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE = 0x6,
- MLX5_MODULE_EVENT_ERROR_BAD_CABLE = 0x7,
- MLX5_MODULE_EVENT_ERROR_PCIE_POWER_SLOT_EXCEEDED = 0xc,
- MLX5_MODULE_EVENT_ERROR_NUM,
-};
-
-struct mlx5_pme_stats {
- u64 status_counters[MLX5_MODULE_STATUS_NUM];
- u64 error_counters[MLX5_MODULE_EVENT_ERROR_NUM];
-};
-
-void mlx5_get_pme_stats(struct mlx5_core_dev *dev, struct mlx5_pme_stats *stats);
-int mlx5_notifier_call_chain(struct mlx5_events *events, unsigned int event, void *data);
-
static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
{
return devlink_net(priv_to_devlink(dev));
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
index 8ff16318e32d..4450091e181a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
@@ -99,7 +99,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev)
int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table);
struct mlx5_mpfs *mpfs;
- if (!MLX5_ESWITCH_MANAGER(dev))
+ if (!MLX5_ESWITCH_MANAGER(dev) || l2table_size == 1)
return 0;
mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
index 696e45e2bd06..e223e0e46433 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c
@@ -24,7 +24,8 @@ static const u32 tout_def_sw_val[MAX_TIMEOUT_TYPES] = {
[MLX5_TO_TEARDOWN_MS] = 3000,
[MLX5_TO_FSM_REACTIVATE_MS] = 5000,
[MLX5_TO_RECLAIM_PAGES_MS] = 5000,
- [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000
+ [MLX5_TO_RECLAIM_VFS_PAGES_MS] = 120000,
+ [MLX5_TO_RESET_UNLOAD_MS] = 300000
};
static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_types type)
@@ -118,7 +119,8 @@ u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type)
#define MLX5_TIMEOUT_FILL(fld, reg_out, dev, to_type, to_extra) \
({ \
u64 fw_to = MLX5_TIMEOUT_QUERY(fld, reg_out); \
- tout_set(dev, fw_to + (to_extra), to_type); \
+ if (fw_to) \
+ tout_set(dev, fw_to + (to_extra), to_type); \
fw_to; \
})
@@ -146,6 +148,7 @@ static int tout_query_dtor(struct mlx5_core_dev *dev)
MLX5_TIMEOUT_FILL(fsm_reactivate_to, out, dev, MLX5_TO_FSM_REACTIVATE_MS, 0);
MLX5_TIMEOUT_FILL(reclaim_pages_to, out, dev, MLX5_TO_RECLAIM_PAGES_MS, 0);
MLX5_TIMEOUT_FILL(reclaim_vfs_pages_to, out, dev, MLX5_TO_RECLAIM_VFS_PAGES_MS, 0);
+ MLX5_TIMEOUT_FILL(reset_unload_to, out, dev, MLX5_TO_RESET_UNLOAD_MS, 0);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
index bc9e9aeda847..99e0a05526fe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h
@@ -26,6 +26,7 @@ enum mlx5_timeouts_types {
MLX5_TO_FSM_REACTIVATE_MS,
MLX5_TO_RECLAIM_PAGES_MS,
MLX5_TO_RECLAIM_VFS_PAGES_MS,
+ MLX5_TO_RESET_UNLOAD_MS,
MAX_TIMEOUT_TYPES
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index d6ee016deae1..72ae560a1c68 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -619,6 +619,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_event))
MLX5_SET(cmd_hca_cap, set_hca_cap, pci_sync_for_fw_update_event, 1);
+ if (MLX5_CAP_GEN_MAX(dev, pci_sync_for_fw_update_with_driver_unload))
+ MLX5_SET(cmd_hca_cap, set_hca_cap,
+ pci_sync_for_fw_update_with_driver_unload, 1);
if (MLX5_CAP_GEN_MAX(dev, num_vhca_ports))
MLX5_SET(cmd_hca_cap,
@@ -1118,7 +1121,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
mlx5_devcom_unregister_device(dev->priv.devcom);
}
-static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
+static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout)
{
int err;
@@ -1183,28 +1186,56 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
goto reclaim_boot_pages;
}
+ return 0;
+
+reclaim_boot_pages:
+ mlx5_reclaim_startup_pages(dev);
+err_disable_hca:
+ mlx5_core_disable_hca(dev, 0);
+stop_health_poll:
+ mlx5_stop_health_poll(dev, boot);
+err_cmd_cleanup:
+ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
+ mlx5_cmd_cleanup(dev);
+
+ return err;
+}
+
+static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot)
+{
+ mlx5_reclaim_startup_pages(dev);
+ mlx5_core_disable_hca(dev, 0);
+ mlx5_stop_health_poll(dev, boot);
+ mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
+ mlx5_cmd_cleanup(dev);
+}
+
+static int mlx5_function_open(struct mlx5_core_dev *dev)
+{
+ int err;
+
err = set_hca_ctrl(dev);
if (err) {
mlx5_core_err(dev, "set_hca_ctrl failed\n");
- goto reclaim_boot_pages;
+ return err;
}
err = set_hca_cap(dev);
if (err) {
mlx5_core_err(dev, "set_hca_cap failed\n");
- goto reclaim_boot_pages;
+ return err;
}
err = mlx5_satisfy_startup_pages(dev, 0);
if (err) {
mlx5_core_err(dev, "failed to allocate init pages\n");
- goto reclaim_boot_pages;
+ return err;
}
err = mlx5_cmd_init_hca(dev, sw_owner_id);
if (err) {
mlx5_core_err(dev, "init hca failed\n");
- goto reclaim_boot_pages;
+ return err;
}
mlx5_set_driver_version(dev);
@@ -1212,26 +1243,13 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
err = mlx5_query_hca_caps(dev);
if (err) {
mlx5_core_err(dev, "query hca failed\n");
- goto reclaim_boot_pages;
+ return err;
}
mlx5_start_health_fw_log_up(dev);
-
return 0;
-
-reclaim_boot_pages:
- mlx5_reclaim_startup_pages(dev);
-err_disable_hca:
- mlx5_core_disable_hca(dev, 0);
-stop_health_poll:
- mlx5_stop_health_poll(dev, boot);
-err_cmd_cleanup:
- mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
- mlx5_cmd_cleanup(dev);
-
- return err;
}
-static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
+static int mlx5_function_close(struct mlx5_core_dev *dev)
{
int err;
@@ -1240,15 +1258,33 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n");
return err;
}
- mlx5_reclaim_startup_pages(dev);
- mlx5_core_disable_hca(dev, 0);
- mlx5_stop_health_poll(dev, boot);
- mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
- mlx5_cmd_cleanup(dev);
return 0;
}
+static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
+{
+ int err;
+
+ err = mlx5_function_enable(dev, boot, timeout);
+ if (err)
+ return err;
+
+ err = mlx5_function_open(dev);
+ if (err)
+ mlx5_function_disable(dev, boot);
+ return err;
+}
+
+static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
+{
+ int err = mlx5_function_close(dev);
+
+ if (!err)
+ mlx5_function_disable(dev, boot);
+ return err;
+}
+
static int mlx5_load(struct mlx5_core_dev *dev)
{
int err;
@@ -1391,12 +1427,11 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
mlx5_put_uars_page(dev, dev->priv.uar);
}
-int mlx5_init_one(struct mlx5_core_dev *dev)
+int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev)
{
- struct devlink *devlink = priv_to_devlink(dev);
+ bool light_probe = mlx5_dev_is_lightweight(dev);
int err = 0;
- devl_lock(devlink);
mutex_lock(&dev->intf_state_mutex);
dev->state = MLX5_DEVICE_STATE_UP;
@@ -1410,9 +1445,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
goto function_teardown;
}
- err = mlx5_devlink_params_register(priv_to_devlink(dev));
- if (err)
- goto err_devlink_params_reg;
+ /* In case of light_probe, mlx5_devlink is already registered.
+ * Hence, don't register devlink again.
+ */
+ if (!light_probe) {
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ if (err)
+ goto err_devlink_params_reg;
+ }
err = mlx5_load(dev);
if (err)
@@ -1425,14 +1465,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
goto err_register;
mutex_unlock(&dev->intf_state_mutex);
- devl_unlock(devlink);
return 0;
err_register:
clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state);
mlx5_unload(dev);
err_load:
- mlx5_devlink_params_unregister(priv_to_devlink(dev));
+ if (!light_probe)
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
err_devlink_params_reg:
mlx5_cleanup_once(dev);
function_teardown:
@@ -1440,6 +1480,16 @@ function_teardown:
err_function:
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
mutex_unlock(&dev->intf_state_mutex);
+ return err;
+}
+
+int mlx5_init_one(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+ int err;
+
+ devl_lock(devlink);
+ err = mlx5_init_one_devl_locked(dev);
devl_unlock(devlink);
return err;
}
@@ -1456,6 +1506,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
mlx5_core_warn(dev, "%s: interface is down, NOP\n",
__func__);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
mlx5_cleanup_once(dev);
goto out;
}
@@ -1557,6 +1608,100 @@ void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend)
devl_unlock(devlink);
}
+/* In case of light probe, we don't need a full query of hca_caps, but only the bellow caps.
+ * A full query of hca_caps will be done when the device will reload.
+ */
+static int mlx5_query_hca_caps_light(struct mlx5_core_dev *dev)
+{
+ int err;
+
+ err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL);
+ if (err)
+ return err;
+
+ if (MLX5_CAP_GEN(dev, eth_net_offloads)) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS);
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN(dev, nic_flow_table) ||
+ MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE);
+ if (err)
+ return err;
+ }
+
+ if (MLX5_CAP_GEN_64(dev, general_obj_types) &
+ MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) {
+ err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int mlx5_init_one_light(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+ int err;
+
+ dev->state = MLX5_DEVICE_STATE_UP;
+ err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_function_enable err=%d\n", err);
+ goto out;
+ }
+
+ err = mlx5_query_hca_caps_light(dev);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_query_hca_caps_light err=%d\n", err);
+ goto query_hca_caps_err;
+ }
+
+ devl_lock(devlink);
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ devl_unlock(devlink);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+ goto query_hca_caps_err;
+ }
+
+ return 0;
+
+query_hca_caps_err:
+ mlx5_function_disable(dev, true);
+out:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+ return err;
+}
+
+void mlx5_uninit_one_light(struct mlx5_core_dev *dev)
+{
+ struct devlink *devlink = priv_to_devlink(dev);
+
+ devl_lock(devlink);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
+ devl_unlock(devlink);
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+ mlx5_function_disable(dev, true);
+}
+
+/* xxx_light() function are used in order to configure the device without full
+ * init (light init). e.g.: There isn't a point in reload a device to light state.
+ * Hence, mlx5_load_one_light() isn't needed.
+ */
+
+void mlx5_unload_one_light(struct mlx5_core_dev *dev)
+{
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+ mlx5_function_disable(dev, false);
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+}
+
static const int types[] = {
MLX5_CAP_GENERAL,
MLX5_CAP_GENERAL_2,
@@ -1809,7 +1954,7 @@ static void remove_one(struct pci_dev *pdev)
mlx5_drain_fw_reset(dev);
mlx5_drain_health_wq(dev);
devlink_unregister(devlink);
- mlx5_sriov_disable(pdev);
+ mlx5_sriov_disable(pdev, false);
mlx5_thermal_uninit(dev);
mlx5_crdump_disable(dev);
mlx5_uninit_one(dev);
@@ -1844,7 +1989,7 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
mlx5_enter_error_state(dev, false);
mlx5_error_sw_reset(dev);
- mlx5_unload_one(dev, true);
+ mlx5_unload_one(dev, false);
mlx5_drain_health_wq(dev);
mlx5_pci_disable_device(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 229520405d4a..682d3dc00dd1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -195,7 +195,7 @@ void mlx5_sriov_cleanup(struct mlx5_core_dev *dev);
int mlx5_sriov_attach(struct mlx5_core_dev *dev);
void mlx5_sriov_detach(struct mlx5_core_dev *dev);
int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs);
-void mlx5_sriov_disable(struct pci_dev *pdev);
+void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change);
int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count);
int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
@@ -240,11 +240,14 @@ int mlx5_attach_device(struct mlx5_core_dev *dev);
void mlx5_detach_device(struct mlx5_core_dev *dev, bool suspend);
int mlx5_register_device(struct mlx5_core_dev *dev);
void mlx5_unregister_device(struct mlx5_core_dev *dev);
+void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev);
+bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev);
struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev);
void mlx5_dev_list_lock(void);
void mlx5_dev_list_unlock(void);
int mlx5_dev_list_trylock(void);
+void mlx5_fw_reporters_create(struct mlx5_core_dev *dev);
int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size);
int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size);
int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode);
@@ -307,16 +310,20 @@ static inline bool mlx5_core_is_sf(const struct mlx5_core_dev *dev)
int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx);
void mlx5_mdev_uninit(struct mlx5_core_dev *dev);
int mlx5_init_one(struct mlx5_core_dev *dev);
+int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev);
void mlx5_uninit_one(struct mlx5_core_dev *dev);
void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend);
void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev, bool suspend);
int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery);
+int mlx5_init_one_light(struct mlx5_core_dev *dev);
+void mlx5_uninit_one_light(struct mlx5_core_dev *dev);
+void mlx5_unload_one_light(struct mlx5_core_dev *dev);
-int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 function_id,
+int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 vport,
u16 opmod);
-#define mlx5_vport_get_other_func_general_cap(dev, fid, out) \
- mlx5_vport_get_other_func_cap(dev, fid, out, MLX5_CAP_GENERAL)
+#define mlx5_vport_get_other_func_general_cap(dev, vport, out) \
+ mlx5_vport_get_other_func_cap(dev, vport, out, MLX5_CAP_GENERAL)
void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work);
static inline u32 mlx5_sriov_get_vf_total_msix(struct pci_dev *pdev)
@@ -331,4 +338,31 @@ bool mlx5_rdma_supported(struct mlx5_core_dev *dev);
bool mlx5_vnet_supported(struct mlx5_core_dev *dev);
bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev);
+static inline u16 mlx5_core_ec_vf_vport_base(const struct mlx5_core_dev *dev)
+{
+ return MLX5_CAP_GEN_2(dev, ec_vf_vport_base);
+}
+
+static inline u16 mlx5_core_ec_sriov_enabled(const struct mlx5_core_dev *dev)
+{
+ return mlx5_core_is_ecpf(dev) && mlx5_core_ec_vf_vport_base(dev);
+}
+
+static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16 vport_num)
+{
+ int base_vport = mlx5_core_ec_vf_vport_base(dev);
+ int max_vport = base_vport + mlx5_core_max_ec_vfs(dev);
+
+ if (!mlx5_core_ec_sriov_enabled(dev))
+ return false;
+
+ return (vport_num >= base_vport && vport_num < max_vport);
+}
+
+static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func)
+{
+ return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + 1
+ : vport;
+}
+
#endif /* __MLX5_CORE_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index 95dc67fb3001..dcf58efac159 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -79,7 +79,13 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct
if (!func_id)
return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF;
- return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF;
+ if (func_id <= max(mlx5_core_max_vfs(dev), mlx5_core_max_ec_vfs(dev))) {
+ if (ec_function)
+ return MLX5_EC_VF;
+ else
+ return MLX5_VF;
+ }
+ return MLX5_SF;
}
static u32 mlx5_get_ec_function(u32 function)
@@ -730,6 +736,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
WARN(dev->priv.page_counters[MLX5_HOST_PF],
"External host PF FW pages counter is %d after reclaiming all pages\n",
dev->priv.page_counters[MLX5_HOST_PF]);
+ WARN(dev->priv.page_counters[MLX5_EC_VF],
+ "EC VFs FW pages counter is %d after reclaiming all pages\n",
+ dev->priv.page_counters[MLX5_EC_VF]);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index 98412bd5a696..cba2a4afb5fd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -41,6 +41,15 @@ struct mlx5_irq_table {
struct mlx5_irq_pool *sf_comp_pool;
};
+static int mlx5_core_func_to_vport(const struct mlx5_core_dev *dev,
+ int func,
+ bool ec_vf_func)
+{
+ if (!ec_vf_func)
+ return func;
+ return mlx5_core_ec_vf_vport_base(dev) + func - 1;
+}
+
/**
* mlx5_get_default_msix_vec_count - Get the default number of MSI-X vectors
* to be ssigned to each VF.
@@ -79,6 +88,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
void *hca_cap = NULL, *query_cap = NULL, *cap;
int num_vf_msix, min_msix, max_msix;
+ bool ec_vf_function;
+ int vport;
int ret;
num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix);
@@ -104,7 +115,9 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
goto out;
}
- ret = mlx5_vport_get_other_func_general_cap(dev, function_id, query_cap);
+ ec_vf_function = mlx5_core_ec_sriov_enabled(dev);
+ vport = mlx5_core_func_to_vport(dev, function_id, ec_vf_function);
+ ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_cap);
if (ret)
goto out;
@@ -115,6 +128,7 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP);
MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1);
+ MLX5_SET(set_hca_cap_in, hca_cap, ec_vf_function, ec_vf_function);
MLX5_SET(set_hca_cap_in, hca_cap, function_id, function_id);
MLX5_SET(set_hca_cap_in, hca_cap, op_mod,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
index 540cf05f6373..a42f6cd99b74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
@@ -30,9 +30,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
struct mlx5_flow_spec *spec;
struct mlx5_flow_table *ft;
struct mlx5_flow_group *fg;
- void *match_criteria;
+ struct mlx5_eswitch *esw;
u32 *flow_group_in;
- void *misc;
int err;
if (!(MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) &&
@@ -63,12 +62,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
goto free;
}
- MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
- MLX5_MATCH_MISC_PARAMETERS);
- match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
- match_criteria);
- MLX5_SET_TO_ONES(fte_match_param, match_criteria,
- misc_parameters.source_port);
+ esw = dev->priv.eswitch;
+ mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0);
fg = mlx5_create_flow_group(ft, flow_group_in);
if (IS_ERR(fg)) {
@@ -77,14 +72,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev)
goto destroy_flow_table;
}
- spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
- misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
- misc_parameters);
- MLX5_SET(fte_match_set_misc, misc, source_port,
- dev->priv.eswitch->manager_vport);
- misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
- misc_parameters);
- MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
+ mlx5_esw_set_spec_source_port(esw, esw->manager_vport, spec);
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0);
@@ -115,7 +103,7 @@ free:
static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev)
{
- mlx5_core_roce_gid_set(dev, 0, 0, 0,
+ mlx5_core_roce_gid_set(dev, 0, MLX5_ROCE_VERSION_2, 0,
NULL, NULL, false, 0, 1);
}
@@ -135,7 +123,7 @@ static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev)
mlx5_rdma_make_default_gid(dev, &gid);
return mlx5_core_roce_gid_set(dev, 0,
- MLX5_ROCE_VERSION_1,
+ MLX5_ROCE_VERSION_2,
0, gid.raw, mac,
false, 0, 1);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
index 0692363cf80e..8fe82f1191bb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
@@ -3,6 +3,7 @@
#include <linux/mlx5/driver.h>
#include <linux/mlx5/device.h>
+#include <linux/mlx5/eswitch.h>
#include "mlx5_core.h"
#include "dev.h"
#include "devlink.h"
@@ -28,6 +29,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
mdev->priv.adev_idx = adev->id;
sf_dev->mdev = mdev;
+ /* Only local SFs do light probe */
+ if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev))
+ mlx5_dev_set_lightweight(mdev);
+
err = mlx5_mdev_init(mdev, MLX5_SF_PROF);
if (err) {
mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err);
@@ -41,7 +46,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
goto remap_err;
}
- err = mlx5_init_one(mdev);
+ if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev))
+ err = mlx5_init_one_light(mdev);
+ else
+ err = mlx5_init_one(mdev);
if (err) {
mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err);
goto init_one_err;
@@ -65,7 +73,10 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
mlx5_drain_health_wq(sf_dev->mdev);
devlink_unregister(devlink);
- mlx5_uninit_one(sf_dev->mdev);
+ if (mlx5_dev_is_lightweight(sf_dev->mdev))
+ mlx5_uninit_one_light(sf_dev->mdev);
+ else
+ mlx5_uninit_one(sf_dev->mdev);
iounmap(sf_dev->mdev->iseg);
mlx5_mdev_uninit(sf_dev->mdev);
mlx5_devlink_free(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
index 7d955a4d9f14..6a3fa30b2bf2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
@@ -28,7 +28,6 @@ struct mlx5_sf_table {
struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */
struct notifier_block esw_nb;
struct notifier_block vhca_nb;
- u8 ecpu: 1;
};
static struct mlx5_sf *
@@ -283,7 +282,7 @@ out:
static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
const struct devlink_port_new_attrs *new_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index)
+ struct devlink_port **dl_port)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5_sf *sf;
@@ -297,7 +296,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
new_attr->controller, new_attr->sfnum);
if (err)
goto esw_err;
- *new_port_index = sf->port_index;
+ *dl_port = &sf->dl_port;
trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum);
return 0;
@@ -339,7 +338,7 @@ mlx5_sf_new_check_attr(struct mlx5_core_dev *dev, const struct devlink_port_new_
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *new_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index)
+ struct devlink_port **dl_port)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_sf_table *table;
@@ -355,7 +354,7 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink,
"Port add is only supported in eswitch switchdev mode or SF ports are disabled.");
return -EOPNOTSUPP;
}
- err = mlx5_sf_add(dev, table, new_attr, extack, new_port_index);
+ err = mlx5_sf_add(dev, table, new_attr, extack, dl_port);
mlx5_sf_table_put(table);
return err;
}
@@ -379,7 +378,8 @@ static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf)
}
}
-int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
+int mlx5_devlink_sf_port_del(struct devlink *devlink,
+ struct devlink_port *dl_port,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
@@ -394,7 +394,7 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
"Port del is only supported in eswitch switchdev mode or SF ports are disabled.");
return -EOPNOTSUPP;
}
- sf = mlx5_sf_lookup_by_index(table, port_index);
+ sf = mlx5_sf_lookup_by_index(table, dl_port->index);
if (!sf) {
err = -ENODEV;
goto sf_err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
index 3a480e06ecc0..860f9ddb7107 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
@@ -21,8 +21,9 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev);
int mlx5_devlink_sf_port_new(struct devlink *devlink,
const struct devlink_port_new_attrs *add_attr,
struct netlink_ext_ack *extack,
- unsigned int *new_port_index);
-int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index,
+ struct devlink_port **dl_port);
+int mlx5_devlink_sf_port_del(struct devlink *devlink,
+ struct devlink_port *dl_port,
struct netlink_ext_ack *extack);
int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port,
enum devlink_port_fn_state *state,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
index 20d7662c10fb..a2fc937d5461 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
@@ -37,7 +37,7 @@
#include "mlx5_irq.h"
#include "eswitch.h"
-static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
+static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf, u16 func_id)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
struct mlx5_hca_vport_context *in;
@@ -59,7 +59,7 @@ static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf)
!!(in->node_guid) * MLX5_HCA_VPORT_SEL_NODE_GUID |
!!(in->policy) * MLX5_HCA_VPORT_SEL_STATE_POLICY;
- err = mlx5_core_modify_hca_vport_context(dev, 1, 1, vf + 1, in);
+ err = mlx5_core_modify_hca_vport_context(dev, 1, 1, func_id, in);
if (err)
mlx5_core_warn(dev, "modify vport context failed, unable to restore VF %d settings\n", vf);
@@ -73,9 +73,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
int err, vf, num_msix_count;
-
- if (!MLX5_ESWITCH_MANAGER(dev))
- goto enable_vfs_hca;
+ int vport_num;
err = mlx5_eswitch_enable(dev->priv.eswitch, num_vfs);
if (err) {
@@ -84,7 +82,6 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
return err;
}
-enable_vfs_hca:
num_msix_count = mlx5_get_default_msix_vec_count(dev, num_vfs);
for (vf = 0; vf < num_vfs; vf++) {
/* Notify the VF before its enablement to let it set
@@ -108,7 +105,10 @@ enable_vfs_hca:
sriov->vfs_ctx[vf].enabled = 1;
if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) {
- err = sriov_restore_guids(dev, vf);
+ vport_num = mlx5_core_ec_sriov_enabled(dev) ?
+ mlx5_core_ec_vf_vport_base(dev) + vf
+ : vf + 1;
+ err = sriov_restore_guids(dev, vf, vport_num);
if (err) {
mlx5_core_warn(dev,
"failed to restore VF %d settings, err %d\n",
@@ -123,9 +123,11 @@ enable_vfs_hca:
}
static void
-mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf)
+mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf, bool num_vf_change)
{
struct mlx5_core_sriov *sriov = &dev->priv.sriov;
+ bool wait_for_ec_vf_pages = true;
+ bool wait_for_vf_pages = true;
int err;
int vf;
@@ -147,11 +149,30 @@ mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf)
mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf);
+ /* There are a number of scenarios when SRIOV is being disabled:
+ * 1. VFs or ECVFs had been created, and now set back to 0 (num_vf_change == true).
+ * - If EC SRIOV is enabled then this flow is happening on the
+ * embedded platform, wait for only EC VF pages.
+ * - If EC SRIOV is not enabled this flow is happening on non-embedded
+ * platform, wait for the VF pages.
+ *
+ * 2. The driver is being unloaded. In this case wait for all pages.
+ */
+ if (num_vf_change) {
+ if (mlx5_core_ec_sriov_enabled(dev))
+ wait_for_vf_pages = false;
+ else
+ wait_for_ec_vf_pages = false;
+ }
+
+ if (wait_for_ec_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_EC_VF]))
+ mlx5_core_warn(dev, "timeout reclaiming EC VFs pages\n");
+
/* For ECPFs, skip waiting for host VF pages until ECPF is destroyed */
if (mlx5_core_is_ecpf(dev))
return;
- if (mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF]))
+ if (wait_for_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF]))
mlx5_core_warn(dev, "timeout reclaiming VFs pages\n");
}
@@ -172,12 +193,12 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs)
err = pci_enable_sriov(pdev, num_vfs);
if (err) {
mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err);
- mlx5_device_disable_sriov(dev, num_vfs, true);
+ mlx5_device_disable_sriov(dev, num_vfs, true, true);
}
return err;
}
-void mlx5_sriov_disable(struct pci_dev *pdev)
+void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change)
{
struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
struct devlink *devlink = priv_to_devlink(dev);
@@ -185,7 +206,7 @@ void mlx5_sriov_disable(struct pci_dev *pdev)
pci_disable_sriov(pdev);
devl_lock(devlink);
- mlx5_device_disable_sriov(dev, num_vfs, true);
+ mlx5_device_disable_sriov(dev, num_vfs, true, num_vf_change);
devl_unlock(devlink);
}
@@ -200,7 +221,7 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs)
if (num_vfs)
err = mlx5_sriov_enable(pdev, num_vfs);
else
- mlx5_sriov_disable(pdev);
+ mlx5_sriov_disable(pdev, true);
if (!err)
sriov->num_vfs = num_vfs;
@@ -245,7 +266,7 @@ void mlx5_sriov_detach(struct mlx5_core_dev *dev)
if (!mlx5_core_is_pf(dev))
return;
- mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false);
+ mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false, false);
}
static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
@@ -264,8 +285,7 @@ static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
host_total_vfs = MLX5_GET(query_esw_functions_out, out,
host_params_context.host_total_vfs);
kvfree(out);
- if (host_total_vfs)
- return host_total_vfs;
+ return host_total_vfs;
}
done:
@@ -284,6 +304,7 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev)
total_vfs = pci_sriov_get_totalvfs(pdev);
sriov->max_vfs = mlx5_get_max_vfs(dev);
sriov->num_vfs = pci_num_vf(pdev);
+ sriov->max_ec_vfs = mlx5_core_ec_sriov_enabled(dev) ? pci_sriov_get_totalvfs(dev->pdev) : 0;
sriov->vfs_ctx = kcalloc(total_vfs, sizeof(*sriov->vfs_ctx), GFP_KERNEL);
if (!sriov->vfs_ctx)
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
index 0f783e7906cb..54bb0866ed72 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -2077,8 +2077,9 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
struct mlx5dr_action *action;
u8 peer_vport;
- peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi);
- vport_dmn = peer_vport ? dmn->peer_dmn : dmn;
+ peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) &&
+ (vhca_id != dmn->info.caps.gvmi);
+ vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn;
if (!vport_dmn) {
mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n");
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
index 1aa525e509f1..8c2a34a0d6be 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
@@ -34,6 +34,7 @@ int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
u16 vport_number, u16 *gvmi)
{
+ bool ec_vf_func = other_vport ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false;
u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
int out_size;
void *out;
@@ -46,7 +47,8 @@ int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
- MLX5_SET(query_hca_cap_in, in, function_id, vport_number);
+ MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func));
+ MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
MLX5_SET(query_hca_cap_in, in, op_mod,
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
HCA_CAP_OPMOD_GET_CUR);
@@ -562,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
if (err)
- return err;
+ goto err_free_in;
*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
- kvfree(in);
+err_free_in:
+ kvfree(in);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
index 9a2dfe6ebe31..3d74109f8230 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
@@ -475,6 +475,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
mutex_init(&dmn->info.rx.mutex);
mutex_init(&dmn->info.tx.mutex);
xa_init(&dmn->definers_xa);
+ xa_init(&dmn->peer_dmn_xa);
if (dr_domain_caps_init(mdev, dmn)) {
mlx5dr_err(dmn, "Failed init domain, no caps\n");
@@ -507,6 +508,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
uninit_caps:
dr_domain_caps_uninit(dmn);
def_xa_destroy:
+ xa_destroy(&dmn->peer_dmn_xa);
xa_destroy(&dmn->definers_xa);
kfree(dmn);
return NULL;
@@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
dr_domain_uninit_csum_recalc_fts(dmn);
dr_domain_uninit_resources(dmn);
dr_domain_caps_uninit(dmn);
+ xa_destroy(&dmn->peer_dmn_xa);
xa_destroy(&dmn->definers_xa);
mutex_destroy(&dmn->info.tx.mutex);
mutex_destroy(&dmn->info.rx.mutex);
@@ -555,17 +558,22 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
}
void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
- struct mlx5dr_domain *peer_dmn)
+ struct mlx5dr_domain *peer_dmn,
+ u16 peer_vhca_id)
{
+ struct mlx5dr_domain *peer;
+
mlx5dr_domain_lock(dmn);
- if (dmn->peer_dmn)
- refcount_dec(&dmn->peer_dmn->refcount);
+ peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+ if (peer)
+ refcount_dec(&peer->refcount);
- dmn->peer_dmn = peer_dmn;
+ WARN_ON(xa_err(xa_store(&dmn->peer_dmn_xa, peer_vhca_id, peer_dmn, GFP_KERNEL)));
- if (dmn->peer_dmn)
- refcount_inc(&dmn->peer_dmn->refcount);
+ peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+ if (peer)
+ refcount_inc(&peer->refcount);
mlx5dr_domain_unlock(dmn);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
index d6947fe13d56..8ca534ef5d03 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
@@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr,
u32 chunk_size;
u32 index;
- chunk_size = ilog2(num_of_actions);
+ chunk_size = ilog2(roundup_pow_of_two(num_of_actions));
/* HW modify action index granularity is at least 64B */
chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
index 2010d4ac6519..f708b029425a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
@@ -1647,21 +1647,23 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
u8 *tag)
{
struct mlx5dr_match_misc *misc = &value->misc;
+ int id = misc->source_eswitch_owner_vhca_id;
struct mlx5dr_cmd_vport_cap *vport_cap;
struct mlx5dr_domain *dmn = sb->dmn;
struct mlx5dr_domain *vport_dmn;
u8 *bit_mask = sb->bit_mask;
+ struct mlx5dr_domain *peer;
bool source_gvmi_set;
DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
if (sb->vhca_id_valid) {
+ peer = xa_load(&dmn->peer_dmn_xa, id);
/* Find port GVMI based on the eswitch_owner_vhca_id */
- if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
+ if (id == dmn->info.caps.gvmi)
vport_dmn = dmn;
- else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
- dmn->peer_dmn->info.caps.gvmi))
- vport_dmn = dmn->peer_dmn;
+ else if (peer && (id == peer->info.caps.gvmi))
+ vport_dmn = peer;
else
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
index 4c0704ad166b..dd856cde188d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
@@ -1979,20 +1979,22 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
u8 *tag)
{
struct mlx5dr_match_misc *misc = &value->misc;
+ int id = misc->source_eswitch_owner_vhca_id;
struct mlx5dr_cmd_vport_cap *vport_cap;
struct mlx5dr_domain *dmn = sb->dmn;
struct mlx5dr_domain *vport_dmn;
u8 *bit_mask = sb->bit_mask;
+ struct mlx5dr_domain *peer;
DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn);
if (sb->vhca_id_valid) {
+ peer = xa_load(&dmn->peer_dmn_xa, id);
/* Find port GVMI based on the eswitch_owner_vhca_id */
- if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
+ if (id == dmn->info.caps.gvmi)
vport_dmn = dmn;
- else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
- dmn->peer_dmn->info.caps.gvmi))
- vport_dmn = dmn->peer_dmn;
+ else if (peer && (id == peer->info.caps.gvmi))
+ vport_dmn = peer;
else
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
index 678a993ab053..6c59de3e28f6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
@@ -935,7 +935,6 @@ struct mlx5dr_domain_info {
};
struct mlx5dr_domain {
- struct mlx5dr_domain *peer_dmn;
struct mlx5_core_dev *mdev;
u32 pdn;
struct mlx5_uars_page *uar;
@@ -956,6 +955,7 @@ struct mlx5dr_domain {
struct list_head dbg_tbl_list;
struct mlx5dr_dbg_dump_info dump_info;
struct xarray definers_xa;
+ struct xarray peer_dmn_xa;
/* memory management statistics */
u32 num_buddies[DR_ICM_TYPE_MAX];
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
index cc215beb7436..feb307fb3440 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
@@ -780,14 +780,15 @@ restore_fte:
}
static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns,
- struct mlx5_flow_root_namespace *peer_ns)
+ struct mlx5_flow_root_namespace *peer_ns,
+ u16 peer_vhca_id)
{
struct mlx5dr_domain *peer_domain = NULL;
if (peer_ns)
peer_domain = peer_ns->fs_dr_domain.dr_domain;
mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain,
- peer_domain);
+ peer_domain, peer_vhca_id);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
index d1c04f43d86d..89fced86936f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
@@ -48,7 +48,8 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *domain);
int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags);
void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
- struct mlx5dr_domain *peer_dmn);
+ struct mlx5dr_domain *peer_dmn,
+ u16 peer_vhca_id);
struct mlx5dr_table *
mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
index e47fa6fb836f..52199d39657e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/thermal.c
@@ -45,7 +45,7 @@ static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p
static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev,
int *p_temp)
{
- struct mlx5_thermal *thermal = tzdev->devdata;
+ struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev);
struct mlx5_core_dev *mdev = thermal->mdev;
int err;
@@ -68,30 +68,36 @@ static struct thermal_zone_device_ops mlx5_thermal_ops = {
int mlx5_thermal_init(struct mlx5_core_dev *mdev)
{
+ char data[THERMAL_NAME_LENGTH];
struct mlx5_thermal *thermal;
- struct thermal_zone_device *tzd;
- const char *data = "mlx5";
+ int err;
- tzd = thermal_zone_get_zone_by_name(data);
- if (!IS_ERR(tzd))
+ if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev))
return 0;
+ err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device));
+ if (err < 0 || err >= sizeof(data)) {
+ mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err);
+ return -EINVAL;
+ }
+
thermal = kzalloc(sizeof(*thermal), GFP_KERNEL);
if (!thermal)
return -ENOMEM;
thermal->mdev = mdev;
- thermal->tzdev = thermal_zone_device_register(data,
- MLX5_THERMAL_NUM_TRIPS,
- MLX5_THERMAL_TRIP_MASK,
- thermal,
- &mlx5_thermal_ops,
- NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
+ thermal->tzdev = thermal_zone_device_register_with_trips(data,
+ NULL,
+ MLX5_THERMAL_NUM_TRIPS,
+ MLX5_THERMAL_TRIP_MASK,
+ thermal,
+ &mlx5_thermal_ops,
+ NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
if (IS_ERR(thermal->tzdev)) {
- dev_err(mdev->device, "Failed to register thermal zone device (%s) %ld\n",
- data, PTR_ERR(thermal->tzdev));
+ err = PTR_ERR(thermal->tzdev);
+ mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err);
kfree(thermal);
- return -EINVAL;
+ return err;
}
mdev->thermal = thermal;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
index ba7e3df22413..5a31fb47ffa5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
@@ -288,7 +288,8 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type);
MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
- MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
+ if (vport || mlx5_core_is_ecpf(dev))
+ MLX5_SET(query_nic_vport_context_in, in, other_vport, 1);
err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
if (err)
@@ -1160,23 +1161,26 @@ u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev)
}
EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid);
-int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out,
+int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out,
u16 opmod)
{
+ bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {};
opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01);
MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
MLX5_SET(query_hca_cap_in, in, op_mod, opmod);
- MLX5_SET(query_hca_cap_in, in, function_id, function_id);
+ MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(dev, vport, ec_vf_func));
MLX5_SET(query_hca_cap_in, in, other_function, true);
+ MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
}
EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap);
int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap,
- u16 function_id, u16 opmod)
+ u16 vport, u16 opmod)
{
+ bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport);
int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
void *set_hca_cap;
void *set_ctx;
@@ -1190,8 +1194,10 @@ int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap
MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1);
set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap));
- MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id);
+ MLX5_SET(set_hca_cap_in, set_ctx, function_id,
+ mlx5_vport_to_func_id(dev, vport, ec_vf_func));
MLX5_SET(set_hca_cap_in, set_ctx, other_function, true);
+ MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func);
ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx);
kfree(set_ctx);
diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
index b001e5258091..47f6cc0401c3 100644
--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
+++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h
@@ -44,7 +44,7 @@ MLXFW_MFA2_TLV(multi, struct mlxfw_mfa2_tlv_multi,
MLXFW_MFA2_TLV_MULTI_PART);
struct mlxfw_mfa2_tlv_psid {
- u8 psid[0];
+ DECLARE_FLEX_ARRAY(u8, psid);
} __packed;
MLXFW_MFA2_TLV_VARSIZE(psid, struct mlxfw_mfa2_tlv_psid,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 22db0bb15c45..1ccf3b73ed72 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1723,8 +1723,6 @@ static const struct devlink_ops mlxsw_devlink_ops = {
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
.reload_down = mlxsw_devlink_core_bus_device_reload_down,
.reload_up = mlxsw_devlink_core_bus_device_reload_up,
- .port_split = mlxsw_devlink_port_split,
- .port_unsplit = mlxsw_devlink_port_unsplit,
.sb_pool_get = mlxsw_devlink_sb_pool_get,
.sb_pool_set = mlxsw_devlink_sb_pool_set,
.sb_port_pool_get = mlxsw_devlink_sb_port_pool_get,
@@ -3116,6 +3114,11 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_res_get);
+static const struct devlink_port_ops mlxsw_devlink_port_ops = {
+ .port_split = mlxsw_devlink_port_split,
+ .port_unsplit = mlxsw_devlink_port_unsplit,
+};
+
static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
enum devlink_port_flavour flavour,
u8 slot_index, u32 port_number, bool split,
@@ -3150,7 +3153,8 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port,
devlink_port_linecard_set(devlink_port,
linecard->devlink_linecard);
}
- err = devl_port_register(devlink, devlink_port, local_port);
+ err = devl_port_register_with_ops(devlink, devlink_port, local_port,
+ &mlxsw_devlink_port_ops);
if (err)
memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
index bd1a51a0a540..973de2adc943 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
@@ -32,8 +32,8 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x18, 0, 8),
MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x18, 9, 2),
MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x18, 11, 6),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x18, 17, 3),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_LSB, 0x18, 20, 8),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x18, 17, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_LSB, 0x18, 21, 8),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_96_127, 0x20, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_64_95, 0x24, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_32_63, 0x28, 4),
@@ -42,6 +42,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_64_95, 0x34, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1),
};
struct mlxsw_afk {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
index 3a037fe47211..65a4abadc7db 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
@@ -35,6 +35,7 @@ enum mlxsw_afk_element {
MLXSW_AFK_ELEMENT_IP_DSCP,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
+ MLXSW_AFK_ELEMENT_FDB_MISS,
MLXSW_AFK_ELEMENT_MAX,
};
@@ -69,7 +70,7 @@ struct mlxsw_afk_element_info {
MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \
_element, _offset, 0, _size)
-#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40
+#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44
struct mlxsw_afk_element_inst { /* element instance in actual block */
enum mlxsw_afk_element element;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 70735068cf29..0fd290d776ff 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -405,7 +405,8 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev,
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
return sprintf(buf, "front panel %03u\n",
- mlxsw_hwmon_attr->type_index);
+ mlxsw_hwmon_attr->type_index + 1 -
+ mlxsw_hwmon_attr->mlxsw_hwmon_dev->sensor_count);
}
static ssize_t
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index 2c586c2308ae..d23f293e285c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -48,6 +48,7 @@
#define MLXSW_I2C_MBOX_SIZE_BITS 12
#define MLXSW_I2C_ADDR_BUF_SIZE 4
#define MLXSW_I2C_BLK_DEF 32
+#define MLXSW_I2C_BLK_MAX 100
#define MLXSW_I2C_RETRY 5
#define MLXSW_I2C_TIMEOUT_MSECS 5000
#define MLXSW_I2C_MAX_DATA_SIZE 256
@@ -444,7 +445,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
} else {
/* No input mailbox is case of initialization query command. */
reg_size = MLXSW_I2C_MAX_DATA_SIZE;
- num = reg_size / mlxsw_i2c->block_size;
+ num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size);
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
dev_err(&client->dev, "Could not acquire lock");
@@ -653,7 +654,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client)
return -EOPNOTSUPP;
}
- mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF,
+ mlxsw_i2c->block_size = min_t(u16, MLXSW_I2C_BLK_MAX,
min_t(u16, quirks->max_read_len,
quirks->max_write_len));
} else {
@@ -751,7 +752,7 @@ static void mlxsw_i2c_remove(struct i2c_client *client)
int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
{
- i2c_driver->probe_new = mlxsw_i2c_probe;
+ i2c_driver->probe = mlxsw_i2c_probe;
i2c_driver->remove = mlxsw_i2c_remove;
return i2c_add_driver(i2c_driver);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
index 6b56eadd736e..6b98c3287b49 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -417,6 +417,7 @@ static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m)
err_kmalloc_array:
for (i--; i >= 0; i--)
kfree(mlxsw_m->line_cards[i]);
+ kfree(mlxsw_m->line_cards);
err_kcalloc:
kfree(mlxsw_m->ports);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index c968309657dd..51eea1f0529c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -517,11 +517,15 @@ static void mlxsw_pci_skb_cb_ts_set(struct mlxsw_pci *mlxsw_pci,
struct sk_buff *skb,
enum mlxsw_pci_cqe_v cqe_v, char *cqe)
{
+ u8 ts_type;
+
if (cqe_v != MLXSW_PCI_CQE_V2)
return;
- if (mlxsw_pci_cqe2_time_stamp_type_get(cqe) !=
- MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC)
+ ts_type = mlxsw_pci_cqe2_time_stamp_type_get(cqe);
+
+ if (ts_type != MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC &&
+ ts_type != MLXSW_PCI_CQE_TIME_STAMP_TYPE_MIRROR_UTC)
return;
mlxsw_skb_cb(skb)->cqe_ts.sec = mlxsw_pci_cqe2_time_stamp_sec_get(cqe);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 8165bf31a99a..17160e867bef 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -97,14 +97,6 @@ MLXSW_ITEM32(reg, sspr, m, 0x00, 31, 1);
*/
MLXSW_ITEM32_LP(reg, sspr, 0x00, 16, 0x00, 12);
-/* reg_sspr_sub_port
- * Virtual port within the physical port.
- * Should be set to 0 when virtual ports are not enabled on the port.
- *
- * Access: RW
- */
-MLXSW_ITEM32(reg, sspr, sub_port, 0x00, 8, 8);
-
/* reg_sspr_system_port
* Unique identifier within the stacking domain that represents all the ports
* that are available in the system (external ports).
@@ -120,7 +112,6 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u16 local_port)
MLXSW_REG_ZERO(sspr, payload);
mlxsw_reg_sspr_m_set(payload, 1);
mlxsw_reg_sspr_local_port_set(payload, local_port);
- mlxsw_reg_sspr_sub_port_set(payload, 0);
mlxsw_reg_sspr_system_port_set(payload, local_port);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 02a327744a61..25a01dafde1b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4337,8 +4337,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
/* Join a router interface configured on the LAG, if exists */
- err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan,
- lag_dev, extack);
+ err = mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev,
+ extack);
if (err)
goto err_router_join;
@@ -5139,14 +5139,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
return notifier_from_errno(err);
}
-static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
- .notifier_call = mlxsw_sp_inetaddr_valid_event,
-};
-
-static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
- .notifier_call = mlxsw_sp_inet6addr_valid_event,
-};
-
static const struct pci_device_id mlxsw_sp1_pci_id_table[] = {
{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
{0, },
@@ -5191,12 +5183,9 @@ static int __init mlxsw_sp_module_init(void)
{
int err;
- register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
- register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
-
err = mlxsw_core_driver_register(&mlxsw_sp1_driver);
if (err)
- goto err_sp1_core_driver_register;
+ return err;
err = mlxsw_core_driver_register(&mlxsw_sp2_driver);
if (err)
@@ -5242,9 +5231,6 @@ err_sp3_core_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
err_sp2_core_driver_register:
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
-err_sp1_core_driver_register:
- unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
- unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
return err;
}
@@ -5258,8 +5244,6 @@ static void __exit mlxsw_sp_module_exit(void)
mlxsw_core_driver_unregister(&mlxsw_sp3_driver);
mlxsw_core_driver_unregister(&mlxsw_sp2_driver);
mlxsw_core_driver_unregister(&mlxsw_sp1_driver);
- unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
- unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
}
module_init(mlxsw_sp_module_init);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 4c22f8004514..231e364cbb7c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -755,14 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
const struct net_device *macvlan_dev);
-int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr);
-int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr);
-int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev,
- struct netlink_ext_ack *extack);
void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
index e4f4cded2b6f..b1178b7a7f51 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
@@ -193,7 +193,7 @@ mlxsw_sp2_mr_tcam_rule_parse(struct mlxsw_sp_acl_rule *rule,
key->vrid, GENMASK(7, 0));
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- key->vrid >> 8, GENMASK(2, 0));
+ key->vrid >> 8, GENMASK(3, 0));
switch (key->proto) {
case MLXSW_SP_L3_PROTO_IPV4:
return mlxsw_sp2_mr_tcam_rule_parse4(rulei, key);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
index 00c32320f891..ae2d6f12b799 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
@@ -123,10 +123,12 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
};
@@ -169,7 +171,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 24, 8),
- MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 3),
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
@@ -319,7 +321,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 13, 8),
- MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x04, 21, 4, 0, true),
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x04, 21, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
index 5416093c0e35..c8a356accdf8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -221,7 +221,7 @@ start_again:
for (; i < rif_count; i++) {
struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
- if (!rif || !mlxsw_sp_rif_dev(rif))
+ if (!rif || !mlxsw_sp_rif_has_dev(rif))
continue;
err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif,
counters_enabled);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index 594cdcb90b3d..72917f09e806 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -281,39 +281,38 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
return 0;
}
-static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
- struct flow_cls_offload *f,
- struct mlxsw_sp_flow_block *block)
+static int
+mlxsw_sp_flower_parse_meta_iif(struct mlxsw_sp_acl_rule_info *rulei,
+ const struct mlxsw_sp_flow_block *block,
+ const struct flow_match_meta *match,
+ struct netlink_ext_ack *extack)
{
- struct flow_rule *rule = flow_cls_offload_flow_rule(f);
struct mlxsw_sp_port *mlxsw_sp_port;
struct net_device *ingress_dev;
- struct flow_match_meta match;
- if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
+ if (!match->mask->ingress_ifindex)
return 0;
- flow_rule_match_meta(rule, &match);
- if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask");
+ if (match->mask->ingress_ifindex != 0xFFFFFFFF) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
return -EINVAL;
}
ingress_dev = __dev_get_by_index(block->net,
- match.key->ingress_ifindex);
+ match->key->ingress_ifindex);
if (!ingress_dev) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on");
+ NL_SET_ERR_MSG_MOD(extack, "Can't find specified ingress port to match on");
return -EINVAL;
}
if (!mlxsw_sp_port_dev_check(ingress_dev)) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port");
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on non-mlxsw ingress port");
return -EINVAL;
}
mlxsw_sp_port = netdev_priv(ingress_dev);
if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) {
- NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device");
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on a port from different device");
return -EINVAL;
}
@@ -321,9 +320,29 @@ static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
mlxsw_sp_port->local_port,
0xFFFFFFFF);
+
return 0;
}
+static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
+ struct flow_cls_offload *f,
+ struct mlxsw_sp_flow_block *block)
+{
+ struct flow_rule *rule = flow_cls_offload_flow_rule(f);
+ struct flow_match_meta match;
+
+ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
+ return 0;
+
+ flow_rule_match_meta(rule, &match);
+
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_FDB_MISS,
+ match.key->l2_miss, match.mask->l2_miss);
+
+ return mlxsw_sp_flower_parse_meta_iif(rulei, block, &match,
+ f->common.extack);
+}
+
static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei,
struct flow_cls_offload *f)
{
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
index 1f6bc0c7e91d..69cd689dbc83 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
@@ -704,12 +704,12 @@ void mlxsw_sp_mr_vif_del(struct mlxsw_sp_mr_table *mr_table, vifi_t vif_index)
static struct mlxsw_sp_mr_vif *
mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
- const struct net_device *dev)
+ const struct mlxsw_sp_rif *rif)
{
vifi_t vif_index;
for (vif_index = 0; vif_index < MAXVIFS; vif_index++)
- if (mr_table->vifs[vif_index].dev == dev)
+ if (mlxsw_sp_rif_dev_is(rif, mr_table->vifs[vif_index].dev))
return &mr_table->vifs[vif_index];
return NULL;
}
@@ -717,13 +717,12 @@ mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table,
int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return 0;
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return 0;
return mlxsw_sp_mr_vif_resolve(mr_table, mr_vif->dev, mr_vif,
@@ -733,13 +732,12 @@ int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return;
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return;
mlxsw_sp_mr_vif_unresolve(mr_table, mr_vif->dev, mr_vif);
@@ -748,17 +746,16 @@ void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table,
void mlxsw_sp_mr_rif_mtu_update(struct mlxsw_sp_mr_table *mr_table,
const struct mlxsw_sp_rif *rif, int mtu)
{
- const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = mr_table->mlxsw_sp;
struct mlxsw_sp_mr_route_vif_entry *rve;
struct mlxsw_sp_mr *mr = mlxsw_sp->mr;
struct mlxsw_sp_mr_vif *mr_vif;
- if (!rif_dev)
+ if (!mlxsw_sp_rif_has_dev(rif))
return;
/* Search for a VIF that use that RIF */
- mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev);
+ mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif);
if (!mr_vif)
return;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
index d309b77a0194..bb8eeb86edf7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
@@ -11,10 +11,12 @@
#include "spectrum_nve.h"
#define MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \
- VXLAN_F_LEARN)
+ VXLAN_F_LEARN | \
+ VXLAN_F_LOCALBYPASS)
#define MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS (VXLAN_F_IPV6 | \
VXLAN_F_UDP_ZERO_CSUM6_TX | \
- VXLAN_F_UDP_ZERO_CSUM6_RX)
+ VXLAN_F_UDP_ZERO_CSUM6_RX | \
+ VXLAN_F_LOCALBYPASS)
static bool mlxsw_sp_nve_vxlan_ipv4_flags_check(const struct vxlan_config *cfg,
struct netlink_ext_ack *extack)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 4a73e2fe95ef..b32adf277a22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -51,10 +51,27 @@ struct mlxsw_sp_vr;
struct mlxsw_sp_lpm_tree;
struct mlxsw_sp_rif_ops;
-struct mlxsw_sp_rif {
+struct mlxsw_sp_crif_key {
+ struct net_device *dev;
+};
+
+struct mlxsw_sp_crif {
+ struct mlxsw_sp_crif_key key;
+ struct rhash_head ht_node;
+ bool can_destroy;
struct list_head nexthop_list;
+ struct mlxsw_sp_rif *rif;
+};
+
+static const struct rhashtable_params mlxsw_sp_crif_ht_params = {
+ .key_offset = offsetof(struct mlxsw_sp_crif, key),
+ .key_len = sizeof_field(struct mlxsw_sp_crif, key),
+ .head_offset = offsetof(struct mlxsw_sp_crif, ht_node),
+};
+
+struct mlxsw_sp_rif {
+ struct mlxsw_sp_crif *crif; /* NULL for underlay RIF */
struct list_head neigh_list;
- struct net_device *dev; /* NULL for underlay RIF */
struct mlxsw_sp_fid *fid;
unsigned char addr[ETH_ALEN];
int mtu;
@@ -71,6 +88,13 @@ struct mlxsw_sp_rif {
bool counter_egress_valid;
};
+static struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
+{
+ if (!rif->crif)
+ return NULL;
+ return rif->crif->key.dev;
+}
+
struct mlxsw_sp_rif_params {
struct net_device *dev;
union {
@@ -96,8 +120,8 @@ struct mlxsw_sp_rif_subport {
struct mlxsw_sp_rif_ipip_lb {
struct mlxsw_sp_rif common;
struct mlxsw_sp_rif_ipip_lb_config lb_config;
- u16 ul_vr_id; /* Reserved for Spectrum-2. */
- u16 ul_rif_id; /* Reserved for Spectrum. */
+ u16 ul_vr_id; /* Spectrum-1. */
+ u16 ul_rif_id; /* Spectrum-2+. */
};
struct mlxsw_sp_rif_params_ipip_lb {
@@ -748,10 +772,11 @@ static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
struct mlxsw_sp_vr *vr;
int i;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_is_used(vr))
return vr;
@@ -792,12 +817,13 @@ static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
u32 tb_id)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
struct mlxsw_sp_vr *vr;
int i;
tb_id = mlxsw_sp_fix_tb_id(tb_id);
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
return vr;
@@ -959,6 +985,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib *fib,
struct mlxsw_sp_lpm_tree *new_tree)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
enum mlxsw_sp_l3proto proto = fib->proto;
struct mlxsw_sp_lpm_tree *old_tree;
u8 old_id, new_id = new_tree->id;
@@ -968,7 +995,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
old_tree = mlxsw_sp->router->lpm.proto_trees[proto];
old_id = old_tree->id;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
continue;
@@ -1052,6 +1079,61 @@ u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
return tb_id;
}
+static void
+mlxsw_sp_crif_init(struct mlxsw_sp_crif *crif, struct net_device *dev)
+{
+ crif->key.dev = dev;
+ INIT_LIST_HEAD(&crif->nexthop_list);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_alloc(struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ crif = kzalloc(sizeof(*crif), GFP_KERNEL);
+ if (!crif)
+ return NULL;
+
+ mlxsw_sp_crif_init(crif, dev);
+ return crif;
+}
+
+static void mlxsw_sp_crif_free(struct mlxsw_sp_crif *crif)
+{
+ if (WARN_ON(crif->rif))
+ return;
+
+ WARN_ON(!list_empty(&crif->nexthop_list));
+ kfree(crif);
+}
+
+static int mlxsw_sp_crif_insert(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ return rhashtable_insert_fast(&router->crif_ht, &crif->ht_node,
+ mlxsw_sp_crif_ht_params);
+}
+
+static void mlxsw_sp_crif_remove(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ rhashtable_remove_fast(&router->crif_ht, &crif->ht_node,
+ mlxsw_sp_crif_ht_params);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_lookup(struct mlxsw_sp_router *router,
+ const struct net_device *dev)
+{
+ struct mlxsw_sp_crif_key key = {
+ .dev = (struct net_device *)dev,
+ };
+
+ return rhashtable_lookup_fast(&router->crif_ht, &key,
+ mlxsw_sp_crif_ht_params);
+}
+
static struct mlxsw_sp_rif *
mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_params *params,
@@ -1557,6 +1639,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
u16 ul_rif_id, bool enable)
{
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
+ struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common);
enum mlxsw_reg_ritr_loopback_ipip_options ipip_options;
struct mlxsw_sp_rif *rif = &lb_rif->common;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
@@ -1569,7 +1652,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
case MLXSW_SP_L3_PROTO_IPV4:
saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
+ rif->rif_index, rif->vr_id, dev->mtu);
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
ipip_options, ul_vr_id,
ul_rif_id, saddr4,
@@ -1579,7 +1662,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
case MLXSW_SP_L3_PROTO_IPV6:
saddr6 = &lb_cf.saddr.addr6;
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
+ rif->rif_index, rif->vr_id, dev->mtu);
mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt,
ipip_options, ul_vr_id,
ul_rif_id, saddr6,
@@ -1639,9 +1722,29 @@ static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
}
-static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
+static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_rif *rif);
+
+static void mlxsw_sp_rif_migrate_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *old_rif,
- struct mlxsw_sp_rif *new_rif);
+ struct mlxsw_sp_rif *new_rif,
+ bool migrate_nhs)
+{
+ struct mlxsw_sp_crif *crif = old_rif->crif;
+ struct mlxsw_sp_crif mock_crif = {};
+
+ if (migrate_nhs)
+ mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
+
+ /* Plant a mock CRIF so that destroying the old RIF doesn't unoffload
+ * our nexthops and IPIP tunnels, and doesn't sever the crif->rif link.
+ */
+ mlxsw_sp_crif_init(&mock_crif, crif->key.dev);
+ old_rif->crif = &mock_crif;
+ mock_crif.rif = old_rif;
+ mlxsw_sp_rif_destroy(old_rif);
+}
+
static int
mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry,
@@ -1659,18 +1762,11 @@ mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
return PTR_ERR(new_lb_rif);
ipip_entry->ol_lb = new_lb_rif;
- if (keep_encap)
- mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common,
- &new_lb_rif->common);
-
- mlxsw_sp_rif_destroy(&old_lb_rif->common);
-
+ mlxsw_sp_rif_migrate_destroy(mlxsw_sp, &old_lb_rif->common,
+ &new_lb_rif->common, keep_encap);
return 0;
}
-static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_rif *rif);
-
/**
* __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
* @mlxsw_sp: mlxsw_sp.
@@ -2329,7 +2425,7 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
}
dipn = htonl(dip);
- dev = mlxsw_sp->router->rifs[rif]->dev;
+ dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
n = neigh_lookup(&arp_tbl, &dipn, dev);
if (!n)
return;
@@ -2357,7 +2453,7 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
return;
}
- dev = mlxsw_sp->router->rifs[rif]->dev;
+ dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
n = neigh_lookup(&nd_tbl, &dip, dev);
if (!n)
return;
@@ -2745,13 +2841,12 @@ static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
}
static int mlxsw_sp_router_schedule_work(struct net *net,
- struct notifier_block *nb,
+ struct mlxsw_sp_router *router,
+ struct neighbour *n,
void (*cb)(struct work_struct *))
{
struct mlxsw_sp_netevent_work *net_work;
- struct mlxsw_sp_router *router;
- router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
return NOTIFY_DONE;
@@ -2761,19 +2856,31 @@ static int mlxsw_sp_router_schedule_work(struct net *net,
INIT_WORK(&net_work->work, cb);
net_work->mlxsw_sp = router->mlxsw_sp;
+ net_work->n = n;
mlxsw_core_schedule_work(&net_work->work);
return NOTIFY_DONE;
}
+static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port;
+
+ rcu_read_lock();
+ mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
+ rcu_read_unlock();
+ return !!mlxsw_sp_port;
+}
+
static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
- struct mlxsw_sp_netevent_work *net_work;
- struct mlxsw_sp_port *mlxsw_sp_port;
- struct mlxsw_sp *mlxsw_sp;
+ struct mlxsw_sp_router *router;
unsigned long interval;
struct neigh_parms *p;
struct neighbour *n;
+ struct net *net;
+
+ router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
switch (event) {
case NETEVENT_DELAY_PROBE_TIME_UPDATE:
@@ -2787,51 +2894,37 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
/* We are in atomic context and can't take RTNL mutex,
* so use RCU variant to walk the device chain.
*/
- mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
- if (!mlxsw_sp_port)
+ if (!mlxsw_sp_dev_lower_is_port(p->dev))
return NOTIFY_DONE;
- mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
- mlxsw_sp->router->neighs_update.interval = interval;
-
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
+ router->neighs_update.interval = interval;
break;
case NETEVENT_NEIGH_UPDATE:
n = ptr;
+ net = neigh_parms_net(n->parms);
if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
return NOTIFY_DONE;
- mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
- if (!mlxsw_sp_port)
+ if (!mlxsw_sp_dev_lower_is_port(n->dev))
return NOTIFY_DONE;
- net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
- if (!net_work) {
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
- return NOTIFY_BAD;
- }
-
- INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work);
- net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- net_work->n = n;
-
/* Take a reference to ensure the neighbour won't be
* destructed until we drop the reference in delayed
* work.
*/
neigh_clone(n);
- mlxsw_core_schedule_work(&net_work->work);
- mlxsw_sp_port_dev_put(mlxsw_sp_port);
- break;
+ return mlxsw_sp_router_schedule_work(net, router, n,
+ mlxsw_sp_router_neigh_event_work);
+
case NETEVENT_IPV4_MPATH_HASH_UPDATE:
case NETEVENT_IPV6_MPATH_HASH_UPDATE:
- return mlxsw_sp_router_schedule_work(ptr, nb,
+ return mlxsw_sp_router_schedule_work(ptr, router, NULL,
mlxsw_sp_router_mp_hash_event_work);
case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
- return mlxsw_sp_router_schedule_work(ptr, nb,
+ return mlxsw_sp_router_schedule_work(ptr, router, NULL,
mlxsw_sp_router_update_priority_work);
}
@@ -2902,7 +2995,7 @@ struct mlxsw_sp_nexthop_key {
struct mlxsw_sp_nexthop {
struct list_head neigh_list_node; /* member of neigh entry list */
- struct list_head rif_list_node;
+ struct list_head crif_list_node;
struct list_head router_list_node;
struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group
* this nexthop belongs to
@@ -2915,7 +3008,7 @@ struct mlxsw_sp_nexthop {
int nh_weight;
int norm_nh_weight;
int num_adj_entries;
- struct mlxsw_sp_rif *rif;
+ struct mlxsw_sp_crif *crif;
u8 should_offload:1, /* set indicates this nexthop should be written
* to the adjacency table.
*/
@@ -2935,6 +3028,14 @@ struct mlxsw_sp_nexthop {
bool counter_valid;
};
+static struct net_device *
+mlxsw_sp_nexthop_dev(const struct mlxsw_sp_nexthop *nh)
+{
+ if (!nh->crif)
+ return NULL;
+ return nh->crif->key.dev;
+}
+
enum mlxsw_sp_nexthop_group_type {
MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4,
MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6,
@@ -2952,9 +3053,18 @@ struct mlxsw_sp_nexthop_group_info {
is_resilient:1;
struct list_head list; /* member in nh_res_grp_list */
struct mlxsw_sp_nexthop nexthops[];
-#define nh_rif nexthops[0].rif
};
+static struct mlxsw_sp_rif *
+mlxsw_sp_nhgi_rif(const struct mlxsw_sp_nexthop_group_info *nhgi)
+{
+ struct mlxsw_sp_crif *crif = nhgi->nexthops[0].crif;
+
+ if (!crif)
+ return NULL;
+ return crif->rif;
+}
+
struct mlxsw_sp_nexthop_group_vr_key {
u16 vr_id;
enum mlxsw_sp_l3proto proto;
@@ -3076,7 +3186,9 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
{
- return nh->rif;
+ if (WARN_ON(!nh->crif))
+ return NULL;
+ return nh->crif->rif;
}
bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
@@ -3461,11 +3573,12 @@ static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp,
bool force, char *ratr_pl)
{
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
+ struct mlxsw_sp_rif *rif = mlxsw_sp_nexthop_rif(nh);
enum mlxsw_reg_ratr_op op;
u16 rif_index;
- rif_index = nh->rif ? nh->rif->rif_index :
- mlxsw_sp->router->lb_rif_index;
+ rif_index = rif ? rif->rif_index :
+ mlxsw_sp->router->lb_crif->rif->rif_index;
op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET,
@@ -4008,16 +4121,18 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
{
struct neighbour *n, *old_n = neigh_entry->key.n;
struct mlxsw_sp_nexthop *nh;
+ struct net_device *dev;
bool entry_connected;
u8 nud_state, dead;
int err;
nh = list_first_entry(&neigh_entry->nexthop_list,
struct mlxsw_sp_nexthop, neigh_list_node);
+ dev = mlxsw_sp_nexthop_dev(nh);
- n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
if (!n) {
- n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
if (IS_ERR(n))
return PTR_ERR(n);
neigh_event_send(n, NULL);
@@ -4081,44 +4196,49 @@ mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
}
}
-static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
- struct mlxsw_sp_rif *rif)
+static void mlxsw_sp_nexthop_crif_init(struct mlxsw_sp_nexthop *nh,
+ struct mlxsw_sp_crif *crif)
{
- if (nh->rif)
+ if (nh->crif)
return;
- nh->rif = rif;
- list_add(&nh->rif_list_node, &rif->nexthop_list);
+ nh->crif = crif;
+ list_add(&nh->crif_list_node, &crif->nexthop_list);
}
-static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
+static void mlxsw_sp_nexthop_crif_fini(struct mlxsw_sp_nexthop *nh)
{
- if (!nh->rif)
+ if (!nh->crif)
return;
- list_del(&nh->rif_list_node);
- nh->rif = NULL;
+ list_del(&nh->crif_list_node);
+ nh->crif = NULL;
}
static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
struct mlxsw_sp_neigh_entry *neigh_entry;
+ struct net_device *dev;
struct neighbour *n;
u8 nud_state, dead;
int err;
+ if (WARN_ON(!nh->crif->rif))
+ return 0;
+
if (!nh->nhgi->gateway || nh->neigh_entry)
return 0;
+ dev = mlxsw_sp_nexthop_dev(nh);
/* Take a reference of neigh here ensuring that neigh would
* not be destructed before the nexthop entry is finished.
* The reference is taken either in neigh_lookup() or
* in neigh_create() in case n is not found.
*/
- n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, dev);
if (!n) {
- n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
+ n = neigh_create(nh->neigh_tbl, &nh->gw_addr, dev);
if (IS_ERR(n))
return PTR_ERR(n);
neigh_event_send(n, NULL);
@@ -4197,15 +4317,20 @@ static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh,
struct mlxsw_sp_ipip_entry *ipip_entry)
{
+ struct mlxsw_sp_crif *crif;
bool removing;
if (!nh->nhgi->gateway || nh->ipip_entry)
return;
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, ipip_entry->ol_dev);
+ if (WARN_ON(!crif))
+ return;
+
nh->ipip_entry = ipip_entry;
removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
__mlxsw_sp_nexthop_neigh_update(nh, removing);
- mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common);
+ mlxsw_sp_nexthop_crif_init(nh, crif);
}
static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
@@ -4237,7 +4362,7 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
{
const struct mlxsw_sp_ipip_ops *ipip_ops;
struct mlxsw_sp_ipip_entry *ipip_entry;
- struct mlxsw_sp_rif *rif;
+ struct mlxsw_sp_crif *crif;
int err;
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
@@ -4251,11 +4376,15 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
}
nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
- rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
- if (!rif)
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, dev);
+ if (!crif)
+ return 0;
+
+ mlxsw_sp_nexthop_crif_init(nh, crif);
+
+ if (!crif->rif)
return 0;
- mlxsw_sp_nexthop_rif_init(nh, rif);
err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
if (err)
goto err_neigh_init;
@@ -4263,25 +4392,30 @@ static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
return 0;
err_neigh_init:
- mlxsw_sp_nexthop_rif_fini(nh);
+ mlxsw_sp_nexthop_crif_fini(nh);
return err;
}
-static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_nexthop *nh)
+static void mlxsw_sp_nexthop_type_rif_gone(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_nexthop *nh)
{
switch (nh->type) {
case MLXSW_SP_NEXTHOP_TYPE_ETH:
mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
- mlxsw_sp_nexthop_rif_fini(nh);
break;
case MLXSW_SP_NEXTHOP_TYPE_IPIP:
- mlxsw_sp_nexthop_rif_fini(nh);
mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
break;
}
}
+static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_nexthop *nh)
+{
+ mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
+ mlxsw_sp_nexthop_crif_fini(nh);
+}
+
static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop_group *nh_grp,
struct mlxsw_sp_nexthop *nh,
@@ -4368,16 +4502,17 @@ static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_nexthop *nh;
bool removing;
- list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
+ list_for_each_entry(nh, &rif->crif->nexthop_list, crif_list_node) {
switch (nh->type) {
case MLXSW_SP_NEXTHOP_TYPE_ETH:
removing = false;
break;
case MLXSW_SP_NEXTHOP_TYPE_IPIP:
- removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev);
+ removing = !mlxsw_sp_ipip_netdev_ul_up(dev);
break;
default:
WARN_ON(1);
@@ -4389,25 +4524,14 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
}
}
-static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_rif *old_rif,
- struct mlxsw_sp_rif *new_rif)
-{
- struct mlxsw_sp_nexthop *nh;
-
- list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
- list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
- nh->rif = new_rif;
- mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
-}
-
static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
struct mlxsw_sp_nexthop *nh, *tmp;
- list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
- mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
+ list_for_each_entry_safe(nh, tmp, &rif->crif->nexthop_list,
+ crif_list_node) {
+ mlxsw_sp_nexthop_type_rif_gone(mlxsw_sp, nh);
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
}
}
@@ -4427,7 +4551,7 @@ static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp)
mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
MLXSW_REG_RATR_TYPE_ETHERNET,
mlxsw_sp->router->adj_trap_index,
- mlxsw_sp->router->lb_rif_index);
+ mlxsw_sp->router->lb_crif->rif->rif_index);
mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
@@ -4743,21 +4867,19 @@ static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
- u16 lb_rif_index = mlxsw_sp->router->lb_rif_index;
-
nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD;
nh->should_offload = 1;
/* While nexthops that discard packets do not forward packets
* via an egress RIF, they still need to be programmed using a
* valid RIF, so use the loopback RIF created during init.
*/
- nh->rif = mlxsw_sp->router->rifs[lb_rif_index];
+ nh->crif = mlxsw_sp->router->lb_crif;
}
static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
- nh->rif = NULL;
+ nh->crif = NULL;
nh->should_offload = 0;
}
@@ -5491,7 +5613,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
return !!nh_group->nhgi->adj_index_valid;
case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
- return !!nh_group->nhgi->nh_rif;
+ return !!mlxsw_sp_nhgi_rif(nh_group->nhgi);
case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
@@ -5509,9 +5631,10 @@ mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
for (i = 0; i < nh_grp->nhgi->count; i++) {
struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
+ struct net_device *dev = mlxsw_sp_nexthop_dev(nh);
struct fib6_info *rt = mlxsw_sp_rt6->rt;
- if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
+ if (dev && dev == rt->fib6_nh->fib_nh_dev &&
ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
&rt->fib6_nh->fib_nh_gw6))
return nh;
@@ -5752,7 +5875,8 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
adjacency_index = nhgi->adj_index;
ecmp_size = nhgi->ecmp_size;
- } else if (!nhgi->adj_index_valid && nhgi->count && nhgi->nh_rif) {
+ } else if (!nhgi->adj_index_valid && nhgi->count &&
+ mlxsw_sp_nhgi_rif(nhgi)) {
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
adjacency_index = mlxsw_sp->router->adj_trap_index;
ecmp_size = 1;
@@ -5771,7 +5895,7 @@ static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry,
enum mlxsw_reg_ralue_op op)
{
- struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif;
+ struct mlxsw_sp_rif *rif = mlxsw_sp_nhgi_rif(fib_entry->nh_group->nhgi);
enum mlxsw_reg_ralue_trap_action trap_action;
char ralue_pl[MLXSW_REG_RALUE_LEN];
u16 trap_id = 0;
@@ -7298,9 +7422,10 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
{
+ int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
int i, j;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
+ for (i = 0; i < max_vrs; i++) {
struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
if (!mlxsw_sp_vr_is_used(vr))
@@ -7699,11 +7824,12 @@ static struct mlxsw_sp_rif *
mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
const struct net_device *dev)
{
+ int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
int i;
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
+ for (i = 0; i < max_rifs; i++)
if (mlxsw_sp->router->rifs[i] &&
- mlxsw_sp->router->rifs[i]->dev == dev)
+ mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev))
return mlxsw_sp->router->rifs[i];
return NULL;
@@ -7761,33 +7887,52 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif)
{
+ /* Signal to nexthop cleanup that the RIF is going away. */
+ rif->crif->rif = NULL;
+
mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
}
+static bool __mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
+{
+ struct inet6_dev *inet6_dev;
+ struct in_device *idev;
+
+ idev = __in_dev_get_rcu(dev);
+ if (idev && idev->ifa_list)
+ return false;
+
+ inet6_dev = __in6_dev_get(dev);
+ if (inet6_dev && !list_empty(&inet6_dev->addr_list))
+ return false;
+
+ return true;
+}
+
+static bool mlxsw_sp_dev_addr_list_empty(const struct net_device *dev)
+{
+ bool addr_list_empty;
+
+ rcu_read_lock();
+ addr_list_empty = __mlxsw_sp_dev_addr_list_empty(dev);
+ rcu_read_unlock();
+
+ return addr_list_empty;
+}
+
static bool
mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
unsigned long event)
{
- struct inet6_dev *inet6_dev;
- bool addr_list_empty = true;
- struct in_device *idev;
+ bool addr_list_empty;
switch (event) {
case NETDEV_UP:
return rif == NULL;
case NETDEV_DOWN:
- rcu_read_lock();
- idev = __in_dev_get_rcu(dev);
- if (idev && idev->ifa_list)
- addr_list_empty = false;
-
- inet6_dev = __in6_dev_get(dev);
- if (addr_list_empty && inet6_dev &&
- !list_empty(&inet6_dev->addr_list))
- addr_list_empty = false;
- rcu_read_unlock();
+ addr_list_empty = mlxsw_sp_dev_addr_list_empty(dev);
/* macvlans do not have a RIF, but rather piggy back on the
* RIF of their lower device.
@@ -7796,7 +7941,7 @@ mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
return true;
if (rif && addr_list_empty &&
- !netif_is_l3_slave(rif->dev))
+ !netif_is_l3_slave(mlxsw_sp_rif_dev(rif)))
return true;
/* It is possible we already removed the RIF ourselves
* if it was assigned to a netdev that is now a bridge
@@ -7854,27 +7999,39 @@ static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
u16 vr_id,
- struct net_device *l3_dev)
+ struct mlxsw_sp_crif *crif)
{
+ struct net_device *l3_dev = crif ? crif->key.dev : NULL;
struct mlxsw_sp_rif *rif;
rif = kzalloc(rif_size, GFP_KERNEL);
if (!rif)
return NULL;
- INIT_LIST_HEAD(&rif->nexthop_list);
INIT_LIST_HEAD(&rif->neigh_list);
if (l3_dev) {
ether_addr_copy(rif->addr, l3_dev->dev_addr);
rif->mtu = l3_dev->mtu;
- rif->dev = l3_dev;
}
rif->vr_id = vr_id;
rif->rif_index = rif_index;
+ if (crif) {
+ rif->crif = crif;
+ crif->rif = rif;
+ }
return rif;
}
+static void mlxsw_sp_rif_free(struct mlxsw_sp_rif *rif)
+{
+ WARN_ON(!list_empty(&rif->neigh_list));
+
+ if (rif->crif)
+ rif->crif->rif = NULL;
+ kfree(rif);
+}
+
struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
u16 rif_index)
{
@@ -7893,7 +8050,8 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
{
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(&lb_rif->common);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp_vr *ul_vr;
ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL);
@@ -8070,12 +8228,18 @@ mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev)
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
{
- return rif->dev->ifindex;
+ return mlxsw_sp_rif_dev(rif)->ifindex;
}
-const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
+bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif)
+{
+ return !!mlxsw_sp_rif_dev(rif);
+}
+
+bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
+ const struct net_device *dev)
{
- return rif->dev;
+ return mlxsw_sp_rif_dev(rif) == dev;
}
static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
@@ -8083,7 +8247,7 @@ static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
struct rtnl_hw_stats64 stats = {};
if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats))
- netdev_offload_xstats_push_delta(rif->dev,
+ netdev_offload_xstats_push_delta(mlxsw_sp_rif_dev(rif),
NETDEV_OFFLOAD_XSTATS_TYPE_L3,
&stats);
}
@@ -8098,6 +8262,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_rif_ops *ops;
struct mlxsw_sp_fid *fid = NULL;
enum mlxsw_sp_rif_type type;
+ struct mlxsw_sp_crif *crif;
struct mlxsw_sp_rif *rif;
struct mlxsw_sp_vr *vr;
u16 rif_index;
@@ -8117,12 +8282,18 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
goto err_rif_index_alloc;
}
- rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
+ crif = mlxsw_sp_crif_lookup(mlxsw_sp->router, params->dev);
+ if (WARN_ON(!crif)) {
+ err = -ENOENT;
+ goto err_crif_lookup;
+ }
+
+ rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, crif);
if (!rif) {
err = -ENOMEM;
goto err_rif_alloc;
}
- dev_hold(rif->dev);
+ dev_hold(params->dev);
mlxsw_sp->router->rifs[rif_index] = rif;
rif->mlxsw_sp = mlxsw_sp;
rif->ops = ops;
@@ -8150,12 +8321,12 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
goto err_mr_rif_add;
}
- if (netdev_offload_xstats_enabled(rif->dev,
+ if (netdev_offload_xstats_enabled(params->dev,
NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
err = mlxsw_sp_router_port_l3_stats_enable(rif);
if (err)
goto err_stats_enable;
- mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
+ mlxsw_sp_router_hwstats_notify_schedule(params->dev);
} else {
mlxsw_sp_rif_counters_alloc(rif);
}
@@ -8173,9 +8344,10 @@ err_configure:
mlxsw_sp_fid_put(fid);
err_fid_get:
mlxsw_sp->router->rifs[rif_index] = NULL;
- dev_put(rif->dev);
- kfree(rif);
+ dev_put(params->dev);
+ mlxsw_sp_rif_free(rif);
err_rif_alloc:
+err_crif_lookup:
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
err_rif_index_alloc:
vr->rif_count--;
@@ -8185,8 +8357,10 @@ err_rif_index_alloc:
static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
const struct mlxsw_sp_rif_ops *ops = rif->ops;
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
+ struct mlxsw_sp_crif *crif = rif->crif;
struct mlxsw_sp_fid *fid = rif->fid;
u8 rif_entries = rif->rif_entries;
u16 rif_index = rif->rif_index;
@@ -8197,11 +8371,10 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
vr = &mlxsw_sp->router->vrs[rif->vr_id];
- if (netdev_offload_xstats_enabled(rif->dev,
- NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
+ if (netdev_offload_xstats_enabled(dev, NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
mlxsw_sp_rif_push_l3_stats(rif);
mlxsw_sp_router_port_l3_stats_disable(rif);
- mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
+ mlxsw_sp_router_hwstats_notify_schedule(dev);
} else {
mlxsw_sp_rif_counters_free(rif);
}
@@ -8213,11 +8386,14 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
/* Loopback RIFs are not associated with a FID. */
mlxsw_sp_fid_put(fid);
mlxsw_sp->router->rifs[rif->rif_index] = NULL;
- dev_put(rif->dev);
- kfree(rif);
+ dev_put(dev);
+ mlxsw_sp_rif_free(rif);
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
vr->rif_count--;
mlxsw_sp_vr_put(mlxsw_sp, vr);
+
+ if (crif->can_destroy)
+ mlxsw_sp_crif_free(crif);
}
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
@@ -8549,25 +8725,20 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
mlxsw_sp_rif_subport_put(rif);
}
-int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev,
- struct netlink_ext_ack *extack)
+static int
+mlxsw_sp_port_vlan_router_join_existing(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
- struct mlxsw_sp_rif *rif;
- int err = 0;
- mutex_lock(&mlxsw_sp->router->lock);
- rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
- if (!rif)
- goto out;
+ lockdep_assert_held(&mlxsw_sp->router->lock);
- err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
- extack);
-out:
- mutex_unlock(&mlxsw_sp->router->lock);
- return err;
+ if (!mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev))
+ return 0;
+
+ return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
+ extack);
}
void
@@ -8874,8 +9045,8 @@ out:
return notifier_from_errno(err);
}
-int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr)
+static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
{
struct in_validator_info *ivi = (struct in_validator_info *) ptr;
struct net_device *dev = ivi->ivi_dev->dev;
@@ -8957,8 +9128,8 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
return NOTIFY_DONE;
}
-int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
- unsigned long event, void *ptr)
+static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
{
struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
struct net_device *dev = i6vi->i6vi_dev->dev;
@@ -9004,7 +9175,7 @@ mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
- struct net_device *dev = rif->dev;
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u8 old_mac_profile;
u16 fid_index;
int err;
@@ -9088,6 +9259,104 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
return -ENOBUFS;
}
+static bool mlxsw_sp_router_netdevice_interesting(struct mlxsw_sp *mlxsw_sp,
+ struct net_device *dev)
+{
+ struct vlan_dev_priv *vlan;
+
+ if (netif_is_lag_master(dev) ||
+ netif_is_bridge_master(dev) ||
+ mlxsw_sp_port_dev_check(dev) ||
+ mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev) ||
+ netif_is_l3_master(dev))
+ return true;
+
+ if (!is_vlan_dev(dev))
+ return false;
+
+ vlan = vlan_dev_priv(dev);
+ return netif_is_lag_master(vlan->real_dev) ||
+ netif_is_bridge_master(vlan->real_dev) ||
+ mlxsw_sp_port_dev_check(vlan->real_dev);
+}
+
+static struct mlxsw_sp_crif *
+mlxsw_sp_crif_register(struct mlxsw_sp_router *router, struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+ int err;
+
+ if (WARN_ON(mlxsw_sp_crif_lookup(router, dev)))
+ return NULL;
+
+ crif = mlxsw_sp_crif_alloc(dev);
+ if (!crif)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlxsw_sp_crif_insert(router, crif);
+ if (err)
+ goto err_netdev_insert;
+
+ return crif;
+
+err_netdev_insert:
+ mlxsw_sp_crif_free(crif);
+ return ERR_PTR(err);
+}
+
+static void mlxsw_sp_crif_unregister(struct mlxsw_sp_router *router,
+ struct mlxsw_sp_crif *crif)
+{
+ struct mlxsw_sp_nexthop *nh, *tmp;
+
+ mlxsw_sp_crif_remove(router, crif);
+
+ list_for_each_entry_safe(nh, tmp, &crif->nexthop_list, crif_list_node)
+ mlxsw_sp_nexthop_type_fini(router->mlxsw_sp, nh);
+
+ if (crif->rif)
+ crif->can_destroy = true;
+ else
+ mlxsw_sp_crif_free(crif);
+}
+
+static int mlxsw_sp_netdevice_register(struct mlxsw_sp_router *router,
+ struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
+ return 0;
+
+ crif = mlxsw_sp_crif_register(router, dev);
+ return PTR_ERR_OR_ZERO(crif);
+}
+
+static void mlxsw_sp_netdevice_unregister(struct mlxsw_sp_router *router,
+ struct net_device *dev)
+{
+ struct mlxsw_sp_crif *crif;
+
+ if (!mlxsw_sp_router_netdevice_interesting(router->mlxsw_sp, dev))
+ return;
+
+ /* netdev_run_todo(), by way of netdev_wait_allrefs_any(), rebroadcasts
+ * the NETDEV_UNREGISTER message, so we can get here twice. If that's
+ * what happened, the netdevice state is NETREG_UNREGISTERED. In that
+ * case, we expect to have collected the CRIF already, and warn if it
+ * still exists. Otherwise we expect the CRIF to exist.
+ */
+ crif = mlxsw_sp_crif_lookup(router, dev);
+ if (dev->reg_state == NETREG_UNREGISTERED) {
+ if (!WARN_ON(crif))
+ return;
+ }
+ if (WARN_ON(!crif))
+ return;
+
+ mlxsw_sp_crif_unregister(router, crif);
+}
+
static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
{
switch (event) {
@@ -9254,6 +9523,46 @@ mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
return err;
}
+static int
+mlxsw_sp_port_vid_router_join_existing(struct mlxsw_sp_port *mlxsw_sp_port,
+ u16 vid, struct net_device *dev,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
+
+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port,
+ vid);
+ if (WARN_ON(!mlxsw_sp_port_vlan))
+ return -EINVAL;
+
+ return mlxsw_sp_port_vlan_router_join_existing(mlxsw_sp_port_vlan,
+ dev, extack);
+}
+
+static int __mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
+{
+ u16 default_vid = MLXSW_SP_DEFAULT_VID;
+
+ return mlxsw_sp_port_vid_router_join_existing(mlxsw_sp_port,
+ default_vid, lag_dev,
+ extack);
+}
+
+int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
+{
+ int err;
+
+ mutex_lock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+ err = __mlxsw_sp_router_port_join_lag(mlxsw_sp_port, lag_dev, extack);
+ mutex_unlock(&mlxsw_sp_port->mlxsw_sp->router->lock);
+
+ return err;
+}
+
static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
@@ -9267,6 +9576,15 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
mutex_lock(&mlxsw_sp->router->lock);
+ if (event == NETDEV_REGISTER) {
+ err = mlxsw_sp_netdevice_register(router, dev);
+ if (err)
+ /* No need to roll this back, UNREGISTER will collect it
+ * anyhow.
+ */
+ goto out;
+ }
+
if (mlxsw_sp_is_offload_xstats_event(event))
err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
event, ptr);
@@ -9281,6 +9599,10 @@ static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
else if (mlxsw_sp_is_vrf_event(event, ptr))
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
+ if (event == NETDEV_UNREGISTER)
+ mlxsw_sp_netdevice_unregister(router, dev);
+
+out:
mutex_unlock(&mlxsw_sp->router->lock);
return notifier_from_errno(err);
@@ -9300,15 +9622,16 @@ static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct netdev_nested_priv priv = {
.data = (void *)rif,
};
- if (!netif_is_macvlan_port(rif->dev))
+ if (!netif_is_macvlan_port(dev))
return 0;
- netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n");
- return netdev_walk_all_upper_dev_rcu(rif->dev,
+ netdev_warn(dev, "Router interface is deleted. Upper macvlans will not work\n");
+ return netdev_walk_all_upper_dev_rcu(dev,
__mlxsw_sp_rif_macvlan_flush, &priv);
}
@@ -9329,6 +9652,7 @@ static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_rif_subport *rif_subport;
char ritr_pl[MLXSW_REG_RITR_LEN];
@@ -9336,8 +9660,8 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
rif_subport = mlxsw_sp_rif_subport_rif(rif);
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
- rif->rif_index, rif->vr_id, rif->dev->mtu);
- mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
+ rif->rif_index, rif->vr_id, dev->mtu);
+ mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
efid = mlxsw_sp_fid_index(rif->fid);
mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
@@ -9350,6 +9674,7 @@ static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u8 mac_profile;
int err;
@@ -9363,7 +9688,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
if (err)
goto err_rif_subport_op;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9375,7 +9700,7 @@ static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_rif_subport_op(rif, false);
@@ -9386,10 +9711,11 @@ err_rif_subport_op:
static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp_fid *fid = rif->fid;
mlxsw_sp_fid_rif_unset(fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_rif_subport_op(rif, false);
@@ -9415,12 +9741,13 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable)
{
enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF;
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
- rif->dev->mtu);
- mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
+ dev->mtu);
+ mlxsw_reg_ritr_mac_pack(ritr_pl, dev->dev_addr);
mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid);
@@ -9435,6 +9762,7 @@ u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
u16 fid_index = mlxsw_sp_fid_index(rif->fid);
u8 mac_profile;
@@ -9460,7 +9788,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
if (err)
goto err_fid_bc_flood_set;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9472,7 +9800,7 @@ static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9489,12 +9817,13 @@ err_rif_fid_op:
static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 fid_index = mlxsw_sp_fid_index(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_fid *fid = rif->fid;
mlxsw_sp_fid_rif_unset(fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9509,7 +9838,9 @@ static struct mlxsw_sp_fid *
mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
- return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
+ int rif_ifindex = mlxsw_sp_rif_dev_ifindex(rif);
+
+ return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif_ifindex);
}
static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
@@ -9517,7 +9848,7 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
struct switchdev_notifier_fdb_info info = {};
struct net_device *dev;
- dev = br_fdb_find_port(rif->dev, mac, 0);
+ dev = br_fdb_find_port(mlxsw_sp_rif_dev(rif), mac, 0);
if (!dev)
return;
@@ -9540,17 +9871,18 @@ static struct mlxsw_sp_fid *
mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct net_device *br_dev;
u16 vid;
int err;
- if (is_vlan_dev(rif->dev)) {
- vid = vlan_dev_vlan_id(rif->dev);
- br_dev = vlan_dev_real_dev(rif->dev);
+ if (is_vlan_dev(dev)) {
+ vid = vlan_dev_vlan_id(dev);
+ br_dev = vlan_dev_real_dev(dev);
if (WARN_ON(!netif_is_bridge_master(br_dev)))
return ERR_PTR(-EINVAL);
} else {
- err = br_vlan_get_pvid(rif->dev, &vid);
+ err = br_vlan_get_pvid(dev, &vid);
if (err < 0 || !vid) {
NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID");
return ERR_PTR(-EINVAL);
@@ -9562,12 +9894,13 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
{
+ struct net_device *rif_dev = mlxsw_sp_rif_dev(rif);
struct switchdev_notifier_fdb_info info = {};
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct net_device *br_dev;
struct net_device *dev;
- br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev;
+ br_dev = is_vlan_dev(rif_dev) ? vlan_dev_real_dev(rif_dev) : rif_dev;
dev = br_fdb_find_port(br_dev, mac, vid);
if (!dev)
return;
@@ -9581,11 +9914,12 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
bool enable)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
char ritr_pl[MLXSW_REG_RITR_LEN];
mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id,
- rif->dev->mtu, rif->dev->dev_addr,
+ dev->mtu, dev->dev_addr,
rif->mac_profile_id, vid, efid);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
@@ -9594,6 +9928,7 @@ static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
struct netlink_ext_ack *extack)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
u8 mac_profile;
@@ -9619,7 +9954,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
if (err)
goto err_fid_bc_flood_set;
- err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), true);
if (err)
goto err_rif_fdb_op;
@@ -9631,7 +9966,7 @@ static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
return 0;
err_fid_rif_set:
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
err_rif_fdb_op:
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9648,11 +9983,12 @@ err_rif_vlan_fid_op:
static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
{
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
mlxsw_sp_fid_rif_unset(rif->fid);
- mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
+ mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
mlxsw_sp_rif_macvlan_flush(rif);
mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
@@ -9719,12 +10055,13 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_vr *ul_vr;
int err;
- ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, extack);
if (IS_ERR(ul_vr))
return PTR_ERR(ul_vr);
@@ -9786,6 +10123,7 @@ mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
static struct mlxsw_sp_rif *
mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
+ struct mlxsw_sp_crif *ul_crif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif *ul_rif;
@@ -9799,7 +10137,8 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
return ERR_PTR(err);
}
- ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
+ ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id,
+ ul_crif);
if (!ul_rif) {
err = -ENOMEM;
goto err_rif_alloc;
@@ -9817,7 +10156,7 @@ mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
ul_rif_op_err:
mlxsw_sp->router->rifs[rif_index] = NULL;
- kfree(ul_rif);
+ mlxsw_sp_rif_free(ul_rif);
err_rif_alloc:
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
return ERR_PTR(err);
@@ -9832,12 +10171,13 @@ static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
- kfree(ul_rif);
+ mlxsw_sp_rif_free(ul_rif);
mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
}
static struct mlxsw_sp_rif *
mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
+ struct mlxsw_sp_crif *ul_crif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_vr *vr;
@@ -9850,7 +10190,7 @@ mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
return vr->ul_rif;
- vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
+ vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, ul_crif, extack);
if (IS_ERR(vr->ul_rif)) {
err = PTR_ERR(vr->ul_rif);
goto err_ul_rif_create;
@@ -9888,7 +10228,7 @@ int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
int err = 0;
mutex_lock(&mlxsw_sp->router->lock);
- ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, NULL);
if (IS_ERR(ul_rif)) {
err = PTR_ERR(ul_rif);
goto out;
@@ -9918,12 +10258,13 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
- u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
+ struct net_device *dev = mlxsw_sp_rif_dev(rif);
+ u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(dev);
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_rif *ul_rif;
int err;
- ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
+ ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL, extack);
if (IS_ERR(ul_rif))
return PTR_ERR(ul_rif);
@@ -10041,11 +10382,12 @@ err_rifs_table_init:
static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
{
+ int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
int i;
WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count));
- for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
+ for (i = 0; i < max_rifs; i++)
WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS);
@@ -10444,28 +10786,41 @@ static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
}
-static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp)
+static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp,
+ struct netlink_ext_ack *extack)
{
- u16 lb_rif_index;
+ struct mlxsw_sp_router *router = mlxsw_sp->router;
+ struct mlxsw_sp_rif *lb_rif;
int err;
+ router->lb_crif = mlxsw_sp_crif_alloc(NULL);
+ if (!router->lb_crif)
+ return -ENOMEM;
+
/* Create a generic loopback RIF associated with the main table
* (default VRF). Any table can be used, but the main table exists
- * anyway, so we do not waste resources.
+ * anyway, so we do not waste resources. Loopback RIFs are usually
+ * created with a NULL CRIF, but this RIF is used as a fallback RIF
+ * for blackhole nexthops, and nexthops expect to have a valid CRIF.
*/
- err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN,
- &lb_rif_index);
- if (err)
- return err;
-
- mlxsw_sp->router->lb_rif_index = lb_rif_index;
+ lb_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN, router->lb_crif,
+ extack);
+ if (IS_ERR(lb_rif)) {
+ err = PTR_ERR(lb_rif);
+ goto err_ul_rif_get;
+ }
return 0;
+
+err_ul_rif_get:
+ mlxsw_sp_crif_free(router->lb_crif);
+ return err;
}
static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp)
{
- mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->router->lb_rif_index);
+ mlxsw_sp_ul_rif_put(mlxsw_sp->router->lb_crif->rif);
+ mlxsw_sp_crif_free(mlxsw_sp->router->lb_crif);
}
static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp)
@@ -10504,6 +10859,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_router *router;
+ struct notifier_block *nb;
int err;
router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
@@ -10525,14 +10881,19 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_router_init;
- err = mlxsw_sp_rifs_init(mlxsw_sp);
- if (err)
- goto err_rifs_init;
-
err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp);
if (err)
goto err_ipips_init;
+ err = rhashtable_init(&mlxsw_sp->router->crif_ht,
+ &mlxsw_sp_crif_ht_params);
+ if (err)
+ goto err_crif_ht_init;
+
+ err = mlxsw_sp_rifs_init(mlxsw_sp);
+ if (err)
+ goto err_rifs_init;
+
err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
&mlxsw_sp_nexthop_ht_params);
if (err)
@@ -10556,7 +10917,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_vrs_init;
- err = mlxsw_sp_lb_rif_init(mlxsw_sp);
+ err = mlxsw_sp_lb_rif_init(mlxsw_sp, extack);
if (err)
goto err_lb_rif_init;
@@ -10582,6 +10943,17 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_register_inet6addr_notifier;
+ router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event;
+ err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+ if (err)
+ goto err_register_inetaddr_valid_notifier;
+
+ nb = &router->inet6addr_valid_nb;
+ nb->notifier_call = mlxsw_sp_inet6addr_valid_event;
+ err = register_inet6addr_validator_notifier(nb);
+ if (err)
+ goto err_register_inet6addr_valid_notifier;
+
mlxsw_sp->router->netevent_nb.notifier_call =
mlxsw_sp_router_netevent_event;
err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
@@ -10621,6 +10993,10 @@ err_register_fib_notifier:
err_register_nexthop_notifier:
unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
err_register_netevent_notifier:
+ unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
+err_register_inet6addr_valid_notifier:
+ unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+err_register_inetaddr_valid_notifier:
unregister_inet6addr_notifier(&router->inet6addr_nb);
err_register_inet6addr_notifier:
unregister_inetaddr_notifier(&router->inetaddr_nb);
@@ -10643,10 +11019,12 @@ err_lpm_init:
err_nexthop_group_ht_init:
rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
err_nexthop_ht_init:
- mlxsw_sp_ipips_fini(mlxsw_sp);
-err_ipips_init:
mlxsw_sp_rifs_fini(mlxsw_sp);
err_rifs_init:
+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
+err_crif_ht_init:
+ mlxsw_sp_ipips_fini(mlxsw_sp);
+err_ipips_init:
__mlxsw_sp_router_fini(mlxsw_sp);
err_router_init:
cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
@@ -10658,15 +11036,18 @@ err_router_ops_init:
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
{
+ struct mlxsw_sp_router *router = mlxsw_sp->router;
+
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->netdevice_nb);
- unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->fib_nb);
+ &router->netdevice_nb);
+ unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb);
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
- &mlxsw_sp->router->nexthop_nb);
- unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
- unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
- unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
+ &router->nexthop_nb);
+ unregister_netevent_notifier(&router->netevent_nb);
+ unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb);
+ unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
+ unregister_inet6addr_notifier(&router->inet6addr_nb);
+ unregister_inetaddr_notifier(&router->inetaddr_nb);
mlxsw_core_flush_owq();
mlxsw_sp_mp_hash_fini(mlxsw_sp);
mlxsw_sp_neigh_fini(mlxsw_sp);
@@ -10674,12 +11055,13 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_vrs_fini(mlxsw_sp);
mlxsw_sp_mr_fini(mlxsw_sp);
mlxsw_sp_lpm_fini(mlxsw_sp);
- rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
- rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
- mlxsw_sp_ipips_fini(mlxsw_sp);
+ rhashtable_destroy(&router->nexthop_group_ht);
+ rhashtable_destroy(&router->nexthop_ht);
mlxsw_sp_rifs_fini(mlxsw_sp);
+ rhashtable_destroy(&mlxsw_sp->router->crif_ht);
+ mlxsw_sp_ipips_fini(mlxsw_sp);
__mlxsw_sp_router_fini(mlxsw_sp);
- cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
- mutex_destroy(&mlxsw_sp->router->lock);
- kfree(mlxsw_sp->router);
+ cancel_delayed_work_sync(&router->nh_grp_activity_dw);
+ mutex_destroy(&router->lock);
+ kfree(router);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 37d6e4c80e6a..9a2669a08480 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -20,6 +20,7 @@ struct mlxsw_sp_router_nve_decap {
struct mlxsw_sp_router {
struct mlxsw_sp *mlxsw_sp;
+ struct rhashtable crif_ht;
struct gen_pool *rifs_table;
struct mlxsw_sp_rif **rifs;
struct idr rif_mac_profiles_idr;
@@ -52,12 +53,14 @@ struct mlxsw_sp_router {
struct notifier_block inetaddr_nb;
struct notifier_block inet6addr_nb;
struct notifier_block netdevice_nb;
+ struct notifier_block inetaddr_valid_nb;
+ struct notifier_block inet6addr_valid_nb;
const struct mlxsw_sp_rif_ops **rif_ops_arr;
const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
struct mlxsw_sp_router_nve_decap nve_decap_config;
struct mutex lock; /* Protects shared router resources */
struct mlxsw_sp_fib_entry_op_ctx *ll_op_ctx;
- u16 lb_rif_index;
+ struct mlxsw_sp_crif *lb_crif;
const struct mlxsw_sp_adj_grp_size_range *adj_grp_size_ranges;
size_t adj_grp_size_ranges_count;
struct delayed_work nh_grp_activity_dw;
@@ -91,7 +94,9 @@ u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif);
u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif);
u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev);
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif);
-const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif);
+bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif);
+bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif,
+ const struct net_device *dev);
int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif,
enum mlxsw_sp_rif_counter_dir dir,
@@ -166,5 +171,8 @@ int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp);
struct net_device *
mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev);
+int mlxsw_sp_router_port_join_lag(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack);
#endif /* _MLXSW_ROUTER_H_*/
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index 24c994baad13..329e374b9539 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -46,7 +46,7 @@ config LAN743X
tristate "LAN743x support"
depends on PCI
depends on PTP_1588_CLOCK_OPTIONAL
- select PHYLIB
+ select FIXED_PHY
select CRC16
select CRC32
help
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index 176efbeae127..d6c9491537e4 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -58,7 +58,6 @@ struct enc28j60_net {
struct mutex lock;
struct sk_buff *tx_skb;
struct work_struct tx_work;
- struct work_struct irq_work;
struct work_struct setrx_work;
struct work_struct restart_work;
u8 bank; /* current register bank selected */
@@ -1118,10 +1117,9 @@ static int enc28j60_rx_interrupt(struct net_device *ndev)
return ret;
}
-static void enc28j60_irq_work_handler(struct work_struct *work)
+static irqreturn_t enc28j60_irq(int irq, void *dev_id)
{
- struct enc28j60_net *priv =
- container_of(work, struct enc28j60_net, irq_work);
+ struct enc28j60_net *priv = dev_id;
struct net_device *ndev = priv->netdev;
int intflags, loop;
@@ -1225,6 +1223,8 @@ static void enc28j60_irq_work_handler(struct work_struct *work)
/* re-enable interrupts */
locked_reg_bfset(priv, EIE, EIE_INTIE);
+
+ return IRQ_HANDLED;
}
/*
@@ -1309,22 +1309,6 @@ static void enc28j60_tx_work_handler(struct work_struct *work)
enc28j60_hw_tx(priv);
}
-static irqreturn_t enc28j60_irq(int irq, void *dev_id)
-{
- struct enc28j60_net *priv = dev_id;
-
- /*
- * Can't do anything in interrupt context because we need to
- * block (spi_sync() is blocking) so fire of the interrupt
- * handling workqueue.
- * Remember that we access enc28j60 registers through SPI bus
- * via spi_sync() call.
- */
- schedule_work(&priv->irq_work);
-
- return IRQ_HANDLED;
-}
-
static void enc28j60_tx_timeout(struct net_device *ndev, unsigned int txqueue)
{
struct enc28j60_net *priv = netdev_priv(ndev);
@@ -1559,7 +1543,6 @@ static int enc28j60_probe(struct spi_device *spi)
mutex_init(&priv->lock);
INIT_WORK(&priv->tx_work, enc28j60_tx_work_handler);
INIT_WORK(&priv->setrx_work, enc28j60_setrx_work_handler);
- INIT_WORK(&priv->irq_work, enc28j60_irq_work_handler);
INIT_WORK(&priv->restart_work, enc28j60_restart_work_handler);
spi_set_drvdata(spi, priv); /* spi to priv reference */
SET_NETDEV_DEV(dev, &spi->dev);
@@ -1578,7 +1561,8 @@ static int enc28j60_probe(struct spi_device *spi)
/* Board setup must set the relevant edge trigger type;
* level triggers won't currently work.
*/
- ret = request_irq(spi->irq, enc28j60_irq, 0, DRV_NAME, priv);
+ ret = request_threaded_irq(spi->irq, NULL, enc28j60_irq, IRQF_ONESHOT,
+ DRV_NAME, priv);
if (ret < 0) {
if (netif_msg_probe(priv))
dev_err(&spi->dev, "request irq %d failed (ret = %d)\n",
diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index 957d96a91a8a..a36f6369f132 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -144,6 +144,18 @@ static int lan743x_csr_light_reset(struct lan743x_adapter *adapter)
!(data & HW_CFG_LRST_), 100000, 10000000);
}
+static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter,
+ int offset, u32 bit_mask,
+ int target_value, int udelay_min,
+ int udelay_max, int count)
+{
+ u32 data;
+
+ return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data,
+ target_value == !!(data & bit_mask),
+ udelay_max, udelay_min * count);
+}
+
static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
int offset, u32 bit_mask,
int target_value, int usleep_min,
@@ -152,7 +164,7 @@ static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
u32 data;
return readx_poll_timeout(LAN743X_CSR_READ_OP, offset, data,
- target_value == ((data & bit_mask) ? 1 : 0),
+ target_value == !!(data & bit_mask),
usleep_max, usleep_min * count);
}
@@ -160,16 +172,13 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
{
struct lan743x_csr *csr = &adapter->csr;
resource_size_t bar_start, bar_length;
- int result;
bar_start = pci_resource_start(adapter->pdev, 0);
bar_length = pci_resource_len(adapter->pdev, 0);
csr->csr_address = devm_ioremap(&adapter->pdev->dev,
bar_start, bar_length);
- if (!csr->csr_address) {
- result = -ENOMEM;
- goto clean_up;
- }
+ if (!csr->csr_address)
+ return -ENOMEM;
csr->id_rev = lan743x_csr_read(adapter, ID_REV);
csr->fpga_rev = lan743x_csr_read(adapter, FPGA_REV);
@@ -177,10 +186,8 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
"ID_REV = 0x%08X, FPGA_REV = %d.%d\n",
csr->id_rev, FPGA_REV_GET_MAJOR_(csr->fpga_rev),
FPGA_REV_GET_MINOR_(csr->fpga_rev));
- if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) {
- result = -ENODEV;
- goto clean_up;
- }
+ if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev))
+ return -ENODEV;
csr->flags = LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR;
switch (csr->id_rev & ID_REV_CHIP_REV_MASK_) {
@@ -193,12 +200,7 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter)
break;
}
- result = lan743x_csr_light_reset(adapter);
- if (result)
- goto clean_up;
- return 0;
-clean_up:
- return result;
+ return lan743x_csr_light_reset(adapter);
}
static void lan743x_intr_software_isr(struct lan743x_adapter *adapter)
@@ -746,8 +748,8 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter,
u32 dp_sel;
int i;
- if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
- 1, 40, 100, 100))
+ if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_,
+ 1, 40, 100, 100))
return -EIO;
dp_sel = lan743x_csr_read(adapter, DP_SEL);
dp_sel &= ~DP_SEL_MASK_;
@@ -758,8 +760,9 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter,
lan743x_csr_write(adapter, DP_ADDR, addr + i);
lan743x_csr_write(adapter, DP_DATA_0, buf[i]);
lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_);
- if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
- 1, 40, 100, 100))
+ if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL,
+ DP_SEL_DPRDY_,
+ 1, 40, 100, 100))
return -EIO;
}
diff --git a/drivers/net/ethernet/microchip/lan966x/Kconfig b/drivers/net/ethernet/microchip/lan966x/Kconfig
index 571e6d4da1e9..f9ebffc04eb8 100644
--- a/drivers/net/ethernet/microchip/lan966x/Kconfig
+++ b/drivers/net/ethernet/microchip/lan966x/Kconfig
@@ -10,3 +10,14 @@ config LAN966X_SWITCH
select VCAP
help
This driver supports the Lan966x network switch device.
+
+config LAN966X_DCB
+ bool "Data Center Bridging (DCB) support"
+ depends on LAN966X_SWITCH && DCB
+ default y
+ help
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver. This can be used to assign priority to traffic, based on
+ DSCP and PCP.
+
+ If unsure, set to Y.
diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/ethernet/microchip/lan966x/Makefile
index 7b0cda4ffa6b..3b6ac331691d 100644
--- a/drivers/net/ethernet/microchip/lan966x/Makefile
+++ b/drivers/net/ethernet/microchip/lan966x/Makefile
@@ -15,6 +15,7 @@ lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
lan966x_xdp.o lan966x_vcap_impl.o lan966x_vcap_ag_api.o \
lan966x_tc_flower.o lan966x_goto.o
+lan966x-switch-$(CONFIG_LAN966X_DCB) += lan966x_dcb.o
lan966x-switch-$(CONFIG_DEBUG_FS) += lan966x_vcap_debugfs.o
# Provide include files
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c
new file mode 100644
index 000000000000..ed2d96d7908e
--- /dev/null
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_dcb.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "lan966x_main.h"
+
+enum lan966x_dcb_apptrust_values {
+ LAN966X_DCB_APPTRUST_EMPTY,
+ LAN966X_DCB_APPTRUST_DSCP,
+ LAN966X_DCB_APPTRUST_PCP,
+ LAN966X_DCB_APPTRUST_DSCP_PCP,
+ __LAN966X_DCB_APPTRUST_MAX
+};
+
+static const struct lan966x_dcb_apptrust {
+ u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1];
+ int nselectors;
+} *lan966x_port_apptrust[NUM_PHYS_PORTS];
+
+static const char *lan966x_dcb_apptrust_names[__LAN966X_DCB_APPTRUST_MAX] = {
+ [LAN966X_DCB_APPTRUST_EMPTY] = "empty",
+ [LAN966X_DCB_APPTRUST_DSCP] = "dscp",
+ [LAN966X_DCB_APPTRUST_PCP] = "pcp",
+ [LAN966X_DCB_APPTRUST_DSCP_PCP] = "dscp pcp"
+};
+
+/* Lan966x supported apptrust policies */
+static const struct lan966x_dcb_apptrust
+ lan966x_dcb_apptrust_policies[__LAN966X_DCB_APPTRUST_MAX] = {
+ /* Empty *must* be first */
+ [LAN966X_DCB_APPTRUST_EMPTY] = { { 0 }, 0 },
+ [LAN966X_DCB_APPTRUST_DSCP] = { { IEEE_8021QAZ_APP_SEL_DSCP }, 1 },
+ [LAN966X_DCB_APPTRUST_PCP] = { { DCB_APP_SEL_PCP }, 1 },
+ [LAN966X_DCB_APPTRUST_DSCP_PCP] = { { IEEE_8021QAZ_APP_SEL_DSCP,
+ DCB_APP_SEL_PCP }, 2 },
+};
+
+static bool lan966x_dcb_apptrust_contains(int portno, u8 selector)
+{
+ const struct lan966x_dcb_apptrust *conf = lan966x_port_apptrust[portno];
+
+ for (int i = 0; i < conf->nselectors; i++)
+ if (conf->selectors[i] == selector)
+ return true;
+
+ return false;
+}
+
+static void lan966x_dcb_app_update(struct net_device *dev)
+{
+ struct dcb_ieee_app_prio_map dscp_rewr_map = {0};
+ struct dcb_rewr_prio_pcp_map pcp_rewr_map = {0};
+ struct lan966x_port *port = netdev_priv(dev);
+ struct lan966x_port_qos qos = {0};
+ struct dcb_app app_itr;
+ bool dscp_rewr = false;
+ bool pcp_rewr = false;
+
+ /* Get pcp ingress mapping */
+ for (int i = 0; i < ARRAY_SIZE(qos.pcp.map); i++) {
+ app_itr.selector = DCB_APP_SEL_PCP;
+ app_itr.protocol = i;
+ qos.pcp.map[i] = dcb_getapp(dev, &app_itr);
+ }
+
+ /* Get dscp ingress mapping */
+ for (int i = 0; i < ARRAY_SIZE(qos.dscp.map); i++) {
+ app_itr.selector = IEEE_8021QAZ_APP_SEL_DSCP;
+ app_itr.protocol = i;
+ qos.dscp.map[i] = dcb_getapp(dev, &app_itr);
+ }
+
+ /* Get default prio */
+ qos.default_prio = dcb_ieee_getapp_default_prio_mask(dev);
+ if (qos.default_prio)
+ qos.default_prio = fls(qos.default_prio) - 1;
+
+ /* Get pcp rewrite mapping */
+ dcb_getrewr_prio_pcp_mask_map(dev, &pcp_rewr_map);
+ for (int i = 0; i < ARRAY_SIZE(pcp_rewr_map.map); i++) {
+ if (!pcp_rewr_map.map[i])
+ continue;
+
+ pcp_rewr = true;
+ qos.pcp_rewr.map[i] = fls(pcp_rewr_map.map[i]) - 1;
+ }
+
+ /* Get dscp rewrite mapping */
+ dcb_getrewr_prio_dscp_mask_map(dev, &dscp_rewr_map);
+ for (int i = 0; i < ARRAY_SIZE(dscp_rewr_map.map); i++) {
+ if (!dscp_rewr_map.map[i])
+ continue;
+
+ dscp_rewr = true;
+ qos.dscp_rewr.map[i] = fls64(dscp_rewr_map.map[i]) - 1;
+ }
+
+ /* Enable use of pcp for queue classification */
+ if (lan966x_dcb_apptrust_contains(port->chip_port, DCB_APP_SEL_PCP)) {
+ qos.pcp.enable = true;
+
+ if (pcp_rewr)
+ qos.pcp_rewr.enable = true;
+ }
+
+ /* Enable use of dscp for queue classification */
+ if (lan966x_dcb_apptrust_contains(port->chip_port, IEEE_8021QAZ_APP_SEL_DSCP)) {
+ qos.dscp.enable = true;
+
+ if (dscp_rewr)
+ qos.dscp_rewr.enable = true;
+ }
+
+ lan966x_port_qos_set(port, &qos);
+}
+
+/* DSCP mapping is global for all ports, so set and delete app entries are
+ * replicated for each port.
+ */
+static int lan966x_dcb_ieee_dscp_setdel(struct net_device *dev,
+ struct dcb_app *app,
+ int (*setdel)(struct net_device *,
+ struct dcb_app *))
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ struct lan966x *lan966x = port->lan966x;
+ int err;
+
+ for (int i = 0; i < NUM_PHYS_PORTS; i++) {
+ port = lan966x->ports[i];
+ if (!port)
+ continue;
+
+ err = setdel(port->dev, app);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int lan966x_dcb_app_validate(struct net_device *dev,
+ const struct dcb_app *app)
+{
+ int err = 0;
+
+ switch (app->selector) {
+ /* Default priority checks */
+ case IEEE_8021QAZ_APP_SEL_ETHERTYPE:
+ if (app->protocol)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ /* Dscp checks */
+ case IEEE_8021QAZ_APP_SEL_DSCP:
+ if (app->protocol >= LAN966X_PORT_QOS_DSCP_COUNT)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ /* Pcp checks */
+ case DCB_APP_SEL_PCP:
+ if (app->protocol >= LAN966X_PORT_QOS_PCP_DEI_COUNT)
+ err = -EINVAL;
+ else if (app->priority >= NUM_PRIO_QUEUES)
+ err = -ERANGE;
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ if (err)
+ netdev_err(dev, "Invalid entry: %d:%d\n", app->protocol,
+ app->priority);
+
+ return err;
+}
+
+static int lan966x_dcb_ieee_delapp(struct net_device *dev, struct dcb_app *app)
+{
+ int err;
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_delapp);
+ else
+ err = dcb_ieee_delapp(dev, app);
+
+ if (err)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+ struct dcb_app app_itr;
+ int err;
+ u8 prio;
+
+ err = lan966x_dcb_app_validate(dev, app);
+ if (err)
+ return err;
+
+ /* Delete current mapping, if it exists */
+ prio = dcb_getapp(dev, app);
+ if (prio) {
+ app_itr = *app;
+ app_itr.priority = prio;
+ lan966x_dcb_ieee_delapp(dev, &app_itr);
+ }
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_ieee_setapp);
+ else
+ err = dcb_ieee_setapp(dev, app);
+
+ if (err)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_apptrust_validate(struct net_device *dev,
+ u8 *selectors,
+ int nselectors)
+{
+ for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_policies); i++) {
+ bool match;
+
+ if (lan966x_dcb_apptrust_policies[i].nselectors != nselectors)
+ continue;
+
+ match = true;
+ for (int j = 0; j < nselectors; j++) {
+ if (lan966x_dcb_apptrust_policies[i].selectors[j] !=
+ *(selectors + j)) {
+ match = false;
+ break;
+ }
+ }
+ if (match)
+ return i;
+ }
+
+ netdev_err(dev, "Valid apptrust configurations are:\n");
+ for (int i = 0; i < ARRAY_SIZE(lan966x_dcb_apptrust_names); i++)
+ pr_info("order: %s\n", lan966x_dcb_apptrust_names[i]);
+
+ return -EOPNOTSUPP;
+}
+
+static int lan966x_dcb_setapptrust(struct net_device *dev,
+ u8 *selectors,
+ int nselectors)
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ int idx;
+
+ idx = lan966x_dcb_apptrust_validate(dev, selectors, nselectors);
+ if (idx < 0)
+ return idx;
+
+ lan966x_port_apptrust[port->chip_port] = &lan966x_dcb_apptrust_policies[idx];
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_getapptrust(struct net_device *dev, u8 *selectors,
+ int *nselectors)
+{
+ struct lan966x_port *port = netdev_priv(dev);
+ const struct lan966x_dcb_apptrust *trust;
+
+ trust = lan966x_port_apptrust[port->chip_port];
+
+ memcpy(selectors, trust->selectors, trust->nselectors);
+ *nselectors = trust->nselectors;
+
+ return 0;
+}
+
+static int lan966x_dcb_delrewr(struct net_device *dev, struct dcb_app *app)
+{
+ int err;
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_delrewr);
+ else
+ err = dcb_delrewr(dev, app);
+
+ if (err < 0)
+ return err;
+
+ lan966x_dcb_app_update(dev);
+
+ return 0;
+}
+
+static int lan966x_dcb_setrewr(struct net_device *dev, struct dcb_app *app)
+{
+ struct dcb_app app_itr;
+ u16 proto;
+ int err;
+
+ err = lan966x_dcb_app_validate(dev, app);
+ if (err)
+ goto out;
+
+ /* Delete current mapping, if it exists. */
+ proto = dcb_getrewr(dev, app);
+ if (proto) {
+ app_itr = *app;
+ app_itr.protocol = proto;
+ lan966x_dcb_delrewr(dev, &app_itr);
+ }
+
+ if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
+ err = lan966x_dcb_ieee_dscp_setdel(dev, app, dcb_setrewr);
+ else
+ err = dcb_setrewr(dev, app);
+
+ if (err)
+ goto out;
+
+ lan966x_dcb_app_update(dev);
+
+out:
+ return err;
+}
+
+static const struct dcbnl_rtnl_ops lan966x_dcbnl_ops = {
+ .ieee_setapp = lan966x_dcb_ieee_setapp,
+ .ieee_delapp = lan966x_dcb_ieee_delapp,
+ .dcbnl_setapptrust = lan966x_dcb_setapptrust,
+ .dcbnl_getapptrust = lan966x_dcb_getapptrust,
+ .dcbnl_setrewr = lan966x_dcb_setrewr,
+ .dcbnl_delrewr = lan966x_dcb_delrewr,
+};
+
+void lan966x_dcb_init(struct lan966x *lan966x)
+{
+ for (int p = 0; p < lan966x->num_phys_ports; ++p) {
+ struct lan966x_port *port;
+
+ port = lan966x->ports[p];
+ if (!port)
+ continue;
+
+ port->dev->dcbnl_ops = &lan966x_dcbnl_ops;
+
+ lan966x_port_apptrust[port->chip_port] =
+ &lan966x_dcb_apptrust_policies[LAN966X_DCB_APPTRUST_DSCP_PCP];
+
+ /* Enable DSCP classification based on classified QoS class and
+ * DP, for all DSCP values, for all ports.
+ */
+ lan966x_port_qos_dscp_rewr_mode_set(port,
+ LAN966X_PORT_QOS_REWR_DSCP_ALL);
+ }
+}
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index ee2698698d71..fbb0bb4594cd 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -818,6 +818,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
port->phylink_config.type = PHYLINK_NETDEV;
port->phylink_pcs.poll = true;
port->phylink_pcs.ops = &lan966x_phylink_pcs_ops;
+ port->phylink_pcs.neg_mode = true;
port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD;
@@ -1223,6 +1224,8 @@ static int lan966x_probe(struct platform_device *pdev)
if (err)
goto cleanup_fdma;
+ lan966x_dcb_init(lan966x);
+
return 0;
cleanup_fdma:
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
index c977c70abc3d..27f272831ea5 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
@@ -101,6 +101,25 @@
#define LAN966X_VCAP_CID_IS2_L1 VCAP_CID_INGRESS_STAGE2_L1 /* IS2 lookup 1 */
#define LAN966X_VCAP_CID_IS2_MAX (VCAP_CID_INGRESS_STAGE2_L2 - 1) /* IS2 Max */
+#define LAN966X_VCAP_CID_ES0_L0 VCAP_CID_EGRESS_L0 /* ES0 lookup 0 */
+#define LAN966X_VCAP_CID_ES0_MAX (VCAP_CID_EGRESS_L1 - 1) /* ES0 Max */
+
+#define LAN966X_PORT_QOS_PCP_COUNT 8
+#define LAN966X_PORT_QOS_DEI_COUNT 8
+#define LAN966X_PORT_QOS_PCP_DEI_COUNT \
+ (LAN966X_PORT_QOS_PCP_COUNT + LAN966X_PORT_QOS_DEI_COUNT)
+
+#define LAN966X_PORT_QOS_DSCP_COUNT 64
+
+/* Port PCP rewrite mode */
+#define LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED 0
+#define LAN966X_PORT_REW_TAG_CTRL_MAPPED 2
+
+/* Port DSCP rewrite mode */
+#define LAN966X_PORT_REW_DSCP_FRAME 0
+#define LAN966X_PORT_REW_DSCP_ANALIZER 1
+#define LAN966X_PORT_QOS_REWR_DSCP_ALL 3
+
/* MAC table entry types.
* ENTRYTYPE_NORMAL is subject to aging.
* ENTRYTYPE_LOCKED is not subject to aging.
@@ -389,6 +408,34 @@ struct lan966x_port_tc {
struct flow_stats mirror_stat;
};
+struct lan966x_port_qos_pcp {
+ u8 map[LAN966X_PORT_QOS_PCP_DEI_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos_dscp {
+ u8 map[LAN966X_PORT_QOS_DSCP_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos_pcp_rewr {
+ u16 map[NUM_PRIO_QUEUES];
+ bool enable;
+};
+
+struct lan966x_port_qos_dscp_rewr {
+ u16 map[LAN966X_PORT_QOS_DSCP_COUNT];
+ bool enable;
+};
+
+struct lan966x_port_qos {
+ struct lan966x_port_qos_pcp pcp;
+ struct lan966x_port_qos_dscp dscp;
+ struct lan966x_port_qos_pcp_rewr pcp_rewr;
+ struct lan966x_port_qos_dscp_rewr dscp_rewr;
+ u8 default_prio;
+};
+
struct lan966x_port {
struct net_device *dev;
struct lan966x *lan966x;
@@ -453,6 +500,11 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
struct lan966x_port_config *config);
void lan966x_port_init(struct lan966x_port *port);
+void lan966x_port_qos_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos);
+void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port,
+ int mode);
+
int lan966x_mac_ip_learn(struct lan966x *lan966x,
bool cpu_copy,
const unsigned char mac[ETH_ALEN],
@@ -677,6 +729,14 @@ int lan966x_goto_port_del(struct lan966x_port *port,
unsigned long goto_id,
struct netlink_ext_ack *extack);
+#ifdef CONFIG_LAN966X_DCB
+void lan966x_dcb_init(struct lan966x *lan966x);
+#else
+static inline void lan966x_dcb_init(struct lan966x *lan966x)
+{
+}
+#endif
+
static inline void __iomem *lan_addr(void __iomem *base[],
int id, int tinst, int tcnt,
int gbase, int ginst,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
index c5f9803e6e63..1d63903f9006 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
@@ -95,8 +95,7 @@ static void lan966x_pcs_get_state(struct phylink_pcs *pcs,
lan966x_port_status_get(port, state);
}
-static int lan966x_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int lan966x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -107,8 +106,8 @@ static int lan966x_pcs_config(struct phylink_pcs *pcs,
config = port->config;
config.portmode = interface;
- config.inband = phylink_autoneg_inband(mode);
- config.autoneg = phylink_test(advertising, Autoneg);
+ config.inband = neg_mode & PHYLINK_PCS_NEG_INBAND;
+ config.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
config.advertising = advertising;
ret = lan966x_port_pcs_set(port, &config);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
index 0050fcb988b7..92108d354051 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
@@ -394,6 +394,155 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
return 0;
}
+static void lan966x_port_qos_pcp_set(struct lan966x_port *port,
+ struct lan966x_port_qos_pcp *qos)
+{
+ u8 *pcp_itr = qos->map;
+ u8 pcp, dp;
+
+ lan_rmw(ANA_QOS_CFG_QOS_PCP_ENA_SET(qos->enable),
+ ANA_QOS_CFG_QOS_PCP_ENA,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Map PCP and DEI to priority */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ pcp = *(pcp_itr + i);
+ dp = (i < LAN966X_PORT_QOS_PCP_COUNT) ? 0 : 1;
+
+ lan_rmw(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(pcp) |
+ ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(dp),
+ ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL |
+ ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL,
+ port->lan966x,
+ ANA_PCP_DEI_CFG(port->chip_port, i));
+ }
+}
+
+static void lan966x_port_qos_dscp_set(struct lan966x_port *port,
+ struct lan966x_port_qos_dscp *qos)
+{
+ struct lan966x *lan966x = port->lan966x;
+
+ /* Enable/disable dscp for qos classification. */
+ lan_rmw(ANA_QOS_CFG_QOS_DSCP_ENA_SET(qos->enable),
+ ANA_QOS_CFG_QOS_DSCP_ENA,
+ lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Map each dscp value to priority and dp */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++)
+ lan_rmw(ANA_DSCP_CFG_DP_DSCP_VAL_SET(0) |
+ ANA_DSCP_CFG_QOS_DSCP_VAL_SET(*(qos->map + i)),
+ ANA_DSCP_CFG_DP_DSCP_VAL |
+ ANA_DSCP_CFG_QOS_DSCP_VAL,
+ lan966x, ANA_DSCP_CFG(i));
+
+ /* Set per-dscp trust */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++)
+ lan_rmw(ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(qos->enable),
+ ANA_DSCP_CFG_DSCP_TRUST_ENA,
+ lan966x, ANA_DSCP_CFG(i));
+}
+
+static int lan966x_port_qos_default_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos)
+{
+ /* Set default prio and dp level */
+ lan_rmw(ANA_QOS_CFG_DP_DEFAULT_VAL_SET(0) |
+ ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(qos->default_prio),
+ ANA_QOS_CFG_DP_DEFAULT_VAL |
+ ANA_QOS_CFG_QOS_DEFAULT_VAL,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+
+ /* Set default pcp and dei for untagged frames */
+ lan_rmw(ANA_VLAN_CFG_VLAN_DEI_SET(0) |
+ ANA_VLAN_CFG_VLAN_PCP_SET(0),
+ ANA_VLAN_CFG_VLAN_DEI |
+ ANA_VLAN_CFG_VLAN_PCP,
+ port->lan966x, ANA_VLAN_CFG(port->chip_port));
+
+ return 0;
+}
+
+static void lan966x_port_qos_pcp_rewr_set(struct lan966x_port *port,
+ struct lan966x_port_qos_pcp_rewr *qos)
+{
+ u8 mode = LAN966X_PORT_REW_TAG_CTRL_CLASSIFIED;
+ u8 pcp, dei;
+
+ if (qos->enable)
+ mode = LAN966X_PORT_REW_TAG_CTRL_MAPPED;
+
+ /* Map the values only if it is enabled otherwise will be the classified
+ * value
+ */
+ lan_rmw(REW_TAG_CFG_TAG_PCP_CFG_SET(mode) |
+ REW_TAG_CFG_TAG_DEI_CFG_SET(mode),
+ REW_TAG_CFG_TAG_PCP_CFG |
+ REW_TAG_CFG_TAG_DEI_CFG,
+ port->lan966x, REW_TAG_CFG(port->chip_port));
+
+ /* Map each value to pcp and dei */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ pcp = qos->map[i];
+ if (pcp > LAN966X_PORT_QOS_PCP_COUNT)
+ dei = 1;
+ else
+ dei = 0;
+
+ lan_rmw(REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(dei) |
+ REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(pcp),
+ REW_PCP_DEI_CFG_DEI_QOS_VAL |
+ REW_PCP_DEI_CFG_PCP_QOS_VAL,
+ port->lan966x,
+ REW_PCP_DEI_CFG(port->chip_port,
+ i + dei * LAN966X_PORT_QOS_PCP_COUNT));
+ }
+}
+
+static void lan966x_port_qos_dscp_rewr_set(struct lan966x_port *port,
+ struct lan966x_port_qos_dscp_rewr *qos)
+{
+ u16 dscp;
+ u8 mode;
+
+ if (qos->enable)
+ mode = LAN966X_PORT_REW_DSCP_ANALIZER;
+ else
+ mode = LAN966X_PORT_REW_DSCP_FRAME;
+
+ /* Enable the rewrite otherwise will use the values from the frame */
+ lan_rmw(REW_DSCP_CFG_DSCP_REWR_CFG_SET(mode),
+ REW_DSCP_CFG_DSCP_REWR_CFG,
+ port->lan966x, REW_DSCP_CFG(port->chip_port));
+
+ /* Map each classified Qos class and DP to classified DSCP value */
+ for (int i = 0; i < ARRAY_SIZE(qos->map); i++) {
+ dscp = qos->map[i];
+
+ lan_rmw(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(dscp),
+ ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL,
+ port->lan966x, ANA_DSCP_REWR_CFG(i));
+ }
+}
+
+void lan966x_port_qos_dscp_rewr_mode_set(struct lan966x_port *port,
+ int mode)
+{
+ lan_rmw(ANA_QOS_CFG_DSCP_REWR_CFG_SET(mode),
+ ANA_QOS_CFG_DSCP_REWR_CFG,
+ port->lan966x, ANA_QOS_CFG(port->chip_port));
+}
+
+void lan966x_port_qos_set(struct lan966x_port *port,
+ struct lan966x_port_qos *qos)
+{
+ lan966x_port_qos_pcp_set(port, &qos->pcp);
+ lan966x_port_qos_dscp_set(port, &qos->dscp);
+ lan966x_port_qos_default_set(port, qos);
+ lan966x_port_qos_pcp_rewr_set(port, &qos->pcp_rewr);
+ lan966x_port_qos_dscp_rewr_set(port, &qos->dscp_rewr);
+}
+
void lan966x_port_init(struct lan966x_port *port)
{
struct lan966x_port_config *config = &port->config;
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
index 266a21a2d124..1da2b1f82ae9 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
@@ -59,7 +59,7 @@ static int lan966x_ptp_add_trap(struct lan966x_port *port,
int err;
vrule = vcap_get_rule(lan966x->vcap_ctrl, rule_id);
- if (vrule) {
+ if (!IS_ERR(vrule)) {
u32 value, mask;
/* Just modify the ingress port mask and exit */
@@ -106,7 +106,7 @@ static int lan966x_ptp_del_trap(struct lan966x_port *port,
int err;
vrule = vcap_get_rule(lan966x->vcap_ctrl, rule_id);
- if (!vrule)
+ if (IS_ERR(vrule))
return -EEXIST;
vcap_rule_get_key_u32(vrule, VCAP_KF_IF_IGR_PORT_MASK, &value, &mask);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
index f99f88b5caa8..4b553927d2e0 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
@@ -283,6 +283,18 @@ enum lan966x_target {
#define ANA_VLAN_CFG_VLAN_POP_CNT_GET(x)\
FIELD_GET(ANA_VLAN_CFG_VLAN_POP_CNT, x)
+#define ANA_VLAN_CFG_VLAN_PCP GENMASK(15, 13)
+#define ANA_VLAN_CFG_VLAN_PCP_SET(x)\
+ FIELD_PREP(ANA_VLAN_CFG_VLAN_PCP, x)
+#define ANA_VLAN_CFG_VLAN_PCP_GET(x)\
+ FIELD_GET(ANA_VLAN_CFG_VLAN_PCP, x)
+
+#define ANA_VLAN_CFG_VLAN_DEI BIT(12)
+#define ANA_VLAN_CFG_VLAN_DEI_SET(x)\
+ FIELD_PREP(ANA_VLAN_CFG_VLAN_DEI, x)
+#define ANA_VLAN_CFG_VLAN_DEI_GET(x)\
+ FIELD_GET(ANA_VLAN_CFG_VLAN_DEI, x)
+
#define ANA_VLAN_CFG_VLAN_VID GENMASK(11, 0)
#define ANA_VLAN_CFG_VLAN_VID_SET(x)\
FIELD_PREP(ANA_VLAN_CFG_VLAN_VID, x)
@@ -316,6 +328,39 @@ enum lan966x_target {
#define ANA_DROP_CFG_DROP_MC_SMAC_ENA_GET(x)\
FIELD_GET(ANA_DROP_CFG_DROP_MC_SMAC_ENA, x)
+/* ANA:PORT:QOS_CFG */
+#define ANA_QOS_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 8, 0, 1, 4)
+
+#define ANA_QOS_CFG_DP_DEFAULT_VAL BIT(8)
+#define ANA_QOS_CFG_DP_DEFAULT_VAL_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_DP_DEFAULT_VAL, x)
+#define ANA_QOS_CFG_DP_DEFAULT_VAL_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_DP_DEFAULT_VAL, x)
+
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL GENMASK(7, 5)
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_DEFAULT_VAL, x)
+#define ANA_QOS_CFG_QOS_DEFAULT_VAL_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_DEFAULT_VAL, x)
+
+#define ANA_QOS_CFG_QOS_DSCP_ENA BIT(4)
+#define ANA_QOS_CFG_QOS_DSCP_ENA_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_DSCP_ENA, x)
+#define ANA_QOS_CFG_QOS_DSCP_ENA_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_DSCP_ENA, x)
+
+#define ANA_QOS_CFG_QOS_PCP_ENA BIT(3)
+#define ANA_QOS_CFG_QOS_PCP_ENA_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_QOS_PCP_ENA, x)
+#define ANA_QOS_CFG_QOS_PCP_ENA_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_QOS_PCP_ENA, x)
+
+#define ANA_QOS_CFG_DSCP_REWR_CFG GENMASK(1, 0)
+#define ANA_QOS_CFG_DSCP_REWR_CFG_SET(x)\
+ FIELD_PREP(ANA_QOS_CFG_DSCP_REWR_CFG, x)
+#define ANA_QOS_CFG_DSCP_REWR_CFG_GET(x)\
+ FIELD_GET(ANA_QOS_CFG_DSCP_REWR_CFG, x)
+
/* ANA:PORT:VCAP_CFG */
#define ANA_VCAP_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 12, 0, 1, 4)
@@ -415,6 +460,21 @@ enum lan966x_target {
#define ANA_VCAP_S2_CFG_OAM_DIS_GET(x)\
FIELD_GET(ANA_VCAP_S2_CFG_OAM_DIS, x)
+/* ANA:PORT:QOS_PCP_DEI_MAP_CFG */
+#define ANA_PCP_DEI_CFG(g, r) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 32, r, 16, 4)
+
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL BIT(3)
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_SET(x)\
+ FIELD_PREP(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x)
+#define ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL_GET(x)\
+ FIELD_GET(ANA_PCP_DEI_CFG_DP_PCP_DEI_VAL, x)
+
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL GENMASK(2, 0)
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_SET(x)\
+ FIELD_PREP(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x)
+#define ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL_GET(x)\
+ FIELD_GET(ANA_PCP_DEI_CFG_QOS_PCP_DEI_VAL, x)
+
/* ANA:PORT:CPU_FWD_CFG */
#define ANA_CPU_FWD_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 96, 0, 1, 4)
@@ -478,6 +538,15 @@ enum lan966x_target {
#define ANA_PORT_CFG_PORTID_VAL_GET(x)\
FIELD_GET(ANA_PORT_CFG_PORTID_VAL, x)
+/* ANA:COMMON:DSCP_REWR_CFG */
+#define ANA_DSCP_REWR_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 332, r, 16, 4)
+
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL GENMASK(5, 0)
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x)
+#define ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_REWR_CFG_DSCP_QOS_REWR_VAL, x)
+
/* ANA:PORT:POL_CFG */
#define ANA_POL_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 116, 0, 1, 4)
@@ -547,6 +616,33 @@ enum lan966x_target {
#define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_GET(x)\
FIELD_GET(ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, x)
+/* ANA:COMMON:DSCP_CFG */
+#define ANA_DSCP_CFG(r) __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 76, r, 64, 4)
+
+#define ANA_DSCP_CFG_DP_DSCP_VAL BIT(11)
+#define ANA_DSCP_CFG_DP_DSCP_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DP_DSCP_VAL, x)
+#define ANA_DSCP_CFG_DP_DSCP_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DP_DSCP_VAL, x)
+
+#define ANA_DSCP_CFG_QOS_DSCP_VAL GENMASK(10, 8)
+#define ANA_DSCP_CFG_QOS_DSCP_VAL_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_QOS_DSCP_VAL, x)
+#define ANA_DSCP_CFG_QOS_DSCP_VAL_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_QOS_DSCP_VAL, x)
+
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA BIT(1)
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DSCP_TRUST_ENA, x)
+#define ANA_DSCP_CFG_DSCP_TRUST_ENA_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DSCP_TRUST_ENA, x)
+
+#define ANA_DSCP_CFG_DSCP_REWR_ENA BIT(0)
+#define ANA_DSCP_CFG_DSCP_REWR_ENA_SET(x)\
+ FIELD_PREP(ANA_DSCP_CFG_DSCP_REWR_ENA, x)
+#define ANA_DSCP_CFG_DSCP_REWR_ENA_GET(x)\
+ FIELD_GET(ANA_DSCP_CFG_DSCP_REWR_ENA, x)
+
/* ANA:POL:POL_PIR_CFG */
#define ANA_POL_PIR_CFG(g) __REG(TARGET_ANA, 0, 1, 16384, g, 345, 32, 0, 0, 1, 4)
@@ -1468,15 +1564,66 @@ enum lan966x_target {
#define REW_TAG_CFG_TAG_TPID_CFG_GET(x)\
FIELD_GET(REW_TAG_CFG_TAG_TPID_CFG, x)
+#define REW_TAG_CFG_TAG_PCP_CFG GENMASK(3, 2)
+#define REW_TAG_CFG_TAG_PCP_CFG_SET(x)\
+ FIELD_PREP(REW_TAG_CFG_TAG_PCP_CFG, x)
+#define REW_TAG_CFG_TAG_PCP_CFG_GET(x)\
+ FIELD_GET(REW_TAG_CFG_TAG_PCP_CFG, x)
+
+#define REW_TAG_CFG_TAG_DEI_CFG GENMASK(1, 0)
+#define REW_TAG_CFG_TAG_DEI_CFG_SET(x)\
+ FIELD_PREP(REW_TAG_CFG_TAG_DEI_CFG, x)
+#define REW_TAG_CFG_TAG_DEI_CFG_GET(x)\
+ FIELD_GET(REW_TAG_CFG_TAG_DEI_CFG, x)
+
/* REW:PORT:PORT_CFG */
#define REW_PORT_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 8, 0, 1, 4)
+#define REW_PORT_CFG_ES0_EN BIT(4)
+#define REW_PORT_CFG_ES0_EN_SET(x)\
+ FIELD_PREP(REW_PORT_CFG_ES0_EN, x)
+#define REW_PORT_CFG_ES0_EN_GET(x)\
+ FIELD_GET(REW_PORT_CFG_ES0_EN, x)
+
#define REW_PORT_CFG_NO_REWRITE BIT(0)
#define REW_PORT_CFG_NO_REWRITE_SET(x)\
FIELD_PREP(REW_PORT_CFG_NO_REWRITE, x)
#define REW_PORT_CFG_NO_REWRITE_GET(x)\
FIELD_GET(REW_PORT_CFG_NO_REWRITE, x)
+/* REW:PORT:DSCP_CFG */
+#define REW_DSCP_CFG(g) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 12, 0, 1, 4)
+
+#define REW_DSCP_CFG_DSCP_REWR_CFG GENMASK(1, 0)
+#define REW_DSCP_CFG_DSCP_REWR_CFG_SET(x)\
+ FIELD_PREP(REW_DSCP_CFG_DSCP_REWR_CFG, x)
+#define REW_DSCP_CFG_DSCP_REWR_CFG_GET(x)\
+ FIELD_GET(REW_DSCP_CFG_DSCP_REWR_CFG, x)
+
+/* REW:PORT:PCP_DEI_QOS_MAP_CFG */
+#define REW_PCP_DEI_CFG(g, r) __REG(TARGET_REW, 0, 1, 0, g, 10, 128, 16, r, 16, 4)
+
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL BIT(3)
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL_SET(x)\
+ FIELD_PREP(REW_PCP_DEI_CFG_DEI_QOS_VAL, x)
+#define REW_PCP_DEI_CFG_DEI_QOS_VAL_GET(x)\
+ FIELD_GET(REW_PCP_DEI_CFG_DEI_QOS_VAL, x)
+
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL GENMASK(2, 0)
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL_SET(x)\
+ FIELD_PREP(REW_PCP_DEI_CFG_PCP_QOS_VAL, x)
+#define REW_PCP_DEI_CFG_PCP_QOS_VAL_GET(x)\
+ FIELD_GET(REW_PCP_DEI_CFG_PCP_QOS_VAL, x)
+
+/* REW:COMMON:STAT_CFG */
+#define REW_STAT_CFG __REG(TARGET_REW, 0, 1, 3072, 0, 1, 528, 520, 0, 1, 4)
+
+#define REW_STAT_CFG_STAT_MODE GENMASK(1, 0)
+#define REW_STAT_CFG_STAT_MODE_SET(x)\
+ FIELD_PREP(REW_STAT_CFG_STAT_MODE, x)
+#define REW_STAT_CFG_STAT_MODE_GET(x)\
+ FIELD_GET(REW_STAT_CFG_STAT_MODE, x)
+
/* SYS:SYSTEM:RESET_CFG */
#define SYS_RESET_CFG __REG(TARGET_SYS, 0, 1, 4128, 0, 1, 168, 0, 0, 1, 4)
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
index cf0cc7562d04..ee652f2d2359 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c
@@ -21,8 +21,14 @@ static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port,
static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port,
struct tc_taprio_qopt_offload *taprio)
{
- return taprio->enable ? lan966x_taprio_add(port, taprio) :
- lan966x_taprio_del(port);
+ switch (taprio->cmd) {
+ case TAPRIO_CMD_REPLACE:
+ return lan966x_taprio_add(port, taprio);
+ case TAPRIO_CMD_DESTROY:
+ return lan966x_taprio_del(port);
+ default:
+ return -EOPNOTSUPP;
+ }
}
static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
index 47b2f7579dd2..96b3def6c474 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c
@@ -5,6 +5,8 @@
#include "vcap_api_client.h"
#include "vcap_tc.h"
+#define LAN966X_FORCE_UNTAGED 3
+
static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st,
u16 etype)
{
@@ -29,6 +31,8 @@ static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st,
return true;
}
break;
+ case VCAP_TYPE_ES0:
+ return true;
default:
NL_SET_ERR_MSG_MOD(st->fco->common.extack,
"VCAP type not supported");
@@ -318,6 +322,9 @@ static int lan966x_tc_set_actionset(struct vcap_admin *admin,
case VCAP_TYPE_IS2:
aset = VCAP_AFS_BASE_TYPE;
break;
+ case VCAP_TYPE_ES0:
+ aset = VCAP_AFS_VID;
+ break;
default:
return -EINVAL;
}
@@ -353,6 +360,10 @@ static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin,
/* Add IS2 specific PAG key (for chaining rules from IS1) */
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
link_val, ~0);
+ case VCAP_TYPE_ES0:
+ /* Add ES0 specific ISDX key (for chaining rules from IS1) */
+ return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS,
+ link_val, ~0);
default:
break;
}
@@ -389,6 +400,18 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
0xff);
if (err)
return err;
+ } else if (admin->vtype == VCAP_TYPE_IS1 &&
+ to_admin->vtype == VCAP_TYPE_ES0) {
+ /* This works for IS1->ES0 */
+ err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_ADD_VAL,
+ diff);
+ if (err)
+ return err;
+
+ err = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_REPLACE_ENA,
+ VCAP_BIT_1);
+ if (err)
+ return err;
} else {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported chain destination");
@@ -398,6 +421,23 @@ static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
return err;
}
+static int lan966x_tc_add_rule_counter(struct vcap_admin *admin,
+ struct vcap_rule *vrule)
+{
+ int err = 0;
+
+ switch (admin->vtype) {
+ case VCAP_TYPE_ES0:
+ err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX,
+ vrule->id);
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
static int lan966x_tc_flower_add(struct lan966x_port *port,
struct flow_cls_offload *f,
struct vcap_admin *admin,
@@ -466,6 +506,21 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
goto out;
break;
+ case FLOW_ACTION_VLAN_POP:
+ if (admin->vtype != VCAP_TYPE_ES0) {
+ NL_SET_ERR_MSG_MOD(f->common.extack,
+ "Cannot use vlan pop on non es0");
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /* Force untag */
+ err = vcap_rule_add_action_u32(vrule, VCAP_AF_PUSH_OUTER_TAG,
+ LAN966X_FORCE_UNTAGED);
+ if (err)
+ goto out;
+
+ break;
default:
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported TC action");
@@ -474,6 +529,12 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
}
}
+ err = lan966x_tc_add_rule_counter(admin, vrule);
+ if (err) {
+ vcap_set_tc_exterr(f, vrule);
+ goto out;
+ }
+
err = vcap_val_rule(vrule, l3_proto);
if (err) {
vcap_set_tc_exterr(f, vrule);
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
index 66400a082d02..fb6851b94528 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_ag_api.c
@@ -2121,6 +2121,69 @@ static const struct vcap_field is2_smac_sip6_keyfield[] = {
},
};
+static const struct vcap_field es0_vid_keyfield[] = {
+ [VCAP_KF_IF_EGR_PORT_NO] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 4,
+ },
+ [VCAP_KF_IF_IGR_PORT] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 4,
+ .width = 4,
+ },
+ [VCAP_KF_ISDX_GT0_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 8,
+ .width = 1,
+ },
+ [VCAP_KF_ISDX_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 9,
+ .width = 8,
+ },
+ [VCAP_KF_L2_MC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 17,
+ .width = 1,
+ },
+ [VCAP_KF_L2_BC_IS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 18,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_VID_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 19,
+ .width = 12,
+ },
+ [VCAP_KF_8021Q_DEI_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 31,
+ .width = 1,
+ },
+ [VCAP_KF_8021Q_PCP_CLS] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 32,
+ .width = 3,
+ },
+ [VCAP_KF_L3_DPL_CLS] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 35,
+ .width = 1,
+ },
+ [VCAP_KF_RTP_ID] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 36,
+ .width = 10,
+ },
+ [VCAP_KF_PDU_TYPE] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 46,
+ .width = 4,
+ },
+};
+
/* keyfield_set */
static const struct vcap_set is1_keyfield_set[] = {
[VCAP_KFS_NORMAL] = {
@@ -2228,6 +2291,14 @@ static const struct vcap_set is2_keyfield_set[] = {
},
};
+static const struct vcap_set es0_keyfield_set[] = {
+ [VCAP_KFS_VID] = {
+ .type_id = -1,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
/* keyfield_set map */
static const struct vcap_field *is1_keyfield_set_map[] = {
[VCAP_KFS_NORMAL] = is1_normal_keyfield,
@@ -2255,6 +2326,10 @@ static const struct vcap_field *is2_keyfield_set_map[] = {
[VCAP_KFS_SMAC_SIP6] = is2_smac_sip6_keyfield,
};
+static const struct vcap_field *es0_keyfield_set_map[] = {
+ [VCAP_KFS_VID] = es0_vid_keyfield,
+};
+
/* keyfield_set map sizes */
static int is1_keyfield_set_map_size[] = {
[VCAP_KFS_NORMAL] = ARRAY_SIZE(is1_normal_keyfield),
@@ -2282,6 +2357,10 @@ static int is2_keyfield_set_map_size[] = {
[VCAP_KFS_SMAC_SIP6] = ARRAY_SIZE(is2_smac_sip6_keyfield),
};
+static int es0_keyfield_set_map_size[] = {
+ [VCAP_KFS_VID] = ARRAY_SIZE(es0_vid_keyfield),
+};
+
/* actionfields */
static const struct vcap_field is1_s1_actionfield[] = {
[VCAP_AF_TYPE] = {
@@ -2522,6 +2601,94 @@ static const struct vcap_field is2_smac_sip_actionfield[] = {
},
};
+static const struct vcap_field es0_vid_actionfield[] = {
+ [VCAP_AF_PUSH_OUTER_TAG] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 0,
+ .width = 2,
+ },
+ [VCAP_AF_PUSH_INNER_TAG] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 2,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_A_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 3,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_A_VID_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 5,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_A_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 6,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_A_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 8,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_TPID_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 10,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_VID_SEL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 12,
+ .width = 1,
+ },
+ [VCAP_AF_TAG_B_PCP_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 13,
+ .width = 2,
+ },
+ [VCAP_AF_TAG_B_DEI_SEL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 15,
+ .width = 2,
+ },
+ [VCAP_AF_VID_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 17,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_A_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 29,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_A_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 32,
+ .width = 1,
+ },
+ [VCAP_AF_VID_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 33,
+ .width = 12,
+ },
+ [VCAP_AF_PCP_B_VAL] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 45,
+ .width = 3,
+ },
+ [VCAP_AF_DEI_B_VAL] = {
+ .type = VCAP_FIELD_BIT,
+ .offset = 48,
+ .width = 1,
+ },
+ [VCAP_AF_ESDX] = {
+ .type = VCAP_FIELD_U32,
+ .offset = 49,
+ .width = 8,
+ },
+};
+
/* actionfield_set */
static const struct vcap_set is1_actionfield_set[] = {
[VCAP_AFS_S1] = {
@@ -2544,6 +2711,14 @@ static const struct vcap_set is2_actionfield_set[] = {
},
};
+static const struct vcap_set es0_actionfield_set[] = {
+ [VCAP_AFS_VID] = {
+ .type_id = -1,
+ .sw_per_item = 1,
+ .sw_cnt = 1,
+ },
+};
+
/* actionfield_set map */
static const struct vcap_field *is1_actionfield_set_map[] = {
[VCAP_AFS_S1] = is1_s1_actionfield,
@@ -2554,6 +2729,10 @@ static const struct vcap_field *is2_actionfield_set_map[] = {
[VCAP_AFS_SMAC_SIP] = is2_smac_sip_actionfield,
};
+static const struct vcap_field *es0_actionfield_set_map[] = {
+ [VCAP_AFS_VID] = es0_vid_actionfield,
+};
+
/* actionfield_set map size */
static int is1_actionfield_set_map_size[] = {
[VCAP_AFS_S1] = ARRAY_SIZE(is1_s1_actionfield),
@@ -2564,6 +2743,10 @@ static int is2_actionfield_set_map_size[] = {
[VCAP_AFS_SMAC_SIP] = ARRAY_SIZE(is2_smac_sip_actionfield),
};
+static int es0_actionfield_set_map_size[] = {
+ [VCAP_AFS_VID] = ARRAY_SIZE(es0_vid_actionfield),
+};
+
/* Type Groups */
static const struct vcap_typegroup is1_x4_keyfield_set_typegroups[] = {
{
@@ -2659,6 +2842,10 @@ static const struct vcap_typegroup is2_x1_keyfield_set_typegroups[] = {
{}
};
+static const struct vcap_typegroup es0_x1_keyfield_set_typegroups[] = {
+ {}
+};
+
static const struct vcap_typegroup *is1_keyfield_set_typegroups[] = {
[4] = is1_x4_keyfield_set_typegroups,
[2] = is1_x2_keyfield_set_typegroups,
@@ -2673,6 +2860,11 @@ static const struct vcap_typegroup *is2_keyfield_set_typegroups[] = {
[5] = NULL,
};
+static const struct vcap_typegroup *es0_keyfield_set_typegroups[] = {
+ [1] = es0_x1_keyfield_set_typegroups,
+ [2] = NULL,
+};
+
static const struct vcap_typegroup is1_x1_actionfield_set_typegroups[] = {
{}
};
@@ -2700,6 +2892,10 @@ static const struct vcap_typegroup is2_x1_actionfield_set_typegroups[] = {
{}
};
+static const struct vcap_typegroup es0_x1_actionfield_set_typegroups[] = {
+ {}
+};
+
static const struct vcap_typegroup *is1_actionfield_set_typegroups[] = {
[1] = is1_x1_actionfield_set_typegroups,
[5] = NULL,
@@ -2711,6 +2907,11 @@ static const struct vcap_typegroup *is2_actionfield_set_typegroups[] = {
[5] = NULL,
};
+static const struct vcap_typegroup *es0_actionfield_set_typegroups[] = {
+ [1] = es0_x1_actionfield_set_typegroups,
+ [2] = NULL,
+};
+
/* Keyfieldset names */
static const char * const vcap_keyfield_set_names[] = {
[VCAP_KFS_NO_VALUE] = "(None)",
@@ -2743,6 +2944,7 @@ static const char * const vcap_keyfield_set_names[] = {
[VCAP_KFS_RT] = "VCAP_KFS_RT",
[VCAP_KFS_SMAC_SIP4] = "VCAP_KFS_SMAC_SIP4",
[VCAP_KFS_SMAC_SIP6] = "VCAP_KFS_SMAC_SIP6",
+ [VCAP_KFS_VID] = "VCAP_KFS_VID",
};
/* Actionfieldset names */
@@ -2751,9 +2953,11 @@ static const char * const vcap_actionfield_set_names[] = {
[VCAP_AFS_BASE_TYPE] = "VCAP_AFS_BASE_TYPE",
[VCAP_AFS_CLASSIFICATION] = "VCAP_AFS_CLASSIFICATION",
[VCAP_AFS_CLASS_REDUCED] = "VCAP_AFS_CLASS_REDUCED",
+ [VCAP_AFS_ES0] = "VCAP_AFS_ES0",
[VCAP_AFS_FULL] = "VCAP_AFS_FULL",
[VCAP_AFS_S1] = "VCAP_AFS_S1",
[VCAP_AFS_SMAC_SIP] = "VCAP_AFS_SMAC_SIP",
+ [VCAP_AFS_VID] = "VCAP_AFS_VID",
};
/* Keyfield names */
@@ -2774,6 +2978,7 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_8021Q_PCP1] = "8021Q_PCP1",
[VCAP_KF_8021Q_PCP2] = "8021Q_PCP2",
[VCAP_KF_8021Q_PCP_CLS] = "8021Q_PCP_CLS",
+ [VCAP_KF_8021Q_TPID] = "8021Q_TPID",
[VCAP_KF_8021Q_TPID0] = "8021Q_TPID0",
[VCAP_KF_8021Q_TPID1] = "8021Q_TPID1",
[VCAP_KF_8021Q_TPID2] = "8021Q_TPID2",
@@ -2799,6 +3004,7 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_HOST_MATCH] = "HOST_MATCH",
[VCAP_KF_IF_EGR_PORT_MASK] = "IF_EGR_PORT_MASK",
[VCAP_KF_IF_EGR_PORT_MASK_RNG] = "IF_EGR_PORT_MASK_RNG",
+ [VCAP_KF_IF_EGR_PORT_NO] = "IF_EGR_PORT_NO",
[VCAP_KF_IF_IGR_PORT] = "IF_IGR_PORT",
[VCAP_KF_IF_IGR_PORT_MASK] = "IF_IGR_PORT_MASK",
[VCAP_KF_IF_IGR_PORT_MASK_L3] = "IF_IGR_PORT_MASK_L3",
@@ -2873,7 +3079,9 @@ static const char * const vcap_keyfield_names[] = {
[VCAP_KF_OAM_OPCODE] = "OAM_OPCODE",
[VCAP_KF_OAM_VER] = "OAM_VER",
[VCAP_KF_OAM_Y1731_IS] = "OAM_Y1731_IS",
+ [VCAP_KF_PDU_TYPE] = "PDU_TYPE",
[VCAP_KF_PROT_ACTIVE] = "PROT_ACTIVE",
+ [VCAP_KF_RTP_ID] = "RTP_ID",
[VCAP_KF_RT_FRMID] = "RT_FRMID",
[VCAP_KF_RT_TYPE] = "RT_TYPE",
[VCAP_KF_RT_VLAN_IDX] = "RT_VLAN_IDX",
@@ -2891,18 +3099,25 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_COPY_PORT_NUM] = "COPY_PORT_NUM",
[VCAP_AF_COPY_QUEUE_NUM] = "COPY_QUEUE_NUM",
[VCAP_AF_CPU_COPY_ENA] = "CPU_COPY_ENA",
+ [VCAP_AF_CPU_QU] = "CPU_QU",
[VCAP_AF_CPU_QUEUE_NUM] = "CPU_QUEUE_NUM",
[VCAP_AF_CUSTOM_ACE_TYPE_ENA] = "CUSTOM_ACE_TYPE_ENA",
+ [VCAP_AF_DEI_A_VAL] = "DEI_A_VAL",
+ [VCAP_AF_DEI_B_VAL] = "DEI_B_VAL",
+ [VCAP_AF_DEI_C_VAL] = "DEI_C_VAL",
[VCAP_AF_DEI_ENA] = "DEI_ENA",
[VCAP_AF_DEI_VAL] = "DEI_VAL",
[VCAP_AF_DLR_SEL] = "DLR_SEL",
[VCAP_AF_DP_ENA] = "DP_ENA",
[VCAP_AF_DP_VAL] = "DP_VAL",
[VCAP_AF_DSCP_ENA] = "DSCP_ENA",
+ [VCAP_AF_DSCP_SEL] = "DSCP_SEL",
[VCAP_AF_DSCP_VAL] = "DSCP_VAL",
[VCAP_AF_ES2_REW_CMD] = "ES2_REW_CMD",
+ [VCAP_AF_ESDX] = "ESDX",
[VCAP_AF_FWD_KILL_ENA] = "FWD_KILL_ENA",
[VCAP_AF_FWD_MODE] = "FWD_MODE",
+ [VCAP_AF_FWD_SEL] = "FWD_SEL",
[VCAP_AF_HIT_ME_ONCE] = "HIT_ME_ONCE",
[VCAP_AF_HOST_MATCH] = "HOST_MATCH",
[VCAP_AF_IGNORE_PIPELINE_CTRL] = "IGNORE_PIPELINE_CTRL",
@@ -2912,6 +3127,7 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_ISDX_ENA] = "ISDX_ENA",
[VCAP_AF_ISDX_REPLACE_ENA] = "ISDX_REPLACE_ENA",
[VCAP_AF_ISDX_VAL] = "ISDX_VAL",
+ [VCAP_AF_LOOP_ENA] = "LOOP_ENA",
[VCAP_AF_LRN_DIS] = "LRN_DIS",
[VCAP_AF_MAP_IDX] = "MAP_IDX",
[VCAP_AF_MAP_KEY] = "MAP_KEY",
@@ -2928,15 +3144,23 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_OAM_SEL] = "OAM_SEL",
[VCAP_AF_PAG_OVERRIDE_MASK] = "PAG_OVERRIDE_MASK",
[VCAP_AF_PAG_VAL] = "PAG_VAL",
+ [VCAP_AF_PCP_A_VAL] = "PCP_A_VAL",
+ [VCAP_AF_PCP_B_VAL] = "PCP_B_VAL",
+ [VCAP_AF_PCP_C_VAL] = "PCP_C_VAL",
[VCAP_AF_PCP_ENA] = "PCP_ENA",
[VCAP_AF_PCP_VAL] = "PCP_VAL",
+ [VCAP_AF_PIPELINE_ACT] = "PIPELINE_ACT",
[VCAP_AF_PIPELINE_FORCE_ENA] = "PIPELINE_FORCE_ENA",
[VCAP_AF_PIPELINE_PT] = "PIPELINE_PT",
[VCAP_AF_POLICE_ENA] = "POLICE_ENA",
[VCAP_AF_POLICE_IDX] = "POLICE_IDX",
[VCAP_AF_POLICE_REMARK] = "POLICE_REMARK",
[VCAP_AF_POLICE_VCAP_ONLY] = "POLICE_VCAP_ONLY",
+ [VCAP_AF_POP_VAL] = "POP_VAL",
[VCAP_AF_PORT_MASK] = "PORT_MASK",
+ [VCAP_AF_PUSH_CUSTOMER_TAG] = "PUSH_CUSTOMER_TAG",
+ [VCAP_AF_PUSH_INNER_TAG] = "PUSH_INNER_TAG",
+ [VCAP_AF_PUSH_OUTER_TAG] = "PUSH_OUTER_TAG",
[VCAP_AF_QOS_ENA] = "QOS_ENA",
[VCAP_AF_QOS_VAL] = "QOS_VAL",
[VCAP_AF_REW_OP] = "REW_OP",
@@ -2945,7 +3169,24 @@ static const char * const vcap_actionfield_names[] = {
[VCAP_AF_SFID_VAL] = "SFID_VAL",
[VCAP_AF_SGID_ENA] = "SGID_ENA",
[VCAP_AF_SGID_VAL] = "SGID_VAL",
+ [VCAP_AF_SWAP_MACS_ENA] = "SWAP_MACS_ENA",
+ [VCAP_AF_TAG_A_DEI_SEL] = "TAG_A_DEI_SEL",
+ [VCAP_AF_TAG_A_PCP_SEL] = "TAG_A_PCP_SEL",
+ [VCAP_AF_TAG_A_TPID_SEL] = "TAG_A_TPID_SEL",
+ [VCAP_AF_TAG_A_VID_SEL] = "TAG_A_VID_SEL",
+ [VCAP_AF_TAG_B_DEI_SEL] = "TAG_B_DEI_SEL",
+ [VCAP_AF_TAG_B_PCP_SEL] = "TAG_B_PCP_SEL",
+ [VCAP_AF_TAG_B_TPID_SEL] = "TAG_B_TPID_SEL",
+ [VCAP_AF_TAG_B_VID_SEL] = "TAG_B_VID_SEL",
+ [VCAP_AF_TAG_C_DEI_SEL] = "TAG_C_DEI_SEL",
+ [VCAP_AF_TAG_C_PCP_SEL] = "TAG_C_PCP_SEL",
+ [VCAP_AF_TAG_C_TPID_SEL] = "TAG_C_TPID_SEL",
+ [VCAP_AF_TAG_C_VID_SEL] = "TAG_C_VID_SEL",
[VCAP_AF_TYPE] = "TYPE",
+ [VCAP_AF_UNTAG_VID_ENA] = "UNTAG_VID_ENA",
+ [VCAP_AF_VID_A_VAL] = "VID_A_VAL",
+ [VCAP_AF_VID_B_VAL] = "VID_B_VAL",
+ [VCAP_AF_VID_C_VAL] = "VID_C_VAL",
[VCAP_AF_VID_REPLACE_ENA] = "VID_REPLACE_ENA",
[VCAP_AF_VID_VAL] = "VID_VAL",
[VCAP_AF_VLAN_POP_CNT] = "VLAN_POP_CNT",
@@ -2996,11 +3237,32 @@ const struct vcap_info lan966x_vcaps[] = {
.keyfield_set_typegroups = is2_keyfield_set_typegroups,
.actionfield_set_typegroups = is2_actionfield_set_typegroups,
},
+ [VCAP_TYPE_ES0] = {
+ .name = "es0",
+ .rows = 256,
+ .sw_count = 1,
+ .sw_width = 96,
+ .sticky_width = 1,
+ .act_width = 65,
+ .default_cnt = 8,
+ .require_cnt_dis = 0,
+ .version = 1,
+ .keyfield_set = es0_keyfield_set,
+ .keyfield_set_size = ARRAY_SIZE(es0_keyfield_set),
+ .actionfield_set = es0_actionfield_set,
+ .actionfield_set_size = ARRAY_SIZE(es0_actionfield_set),
+ .keyfield_set_map = es0_keyfield_set_map,
+ .keyfield_set_map_size = es0_keyfield_set_map_size,
+ .actionfield_set_map = es0_actionfield_set_map,
+ .actionfield_set_map_size = es0_actionfield_set_map_size,
+ .keyfield_set_typegroups = es0_keyfield_set_typegroups,
+ .actionfield_set_typegroups = es0_actionfield_set_typegroups,
+ },
};
const struct vcap_statistics lan966x_vcap_stats = {
.name = "lan966x",
- .count = 2,
+ .count = 3,
.keyfield_set_names = vcap_keyfield_set_names,
.actionfield_set_names = vcap_actionfield_set_names,
.keyfield_names = vcap_keyfield_names,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
index d90c08cfcf14..ac525ff1503e 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_debugfs.c
@@ -190,6 +190,26 @@ static void lan966x_vcap_is2_port_keys(struct lan966x_port *port,
out->prf(out->dst, "\n");
}
+static void lan966x_vcap_es0_port_keys(struct lan966x_port *port,
+ struct vcap_admin *admin,
+ struct vcap_output_print *out)
+{
+ struct lan966x *lan966x = port->lan966x;
+ u32 val;
+
+ out->prf(out->dst, " port[%d] (%s): ", port->chip_port,
+ netdev_name(port->dev));
+
+ val = lan_rd(lan966x, REW_PORT_CFG(port->chip_port));
+ out->prf(out->dst, "\n state: ");
+ if (REW_PORT_CFG_ES0_EN_GET(val))
+ out->prf(out->dst, "on");
+ else
+ out->prf(out->dst, "off");
+
+ out->prf(out->dst, "\n");
+}
+
int lan966x_vcap_port_info(struct net_device *dev,
struct vcap_admin *admin,
struct vcap_output_print *out)
@@ -210,6 +230,9 @@ int lan966x_vcap_port_info(struct net_device *dev,
case VCAP_TYPE_IS1:
lan966x_vcap_is1_port_keys(port, admin, out);
break;
+ case VCAP_TYPE_ES0:
+ lan966x_vcap_es0_port_keys(port, admin, out);
+ break;
default:
out->prf(out->dst, " no info\n");
break;
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
index 7ea8e8633609..a4414f63c9b1 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c
@@ -10,6 +10,12 @@
#define LAN966X_IS1_LOOKUPS 3
#define LAN966X_IS2_LOOKUPS 2
+#define LAN966X_ES0_LOOKUPS 1
+
+#define LAN966X_STAT_ESDX_GRN_BYTES 0x300
+#define LAN966X_STAT_ESDX_GRN_PKTS 0x301
+#define LAN966X_STAT_ESDX_YEL_BYTES 0x302
+#define LAN966X_STAT_ESDX_YEL_PKTS 0x303
static struct lan966x_vcap_inst {
enum vcap_type vtype; /* type of vcap */
@@ -21,6 +27,14 @@ static struct lan966x_vcap_inst {
bool ingress; /* is vcap in the ingress path */
} lan966x_vcap_inst_cfg[] = {
{
+ .vtype = VCAP_TYPE_ES0,
+ .tgt_inst = 0,
+ .lookups = LAN966X_ES0_LOOKUPS,
+ .first_cid = LAN966X_VCAP_CID_ES0_L0,
+ .last_cid = LAN966X_VCAP_CID_ES0_MAX,
+ .count = 64,
+ },
+ {
.vtype = VCAP_TYPE_IS1, /* IS1-0 */
.tgt_inst = 1,
.lookups = LAN966X_IS1_LOOKUPS,
@@ -279,6 +293,8 @@ lan966x_vcap_validate_keyset(struct net_device *dev,
err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
l3_proto);
break;
+ case VCAP_TYPE_ES0:
+ return kslist->keysets[0];
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -338,6 +354,14 @@ static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port,
VCAP_BIT_0);
}
+static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port,
+ struct vcap_admin *admin,
+ struct vcap_rule *rule)
+{
+ vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO,
+ port->chip_port, GENMASK(4, 0));
+}
+
static void lan966x_vcap_add_default_fields(struct net_device *dev,
struct vcap_admin *admin,
struct vcap_rule *rule)
@@ -351,6 +375,9 @@ static void lan966x_vcap_add_default_fields(struct net_device *dev,
case VCAP_TYPE_IS2:
lan966x_vcap_is2_add_default_fields(port, admin, rule);
break;
+ case VCAP_TYPE_ES0:
+ lan966x_vcap_es0_add_default_fields(port, admin, rule);
+ break;
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -366,6 +393,40 @@ static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
}
+/* The ESDX counter is only used/incremented if the frame has been classified
+ * with an ISDX > 0 (e.g by a rule in IS0). This is not mentioned in the
+ * datasheet.
+ */
+static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x,
+ struct vcap_admin *admin, u32 id)
+{
+ u32 counter;
+
+ id = id & 0xff; /* counter limit */
+ mutex_lock(&lan966x->stats_lock);
+ lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
+ counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) +
+ lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
+ mutex_unlock(&lan966x->stats_lock);
+ if (counter)
+ admin->cache.counter = counter;
+}
+
+static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x,
+ struct vcap_admin *admin, u32 id)
+{
+ id = id & 0xff; /* counter limit */
+
+ mutex_lock(&lan966x->stats_lock);
+ lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES));
+ lan_wr(admin->cache.counter, lan966x,
+ SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS));
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES));
+ lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
+ mutex_unlock(&lan966x->stats_lock);
+}
+
static void lan966x_vcap_cache_write(struct net_device *dev,
struct vcap_admin *admin,
enum vcap_selection sel,
@@ -398,6 +459,9 @@ static void lan966x_vcap_cache_write(struct net_device *dev,
admin->cache.sticky = admin->cache.counter > 0;
lan_wr(admin->cache.counter, lan966x,
VCAP_CNT_DAT(admin->tgt_inst, 0));
+
+ if (admin->vtype == VCAP_TYPE_ES0)
+ lan966x_es0_write_esdx_counter(lan966x, admin, start);
break;
default:
break;
@@ -437,6 +501,9 @@ static void lan966x_vcap_cache_read(struct net_device *dev,
admin->cache.counter =
lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
admin->cache.sticky = admin->cache.counter > 0;
+
+ if (admin->vtype == VCAP_TYPE_ES0)
+ lan966x_es0_read_esdx_counter(lan966x, admin, start);
}
}
@@ -625,6 +692,12 @@ static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
break;
+ case VCAP_TYPE_ES0:
+ for (int p = 0; p < lan966x->num_phys_ports; ++p)
+ lan_rmw(REW_PORT_CFG_ES0_EN_SET(false),
+ REW_PORT_CFG_ES0_EN, lan966x,
+ REW_PORT_CFG(p));
+ break;
default:
pr_err("vcap type: %s not supported\n",
lan966x_vcaps[admin->vtype].name);
@@ -674,9 +747,18 @@ int lan966x_vcap_init(struct lan966x *lan966x)
lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
ANA_VCAP_CFG_S1_ENA, lan966x,
ANA_VCAP_CFG(lan966x->ports[p]->chip_port));
+
+ lan_rmw(REW_PORT_CFG_ES0_EN_SET(true),
+ REW_PORT_CFG_ES0_EN, lan966x,
+ REW_PORT_CFG(lan966x->ports[p]->chip_port));
}
}
+ /* Statistics: Use ESDX from ES0 if hit, otherwise no counting */
+ lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1),
+ REW_STAT_CFG_STAT_MODE, lan966x,
+ REW_STAT_CFG);
+
lan966x->vcap_ctrl = ctrl;
return 0;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
index a7edf524eedb..dc9af480bfea 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
@@ -281,6 +281,7 @@ static int sparx5_create_port(struct sparx5 *sparx5,
spx5_port->custom_etype = 0x8880; /* Vitesse */
spx5_port->phylink_pcs.poll = true;
spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops;
+ spx5_port->phylink_pcs.neg_mode = true;
spx5_port->is_mrouter = false;
INIT_LIST_HEAD(&spx5_port->tc_templates);
sparx5->ports[config->portno] = spx5_port;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
index bb97d27a1da4..f8562c1a894d 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
@@ -91,8 +91,7 @@ static void sparx5_pcs_get_state(struct phylink_pcs *pcs,
state->pause = status.pause;
}
-static int sparx5_pcs_config(struct phylink_pcs *pcs,
- unsigned int mode,
+static int sparx5_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -104,8 +103,9 @@ static int sparx5_pcs_config(struct phylink_pcs *pcs,
conf = port->conf;
conf.power_down = false;
conf.portmode = interface;
- conf.inband = phylink_autoneg_inband(mode);
- conf.autoneg = phylink_test(advertising, Autoneg);
+ conf.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED ||
+ neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
+ conf.autoneg = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;
conf.pause_adv = 0;
if (phylink_test(advertising, Pause))
conf.pause_adv |= ADVERTISE_1000XPAUSE;
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
index a556c4419986..c3569a4c7b69 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
+++ b/drivers/net/ethernet/microchip/vcap/vcap_ag_api.h
@@ -3,8 +3,8 @@
* Microchip VCAP API
*/
-/* This file is autogenerated by cml-utils 2023-02-16 11:41:14 +0100.
- * Commit ID: be85f176b3a151fa748dcaf97c8824a5c2e065f3
+/* This file is autogenerated by cml-utils 2023-03-13 10:16:42 +0100.
+ * Commit ID: 259f0efd6d6d91bfbf62858de153cc757b6bffa3 (dirty)
*/
#ifndef __VCAP_AG_API__
@@ -51,6 +51,7 @@ enum vcap_keyfield_set {
VCAP_KFS_RT, /* lan966x is1 X1 */
VCAP_KFS_SMAC_SIP4, /* lan966x is2 X1 */
VCAP_KFS_SMAC_SIP6, /* lan966x is2 X2 */
+ VCAP_KFS_VID, /* lan966x es0 X1 */
};
/* List of keyfields with description
@@ -79,7 +80,7 @@ enum vcap_keyfield_set {
* Second DEI in multiple vlan tags (inner tag)
* VCAP_KF_8021Q_DEI2: W1, sparx5: is0
* Third DEI in multiple vlan tags (not always available)
- * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2
+ * VCAP_KF_8021Q_DEI_CLS: W1, sparx5: is2/es2, lan966x: is2/es0
* Classified DEI
* VCAP_KF_8021Q_PCP0: W3, sparx5: is0, lan966x: is1
* First PCP in multiple vlan tags (outer tag or default port tag)
@@ -87,7 +88,7 @@ enum vcap_keyfield_set {
* Second PCP in multiple vlan tags (inner tag)
* VCAP_KF_8021Q_PCP2: W3, sparx5: is0
* Third PCP in multiple vlan tags (not always available)
- * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2
+ * VCAP_KF_8021Q_PCP_CLS: W3, sparx5: is2/es2, lan966x: is2/es0
* Classified PCP
* VCAP_KF_8021Q_TPID: W3, sparx5: es0
* TPID for outer tag: 0: Customer TPID 1: Service TPID (88A8 or programmable)
@@ -104,7 +105,7 @@ enum vcap_keyfield_set {
* VCAP_KF_8021Q_VID2: W12, sparx5: is0
* Third VID in multiple vlan tags (not always available)
* VCAP_KF_8021Q_VID_CLS: sparx5 is2 W13, sparx5 es0 W13, sparx5 es2 W13,
- * lan966x is2 W12
+ * lan966x is2 W12, lan966x es0 W12
* Classified VID
* VCAP_KF_8021Q_VLAN_DBL_TAGGED_IS: W1, lan966x: is1
* Set if frame has two or more Q-tags. Independent of port VLAN awareness
@@ -146,10 +147,10 @@ enum vcap_keyfield_set {
* VCAP_KF_IF_EGR_PORT_MASK_RNG: W3, sparx5: es2
* Select which 32 port group is available in IF_EGR_PORT (or virtual ports or
* CPU queue)
- * VCAP_KF_IF_EGR_PORT_NO: W7, sparx5: es0
+ * VCAP_KF_IF_EGR_PORT_NO: sparx5 es0 W7, lan966x es0 W4
* Egress port number
* VCAP_KF_IF_IGR_PORT: sparx5 is0 W7, sparx5 es2 W9, lan966x is1 W3, lan966x
- * is2 W4
+ * is2 W4, lan966x es0 W4
* Sparx5: Logical ingress port number retrieved from
* ANA_CL::PORT_ID_CFG.LPORT_NUM or ERLEG, LAN966x: ingress port nunmber
* VCAP_KF_IF_IGR_PORT_MASK: sparx5 is0 W65, sparx5 is2 W32, sparx5 is2 W65,
@@ -178,11 +179,12 @@ enum vcap_keyfield_set {
* Payload after IPv6 header
* VCAP_KF_IP_SNAP_IS: W1, sparx5: is0, lan966x: is1
* Set if frame is IPv4, IPv6, or SNAP frame
- * VCAP_KF_ISDX_CLS: W12, sparx5: is2/es0/es2
+ * VCAP_KF_ISDX_CLS: sparx5 is2 W12, sparx5 es0 W12, sparx5 es2 W12, lan966x es0
+ * W8
* Classified ISDX
- * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2
+ * VCAP_KF_ISDX_GT0_IS: W1, sparx5: is2/es0/es2, lan966x: is2/es0
* Set if classified ISDX > 0
- * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2
+ * VCAP_KF_L2_BC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0
* Set if frame's destination MAC address is the broadcast address
* (FF-FF-FF-FF-FF-FF).
* VCAP_KF_L2_DMAC: W48, sparx5: is0/is2/es2, lan966x: is1/is2
@@ -195,7 +197,7 @@ enum vcap_keyfield_set {
* LLC header and data after up to two VLAN tags and the type/length field
* VCAP_KF_L2_MAC: W48, lan966x: is1
* MAC address (FIRST=1: SMAC, FIRST=0: DMAC)
- * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2
+ * VCAP_KF_L2_MC_IS: W1, sparx5: is0/is2/es2, lan966x: is1/is2/es0
* Set if frame's destination MAC address is a multicast address (bit 40 = 1).
* VCAP_KF_L2_PAYLOAD0: W16, lan966x: is2
* Payload bytes 0-1 after the frame's EtherType
@@ -213,7 +215,7 @@ enum vcap_keyfield_set {
* SNAP header after LLC header (AA-AA-03)
* VCAP_KF_L3_DIP_EQ_SIP_IS: W1, sparx5: is2/es2, lan966x: is2
* Set if Src IP matches Dst IP address
- * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2
+ * VCAP_KF_L3_DPL_CLS: W1, sparx5: es0/es2, lan966x: es0
* The frames drop precedence level
* VCAP_KF_L3_DSCP: W6, sparx5: is0, lan966x: is1
* Frame's DSCP value
@@ -330,8 +332,12 @@ enum vcap_keyfield_set {
* Frame's OAM version
* VCAP_KF_OAM_Y1731_IS: W1, sparx5: is2/es2, lan966x: is2
* Set if frame's EtherType = 0x8902
+ * VCAP_KF_PDU_TYPE: W4, lan966x: es0
+ * PDU type value (none, OAM CCM, MRP, DLR, RTE, IPv4, IPv6, OAM non-CCM)
* VCAP_KF_PROT_ACTIVE: W1, sparx5: es0/es2
* Protection is active
+ * VCAP_KF_RTP_ID: W10, lan966x: es0
+ * Classified RTP_ID
* VCAP_KF_RT_FRMID: W32, lan966x: is1
* Profinet or OPC-UA FrameId
* VCAP_KF_RT_TYPE: W2, lan966x: is1
@@ -470,7 +476,9 @@ enum vcap_key_field {
VCAP_KF_OAM_OPCODE,
VCAP_KF_OAM_VER,
VCAP_KF_OAM_Y1731_IS,
+ VCAP_KF_PDU_TYPE,
VCAP_KF_PROT_ACTIVE,
+ VCAP_KF_RTP_ID,
VCAP_KF_RT_FRMID,
VCAP_KF_RT_TYPE,
VCAP_KF_RT_VLAN_IDX,
@@ -489,6 +497,7 @@ enum vcap_actionfield_set {
VCAP_AFS_FULL, /* sparx5 is0 X3 */
VCAP_AFS_S1, /* lan966x is1 X1 */
VCAP_AFS_SMAC_SIP, /* lan966x is2 X1 */
+ VCAP_AFS_VID, /* lan966x es0 X1 */
};
/* List of actionfields with description
@@ -523,9 +532,9 @@ enum vcap_actionfield_set {
* while bits 1:0 control first lookup. Encoding per lookup: 0: Disabled. 1:
* Extract 40 bytes after position corresponding to the location of the IPv4
* header and use as key. 2: Extract 40 bytes after SMAC and use as key
- * VCAP_AF_DEI_A_VAL: W1, sparx5: es0
+ * VCAP_AF_DEI_A_VAL: W1, sparx5: es0, lan966x: es0
* DEI used in ES0 tag A. See TAG_A_DEI_SEL.
- * VCAP_AF_DEI_B_VAL: W1, sparx5: es0
+ * VCAP_AF_DEI_B_VAL: W1, sparx5: es0, lan966x: es0
* DEI used in ES0 tag B. See TAG_B_DEI_SEL.
* VCAP_AF_DEI_C_VAL: W1, sparx5: es0
* DEI used in ES0 tag C. See TAG_C_DEI_SEL.
@@ -556,7 +565,7 @@ enum vcap_actionfield_set {
* VCAP_AF_ES2_REW_CMD: W3, sparx5: es2
* Command forwarded to REW: 0: No action. 1: SWAP MAC addresses. 2: Do L2CP
* DMAC translation when entering or leaving a tunnel.
- * VCAP_AF_ESDX: W13, sparx5: es0
+ * VCAP_AF_ESDX: sparx5 es0 W13, lan966x es0 W8
* Egress counter index. Used to index egress counter set as defined in
* REW::STAT_CFG.
* VCAP_AF_FWD_KILL_ENA: W1, lan966x: is2
@@ -652,9 +661,9 @@ enum vcap_actionfield_set {
* (input) AND ~PAG_OVERRIDE_MASK) OR (PAG_VAL AND PAG_OVERRIDE_MASK)
* VCAP_AF_PAG_VAL: W8, sparx5: is0, lan966x: is1
* See PAG_OVERRIDE_MASK.
- * VCAP_AF_PCP_A_VAL: W3, sparx5: es0
+ * VCAP_AF_PCP_A_VAL: W3, sparx5: es0, lan966x: es0
* PCP used in ES0 tag A. See TAG_A_PCP_SEL.
- * VCAP_AF_PCP_B_VAL: W3, sparx5: es0
+ * VCAP_AF_PCP_B_VAL: W3, sparx5: es0, lan966x: es0
* PCP used in ES0 tag B. See TAG_B_PCP_SEL.
* VCAP_AF_PCP_C_VAL: W3, sparx5: es0
* PCP used in ES0 tag C. See TAG_C_PCP_SEL.
@@ -691,10 +700,10 @@ enum vcap_actionfield_set {
* Selects tag C mode: 0: Do not push tag C. 1: Push tag C if
* IFH.VSTAX.TAG.WAS_TAGGED = 1. 2: Push tag C if IFH.VSTAX.TAG.WAS_TAGGED = 0.
* 3: Push tag C if UNTAG_VID_ENA = 0 or (C-TAG.VID ! = VID_C_VAL).
- * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0
+ * VCAP_AF_PUSH_INNER_TAG: W1, sparx5: es0, lan966x: es0
* Controls inner tagging. 0: Do not push ES0 tag B as inner tag. 1: Push ES0
* tag B as inner tag.
- * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0
+ * VCAP_AF_PUSH_OUTER_TAG: W2, sparx5: es0, lan966x: es0
* Controls outer tagging. 0: No ES0 tag A: Port tag is allowed if enabled on
* port. 1: ES0 tag A: Push ES0 tag A. No port tag. 2: Force port tag: Always
* push port tag. No ES0 tag A. 3: Force untag: Never push port tag or ES0 tag
@@ -720,29 +729,29 @@ enum vcap_actionfield_set {
* VCAP_AF_SWAP_MACS_ENA: W1, sparx5: es0
* This setting is only active when FWD_SEL = 1 or FWD_SEL = 2 and PIPELINE_ACT
* = LBK_ASM. 0: No action. 1: Swap MACs and clear bit 40 in new SMAC.
- * VCAP_AF_TAG_A_DEI_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_DEI_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag A. 0: Classified DEI. 1: DEI_A_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: DP.
- * VCAP_AF_TAG_A_PCP_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_PCP_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag A. 0: Classified PCP. 1: PCP_A_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: QoS class.
- * VCAP_AF_TAG_A_TPID_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_A_TPID_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects TPID for ES0 tag A: 0: 0x8100. 1: 0x88A8. 2: Custom
* (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else
* custom.
- * VCAP_AF_TAG_A_VID_SEL: W2, sparx5: es0
+ * VCAP_AF_TAG_A_VID_SEL: sparx5 es0 W2, lan966x es0 W1
* Selects VID for ES0 tag A. 0: Classified VID + VID_A_VAL. 1: VID_A_VAL.
- * VCAP_AF_TAG_B_DEI_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_DEI_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag B. 0: Classified DEI. 1: DEI_B_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: DP.
- * VCAP_AF_TAG_B_PCP_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_PCP_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects PCP for ES0 tag B. 0: Classified PCP. 1: PCP_B_VAL. 2: DP and QoS
* mapped to PCP (per port table). 3: QoS class.
- * VCAP_AF_TAG_B_TPID_SEL: W3, sparx5: es0
+ * VCAP_AF_TAG_B_TPID_SEL: sparx5 es0 W3, lan966x es0 W2
* Selects TPID for ES0 tag B. 0: 0x8100. 1: 0x88A8. 2: Custom
* (REW:PORT:PORT_VLAN_CFG.PORT_TPID). 3: If IFH.TAG_TYPE = 0 then 0x8100 else
* custom.
- * VCAP_AF_TAG_B_VID_SEL: W2, sparx5: es0
+ * VCAP_AF_TAG_B_VID_SEL: sparx5 es0 W2, lan966x es0 W1
* Selects VID for ES0 tag B. 0: Classified VID + VID_B_VAL. 1: VID_B_VAL.
* VCAP_AF_TAG_C_DEI_SEL: W3, sparx5: es0
* Selects DEI source for ES0 tag C. 0: Classified DEI. 1: DEI_C_VAL. 2:
@@ -770,9 +779,9 @@ enum vcap_actionfield_set {
* VCAP_AF_UNTAG_VID_ENA: W1, sparx5: es0
* Controls insertion of tag C. Untag or insert mode can be selected. See
* PUSH_CUSTOMER_TAG.
- * VCAP_AF_VID_A_VAL: W12, sparx5: es0
+ * VCAP_AF_VID_A_VAL: W12, sparx5: es0, lan966x: es0
* VID used in ES0 tag A. See TAG_A_VID_SEL.
- * VCAP_AF_VID_B_VAL: W12, sparx5: es0
+ * VCAP_AF_VID_B_VAL: W12, sparx5: es0, lan966x: es0
* VID used in ES0 tag B. See TAG_B_VID_SEL.
* VCAP_AF_VID_C_VAL: W12, sparx5: es0
* VID used in ES0 tag C. See TAG_C_VID_SEL.
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c
index 5675b0962bc3..15a3a31b15d4 100644
--- a/drivers/net/ethernet/microchip/vcap/vcap_api.c
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c
@@ -1021,18 +1021,32 @@ static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri,
list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list) {
newckf = kmemdup(ckf, sizeof(*newckf), GFP_KERNEL);
if (!newckf)
- return ERR_PTR(-ENOMEM);
+ goto err;
list_add_tail(&newckf->ctrl.list, &duprule->data.keyfields);
}
list_for_each_entry(caf, &ri->data.actionfields, ctrl.list) {
newcaf = kmemdup(caf, sizeof(*newcaf), GFP_KERNEL);
if (!newcaf)
- return ERR_PTR(-ENOMEM);
+ goto err;
list_add_tail(&newcaf->ctrl.list, &duprule->data.actionfields);
}
return duprule;
+
+err:
+ list_for_each_entry_safe(ckf, newckf, &duprule->data.keyfields, ctrl.list) {
+ list_del(&ckf->ctrl.list);
+ kfree(ckf);
+ }
+
+ list_for_each_entry_safe(caf, newcaf, &duprule->data.actionfields, ctrl.list) {
+ list_del(&caf->ctrl.list);
+ kfree(caf);
+ }
+
+ kfree(duprule);
+ return ERR_PTR(-ENOMEM);
}
static void vcap_apply_width(u8 *dst, int width, int bytes)
@@ -1121,7 +1135,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri,
vcap_copy_from_w32be(field->data.u128.value, value,
field_size, width);
break;
- };
+ }
} else {
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
@@ -1162,7 +1176,7 @@ static void vcap_copy_to_client_actionfield(struct vcap_rule_internal *ri,
value,
width, field_size);
break;
- };
+ }
}
}
@@ -1236,7 +1250,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri,
vcap_copy_from_w32be(field->data.u128.mask, mask,
field_size, width);
break;
- };
+ }
} else {
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
@@ -1284,7 +1298,7 @@ static void vcap_copy_to_client_keyfield(struct vcap_rule_internal *ri,
value, mask,
width, field_size);
break;
- };
+ }
}
}
diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
index 9d1507eba5b9..2bd1d74021f7 100644
--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
+++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
@@ -627,7 +627,7 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,
if (WARN_ON(cq->id >= gc->max_num_cqs))
return -EPROTO;
- gc->cq_table = vzalloc(gc->max_num_cqs * sizeof(struct gdma_queue *));
+ gc->cq_table = vcalloc(gc->max_num_cqs, sizeof(struct gdma_queue *));
if (!gc->cq_table)
return -ENOMEM;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index d907727c7b7a..c2ad0921e893 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -8,6 +8,7 @@
#include <linux/ethtool.h>
#include <linux/filter.h>
#include <linux/mm.h>
+#include <linux/pci.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
@@ -179,6 +180,14 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
pkg.tx_oob.s_oob.short_vp_offset = txq->vp_offset;
}
+ if (skb_vlan_tag_present(skb)) {
+ pkt_fmt = MANA_LONG_PKT_FMT;
+ pkg.tx_oob.l_oob.inject_vlan_pri_tag = 1;
+ pkg.tx_oob.l_oob.pcp = skb_vlan_tag_get_prio(skb);
+ pkg.tx_oob.l_oob.dei = skb_vlan_tag_get_cfi(skb);
+ pkg.tx_oob.l_oob.vlan_id = skb_vlan_tag_get_id(skb);
+ }
+
pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt;
if (pkt_fmt == MANA_SHORT_PKT_FMT) {
@@ -972,7 +981,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
bool update_tab)
{
u16 num_entries = MANA_INDIRECT_TABLE_SIZE;
- struct mana_cfg_rx_steer_req *req = NULL;
+ struct mana_cfg_rx_steer_req_v2 *req;
struct mana_cfg_rx_steer_resp resp = {};
struct net_device *ndev = apc->ndev;
mana_handle_t *req_indir_tab;
@@ -987,6 +996,8 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size,
sizeof(resp));
+ req->hdr.req.msg_version = GDMA_MESSAGE_V2;
+
req->vport = apc->port_handle;
req->num_indir_entries = num_entries;
req->indir_tab_offset = sizeof(*req);
@@ -996,6 +1007,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
req->update_hashkey = update_key;
req->update_indir_tab = update_tab;
req->default_rxobj = apc->default_rxobj;
+ req->cqe_coalescing_enable = 0;
if (update_key)
memcpy(&req->hashkey, apc->hashkey, MANA_HASH_KEY_SIZE);
@@ -1457,6 +1469,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L3);
}
+ if (cqe->rx_vlantag_present) {
+ u16 vlan_tci = cqe->rx_vlan_id;
+
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+ }
+
u64_stats_update_begin(&rx_stats->syncp);
rx_stats->packets++;
rx_stats->bytes += pkt_len;
@@ -2328,9 +2346,12 @@ int mana_attach(struct net_device *ndev)
static int mana_dealloc_queues(struct net_device *ndev)
{
struct mana_port_context *apc = netdev_priv(ndev);
+ unsigned long timeout = jiffies + 120 * HZ;
struct gdma_dev *gd = apc->ac->gdma_dev;
struct mana_txq *txq;
+ struct sk_buff *skb;
int i, err;
+ u32 tsleep;
if (apc->port_is_up)
return -EINVAL;
@@ -2346,15 +2367,40 @@ static int mana_dealloc_queues(struct net_device *ndev)
* to false, but it doesn't matter since mana_start_xmit() drops any
* new packets due to apc->port_is_up being false.
*
- * Drain all the in-flight TX packets
+ * Drain all the in-flight TX packets.
+ * A timeout of 120 seconds for all the queues is used.
+ * This will break the while loop when h/w is not responding.
+ * This value of 120 has been decided here considering max
+ * number of queues.
*/
+
for (i = 0; i < apc->num_queues; i++) {
txq = &apc->tx_qp[i].txq;
-
- while (atomic_read(&txq->pending_sends) > 0)
- usleep_range(1000, 2000);
+ tsleep = 1000;
+ while (atomic_read(&txq->pending_sends) > 0 &&
+ time_before(jiffies, timeout)) {
+ usleep_range(tsleep, tsleep + 1000);
+ tsleep <<= 1;
+ }
+ if (atomic_read(&txq->pending_sends)) {
+ err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+ if (err) {
+ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+ err, atomic_read(&txq->pending_sends),
+ txq->gdma_txq_id);
+ }
+ break;
+ }
}
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i].txq;
+ while ((skb = skb_dequeue(&txq->pending_skbs))) {
+ mana_unmap_skb(skb, apc);
+ dev_kfree_skb_any(skb);
+ }
+ atomic_set(&txq->pending_sends, 0);
+ }
/* We're 100% sure the queues can no longer be woken up, because
* we're sure now mana_poll_tx_cq() can't be running.
*/
@@ -2451,8 +2497,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
ndev->hw_features |= NETIF_F_RXCSUM;
ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
ndev->hw_features |= NETIF_F_RXHASH;
- ndev->features = ndev->hw_features;
- ndev->vlan_features = 0;
+ ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX;
+ ndev->vlan_features = ndev->features;
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT;
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 1f5f00b30441..56ccbd4c37fe 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2925,10 +2925,8 @@ int ocelot_init(struct ocelot *ocelot)
}
}
- mutex_init(&ocelot->ptp_lock);
mutex_init(&ocelot->mact_lock);
mutex_init(&ocelot->fwd_domain_lock);
- mutex_init(&ocelot->tas_lock);
spin_lock_init(&ocelot->ptp_clock_lock);
spin_lock_init(&ocelot->ts_id_lock);
diff --git a/drivers/net/ethernet/mscc/ocelot_fdma.c b/drivers/net/ethernet/mscc/ocelot_fdma.c
index 8e3894cf5f7c..83a3ce0c568e 100644
--- a/drivers/net/ethernet/mscc/ocelot_fdma.c
+++ b/drivers/net/ethernet/mscc/ocelot_fdma.c
@@ -368,7 +368,8 @@ static bool ocelot_fdma_receive_skb(struct ocelot *ocelot, struct sk_buff *skb)
if (unlikely(!ndev))
return false;
- pskb_trim(skb, skb->len - ETH_FCS_LEN);
+ if (pskb_trim(skb, skb->len - ETH_FCS_LEN))
+ return false;
skb->dev = ndev;
skb->protocol = eth_type_trans(skb, skb->dev);
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index ee052404eb55..e0916afcddfb 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -592,6 +592,16 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
return -EOPNOTSUPP;
}
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
+ struct flow_match_meta match;
+
+ flow_rule_match_meta(rule, &match);
+ if (match.mask->l2_miss) {
+ NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
+ return -EOPNOTSUPP;
+ }
+ }
+
/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
if (!ingress) {
ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
diff --git a/drivers/net/ethernet/mscc/ocelot_mm.c b/drivers/net/ethernet/mscc/ocelot_mm.c
index fb3145118d68..c815ae64e39d 100644
--- a/drivers/net/ethernet/mscc/ocelot_mm.c
+++ b/drivers/net/ethernet/mscc/ocelot_mm.c
@@ -67,10 +67,13 @@ void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port)
val = mm->preemptible_tcs;
/* Cut through switching doesn't work for preemptible priorities,
- * so first make sure it is disabled.
+ * so first make sure it is disabled. Also, changing the preemptible
+ * TCs affects the oversized frame dropping logic, so that needs to be
+ * re-triggered. And since tas_guard_bands_update() also implicitly
+ * calls cut_through_fwd(), we don't need to explicitly call it.
*/
mm->active_preemptible_tcs = val;
- ocelot->ops->cut_through_fwd(ocelot);
+ ocelot->ops->tas_guard_bands_update(ocelot, port);
dev_dbg(ocelot->dev,
"port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n",
@@ -89,17 +92,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port,
{
struct ocelot_mm_state *mm = &ocelot->mm[port];
- mutex_lock(&ocelot->fwd_domain_lock);
+ lockdep_assert_held(&ocelot->fwd_domain_lock);
if (mm->preemptible_tcs == preemptible_tcs)
- goto out_unlock;
+ return;
mm->preemptible_tcs = preemptible_tcs;
ocelot_port_update_active_preemptible_tcs(ocelot, port);
-
-out_unlock:
- mutex_unlock(&ocelot->fwd_domain_lock);
}
static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c
index 2180ae94c744..cb32234a5bf1 100644
--- a/drivers/net/ethernet/mscc/ocelot_ptp.c
+++ b/drivers/net/ethernet/mscc/ocelot_ptp.c
@@ -439,8 +439,12 @@ static int ocelot_ipv6_ptp_trap_del(struct ocelot *ocelot, int port)
static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port,
bool l2, bool l4)
{
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
int err;
+ ocelot_port->trap_proto &= ~(OCELOT_PROTO_PTP_L2 |
+ OCELOT_PROTO_PTP_L4);
+
if (l2)
err = ocelot_l2_ptp_trap_add(ocelot, port);
else
@@ -464,6 +468,11 @@ static int ocelot_setup_ptp_traps(struct ocelot *ocelot, int port,
if (err)
return err;
+ if (l2)
+ ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L2;
+ if (l4)
+ ocelot_port->trap_proto |= OCELOT_PROTO_PTP_L4;
+
return 0;
err_ipv6:
@@ -474,10 +483,38 @@ err_ipv4:
return err;
}
+static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
+{
+ if ((proto & OCELOT_PROTO_PTP_L2) && (proto & OCELOT_PROTO_PTP_L4))
+ return HWTSTAMP_FILTER_PTP_V2_EVENT;
+ else if (proto & OCELOT_PROTO_PTP_L2)
+ return HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+ else if (proto & OCELOT_PROTO_PTP_L4)
+ return HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+
+ return HWTSTAMP_FILTER_NONE;
+}
+
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
{
- return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
- sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct hwtstamp_config cfg = {};
+
+ switch (ocelot_port->ptp_cmd) {
+ case IFH_REW_OP_TWO_STEP_PTP:
+ cfg.tx_type = HWTSTAMP_TX_ON;
+ break;
+ case IFH_REW_OP_ORIGIN_PTP:
+ cfg.tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
+ break;
+ default:
+ cfg.tx_type = HWTSTAMP_TX_OFF;
+ break;
+ }
+
+ cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
EXPORT_SYMBOL(ocelot_hwstamp_get);
@@ -509,8 +546,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
return -ERANGE;
}
- mutex_lock(&ocelot->ptp_lock);
-
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
break;
@@ -531,28 +566,14 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
l4 = true;
break;
default:
- mutex_unlock(&ocelot->ptp_lock);
return -ERANGE;
}
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
- if (err) {
- mutex_unlock(&ocelot->ptp_lock);
+ if (err)
return err;
- }
- if (l2 && l4)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
- else if (l2)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
- else if (l4)
- cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
- else
- cfg.rx_filter = HWTSTAMP_FILTER_NONE;
-
- /* Commit back the result & save it */
- memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
- mutex_unlock(&ocelot->ptp_lock);
+ cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}
@@ -824,11 +845,6 @@ int ocelot_init_timestamp(struct ocelot *ocelot,
ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
- /* There is no device reconfiguration, PTP Rx stamping is always
- * enabled.
- */
- ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-
return 0;
}
EXPORT_SYMBOL(ocelot_init_timestamp);
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index c5687d94ea88..7b7e1c5b00f4 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -66,6 +66,7 @@
#include <linux/slab.h>
#include <linux/prefetch.h>
#include <net/checksum.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <asm/byteorder.h>
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
index bf6bae557158..8c6954c58a88 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c
@@ -311,8 +311,6 @@ nfp_devlink_flash_update(struct devlink *devlink,
}
const struct devlink_ops nfp_devlink_ops = {
- .port_split = nfp_devlink_port_split,
- .port_unsplit = nfp_devlink_port_unsplit,
.sb_pool_get = nfp_devlink_sb_pool_get,
.sb_pool_set = nfp_devlink_sb_pool_set,
.eswitch_mode_get = nfp_devlink_eswitch_mode_get,
@@ -321,6 +319,11 @@ const struct devlink_ops nfp_devlink_ops = {
.flash_update = nfp_devlink_flash_update,
};
+static const struct devlink_port_ops nfp_devlink_port_ops = {
+ .port_split = nfp_devlink_port_split,
+ .port_unsplit = nfp_devlink_port_unsplit,
+};
+
int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
{
struct devlink_port_attrs attrs = {};
@@ -351,7 +354,8 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
devlink = priv_to_devlink(app->pf);
- return devl_port_register(devlink, &port->dl_port, port->eth_id);
+ return devl_port_register_with_ops(devlink, &port->dl_port,
+ port->eth_id, &nfp_devlink_port_ops);
}
void nfp_devlink_port_unregister(struct nfp_port *port)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 62f0bf91d1e1..6b1fb5708434 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -53,6 +53,8 @@
#include "crypto/crypto.h"
#include "crypto/fw.h"
+static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr);
+
/**
* nfp_net_get_fw_version() - Read and parse the FW version
* @fw_ver: Output fw_version structure to read to
@@ -598,7 +600,7 @@ nfp_net_tls_tx(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,
if (likely(!dp->ktls_tx))
return skb;
- if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
+ if (!tls_is_skb_tx_device_offloaded(skb))
return skb;
datalen = skb->len - skb_tcp_all_headers(skb);
@@ -666,7 +668,7 @@ void nfp_net_tls_tx_undo(struct sk_buff *skb, u64 tls_handle)
if (!tls_handle)
return;
- if (WARN_ON_ONCE(!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk)))
+ if (WARN_ON_ONCE(!tls_is_skb_tx_device_offloaded(skb)))
return;
datalen = skb->len - skb_tcp_all_headers(skb);
@@ -1084,6 +1086,9 @@ static int nfp_net_netdev_close(struct net_device *netdev)
/* Step 2: Tell NFP
*/
+ if (nn->cap_w1 & NFP_NET_CFG_CTRL_MCAST_FILTER)
+ __dev_mc_unsync(netdev, nfp_net_mc_unsync);
+
nfp_net_clear_config_and_disable(nn);
nfp_port_configure(netdev, false);
@@ -2418,6 +2423,8 @@ static void nfp_net_rss_init(struct nfp_net *nn)
/* Enable IPv4/IPv6 TCP by default */
nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP |
NFP_NET_CFG_RSS_IPV6_TCP |
+ NFP_NET_CFG_RSS_IPV4_UDP |
+ NFP_NET_CFG_RSS_IPV6_UDP |
FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc) |
NFP_NET_CFG_RSS_MASK;
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index dfedb52b7e70..e75cbb287625 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -436,49 +436,41 @@ static void nfp_add_media_link_mode(struct nfp_port *port,
struct nfp_eth_table_port *eth_port,
struct ethtool_link_ksettings *cmd)
{
- u64 supported_modes[2], advertised_modes[2];
- struct nfp_eth_media_buf ethm = {
- .eth_index = eth_port->eth_index,
- };
- struct nfp_cpp *cpp = port->app->cpp;
-
- if (nfp_eth_read_media(cpp, &ethm)) {
- bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
- return;
- }
-
bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
- for (u32 i = 0; i < 2; i++) {
- supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]);
- advertised_modes[i] = le64_to_cpu(ethm.advertised_modes[i]);
- }
-
for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) {
if (i < 64) {
- if (supported_modes[0] & BIT_ULL(i)) {
+ if (eth_port->link_modes_supp[0] & BIT_ULL(i)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
- if (advertised_modes[0] & BIT_ULL(i))
+ if (eth_port->link_modes_ad[0] & BIT_ULL(i))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
} else {
- if (supported_modes[1] & BIT_ULL(i - 64)) {
+ if (eth_port->link_modes_supp[1] & BIT_ULL(i - 64)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
- if (advertised_modes[1] & BIT_ULL(i - 64))
+ if (eth_port->link_modes_ad[1] & BIT_ULL(i - 64))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
}
}
+
+ /* We take all speeds as supported when it fails to read
+ * link modes due to old management firmware that doesn't
+ * support link modes reading or error occurring, so that
+ * speed change of this port is allowed.
+ */
+ if (bitmap_empty(port->speed_bitmap, NFP_SUP_SPEED_NUMBER))
+ bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
}
/**
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
index 781edc451bd4..6e044ac04917 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h
@@ -196,6 +196,9 @@ enum nfp_ethtool_link_mode_list {
* subports)
* @ports.is_split: is interface part of a split port
* @ports.fec_modes_supported: bitmap of FEC modes supported
+ *
+ * @ports.link_modes_supp: bitmap of link modes supported
+ * @ports.link_modes_ad: bitmap of link modes advertised
*/
struct nfp_eth_table {
unsigned int count;
@@ -235,6 +238,9 @@ struct nfp_eth_table {
bool is_split;
unsigned int fec_modes_supported;
+
+ u64 link_modes_supp[2];
+ u64 link_modes_ad[2];
} ports[];
};
@@ -313,7 +319,6 @@ struct nfp_eth_media_buf {
};
int nfp_nsp_read_media(struct nfp_nsp *state, void *buf, unsigned int size);
-int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm);
#define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
index 570ac1bb2122..9d62085d772a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
@@ -227,6 +227,30 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
entry->port_type = PORT_DA;
}
+static void
+nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry)
+{
+ struct nfp_eth_media_buf ethm = {
+ .eth_index = entry->eth_index,
+ };
+ unsigned int i;
+ int ret;
+
+ if (!nfp_nsp_has_read_media(nsp))
+ return;
+
+ ret = nfp_nsp_read_media(nsp, &ethm, sizeof(ethm));
+ if (ret) {
+ nfp_err(cpp, "Reading media link modes failed: %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < 2; i++) {
+ entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]);
+ entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]);
+ }
+}
+
/**
* nfp_eth_read_ports() - retrieve port information
* @cpp: NFP CPP handle
@@ -293,8 +317,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
&table->ports[j++]);
nfp_eth_calc_port_geometry(cpp, table);
- for (i = 0; i < table->count; i++)
+ for (i = 0; i < table->count; i++) {
nfp_eth_calc_port_type(cpp, &table->ports[i]);
+ nfp_eth_read_media(cpp, nsp, &table->ports[i]);
+ }
kfree(entries);
@@ -647,29 +673,3 @@ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
lanes, NSP_ETH_CTRL_SET_LANES);
}
-
-int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm)
-{
- struct nfp_nsp *nsp;
- int ret;
-
- nsp = nfp_nsp_open(cpp);
- if (IS_ERR(nsp)) {
- nfp_err(cpp, "Failed to access the NSP: %pe\n", nsp);
- return PTR_ERR(nsp);
- }
-
- if (!nfp_nsp_has_read_media(nsp)) {
- nfp_warn(cpp, "Reading media link modes not supported. Please update flash\n");
- ret = -EOPNOTSUPP;
- goto exit_close_nsp;
- }
-
- ret = nfp_nsp_read_media(nsp, ethm, sizeof(*ethm));
- if (ret)
- nfp_err(cpp, "Reading media link modes failed: %pe\n", ERR_PTR(ret));
-
-exit_close_nsp:
- nfp_nsp_close(nsp);
- return ret;
-}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
index 4e18b64dceb9..9651cc714ef2 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
@@ -5,7 +5,7 @@
config PCH_GBE
tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
- depends on PCI && (X86_32 || COMPILE_TEST)
+ depends on PCI && (MIPS_GENERIC || X86_32 || COMPILE_TEST)
depends on PTP_1588_CLOCK
select MII
select PTP_1588_CLOCK_PCH
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
index b8678da1cce5..ab7d217b98b3 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
@@ -353,12 +353,6 @@ err_out_reset:
ionic_reset(ionic);
err_out_teardown:
ionic_dev_teardown(ionic);
- pci_clear_master(pdev);
- /* Don't fail the probe for these errors, keep
- * the hw interface around for inspection
- */
- return 0;
-
err_out_unmap_bars:
ionic_unmap_bars(ionic);
err_out_pci_release_regions:
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index 9b2b96fa36af..3a6b0a9bc241 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -104,6 +104,15 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
}
+static void ionic_get_link_ext_stats(struct net_device *netdev,
+ struct ethtool_link_ext_stats *stats)
+{
+ struct ionic_lif *lif = netdev_priv(netdev);
+
+ if (lif->ionic->pdev->is_physfn)
+ stats->link_down_events = lif->link_down_count;
+}
+
static int ionic_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *ks)
{
@@ -1074,6 +1083,7 @@ static const struct ethtool_ops ionic_ethtool_ops = {
.get_regs_len = ionic_get_regs_len,
.get_regs = ionic_get_regs,
.get_link = ethtool_op_get_link,
+ .get_link_ext_stats = ionic_get_link_ext_stats,
.get_link_ksettings = ionic_get_link_ksettings,
.set_link_ksettings = ionic_set_link_ksettings,
.get_coalesce = ionic_get_coalesce,
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 957027e546b3..432fb93aa801 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -168,6 +168,7 @@ static void ionic_link_status_check(struct ionic_lif *lif)
}
} else {
if (netif_carrier_ok(netdev)) {
+ lif->link_down_count++;
netdev_info(netdev, "Link down\n");
netif_carrier_off(netdev);
}
@@ -474,11 +475,6 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
struct ionic_qcq *n_qcq)
{
- if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
- ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index);
- n_qcq->flags &= ~IONIC_QCQ_F_INTR;
- }
-
n_qcq->intr.vector = src_qcq->intr.vector;
n_qcq->intr.index = src_qcq->intr.index;
n_qcq->napi_qcq = src_qcq->napi_qcq;
@@ -560,7 +556,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
new->q.dev = dev;
new->flags = flags;
- new->q.info = vzalloc(num_descs * sizeof(*new->q.info));
+ new->q.info = vcalloc(num_descs, sizeof(*new->q.info));
if (!new->q.info) {
netdev_err(lif->netdev, "Cannot allocate queue info\n");
err = -ENOMEM;
@@ -581,7 +577,7 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
if (err)
goto err_out;
- new->cq.info = vzalloc(num_descs * sizeof(*new->cq.info));
+ new->cq.info = vcalloc(num_descs, sizeof(*new->cq.info));
if (!new->cq.info) {
netdev_err(lif->netdev, "Cannot allocate completion queue info\n");
err = -ENOMEM;
@@ -1821,6 +1817,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
static void ionic_tx_timeout_work(struct work_struct *ws)
{
struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work);
+ int err;
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
return;
@@ -1833,8 +1830,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
mutex_lock(&lif->queue_lock);
ionic_stop_queues_reconfig(lif);
- ionic_start_queues_reconfig(lif);
+ err = ionic_start_queues_reconfig(lif);
mutex_unlock(&lif->queue_lock);
+
+ if (err)
+ dev_err(lif->ionic->dev, "%s: Restarting queues failed\n", __func__);
}
static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
@@ -2804,17 +2804,22 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif,
if (err) {
dev_err(lif->ionic->dev,
"CMB restore failed: %d\n", err);
- goto errout;
+ goto err_out;
}
}
- ionic_start_queues_reconfig(lif);
- } else {
- /* This was detached in ionic_stop_queues_reconfig() */
- netif_device_attach(lif->netdev);
+ err = ionic_start_queues_reconfig(lif);
+ if (err) {
+ dev_err(lif->ionic->dev,
+ "CMB reconfig failed: %d\n", err);
+ goto err_out;
+ }
}
-errout:
+err_out:
+ /* This was detached in ionic_stop_queues_reconfig() */
+ netif_device_attach(lif->netdev);
+
return err;
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
index c9c4c46d5a16..fd2ea670e7d8 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h
@@ -201,6 +201,7 @@ struct ionic_lif {
u64 hw_features;
bool registered;
u16 lif_type;
+ unsigned int link_down_count;
unsigned int nmcast;
unsigned int nucast;
unsigned int nvlans;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
index f8682356d0cf..94d4f9413ab7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h
@@ -194,6 +194,22 @@ void qed_hw_remove(struct qed_dev *cdev);
struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn);
/**
+ * qed_ptt_acquire_context(): Allocate a PTT window honoring the context
+ * atomicy.
+ *
+ * @p_hwfn: HW device data.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: struct qed_ptt.
+ *
+ * Should be called at the entry point to the driver
+ * (at the beginning of an exported function).
+ */
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn,
+ bool is_atomic);
+
+/**
* qed_ptt_release(): Release PTT Window.
*
* @p_hwfn: HW device data.
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
index 3764190b948e..04602ac94708 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
@@ -693,13 +693,14 @@ static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
}
static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
- struct qed_fcoe_stats *p_stats)
+ struct qed_fcoe_stats *p_stats,
+ bool is_atomic)
{
struct qed_ptt *p_ptt;
memset(p_stats, 0, sizeof(*p_stats));
- p_ptt = qed_ptt_acquire(p_hwfn);
+ p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
if (!p_ptt) {
DP_ERR(p_hwfn, "Failed to acquire ptt\n");
@@ -973,19 +974,27 @@ static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
QED_SPQ_MODE_EBLOCK, NULL);
}
+static int qed_fcoe_stats_context(struct qed_dev *cdev,
+ struct qed_fcoe_stats *stats,
+ bool is_atomic)
+{
+ return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
{
- return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
+ return qed_fcoe_stats_context(cdev, stats, false);
}
void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats)
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic)
{
struct qed_fcoe_stats proto_stats;
/* Retrieve FW statistics */
memset(&proto_stats, 0, sizeof(proto_stats));
- if (qed_fcoe_stats(cdev, &proto_stats)) {
+ if (qed_fcoe_stats_context(cdev, &proto_stats, is_atomic)) {
DP_VERBOSE(cdev, QED_MSG_STORAGE,
"Failed to collect FCoE statistics\n");
return;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_fcoe.h b/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
index 19c85adf4ceb..214e8299ecb4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.h
@@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn);
void qed_fcoe_setup(struct qed_hwfn *p_hwfn);
void qed_fcoe_free(struct qed_hwfn *p_hwfn);
+/**
+ * qed_get_protocol_stats_fcoe(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats);
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic);
#else /* CONFIG_QED_FCOE */
static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
{
@@ -40,7 +52,8 @@ static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn) {}
static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {}
static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
- struct qed_mcp_fcoe_stats *stats)
+ struct qed_mcp_fcoe_stats *stats,
+ bool is_atomic)
{
}
#endif /* CONFIG_QED_FCOE */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c
index 554f30b0cfd5..6263f847b6b9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hw.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c
@@ -23,7 +23,10 @@
#include "qed_reg_addr.h"
#include "qed_sriov.h"
-#define QED_BAR_ACQUIRE_TIMEOUT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT 100000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY 10
/* Invalid values */
#define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1))
@@ -85,11 +88,21 @@ void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
{
+ return qed_ptt_acquire_context(p_hwfn, false);
+}
+
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic)
+{
struct qed_ptt *p_ptt;
- unsigned int i;
+ unsigned int i, count;
+
+ if (is_atomic)
+ count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT;
+ else
+ count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT;
/* Take the free PTT from the list */
- for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) {
+ for (i = 0; i < count; i++) {
spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
@@ -105,7 +118,12 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
}
spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
- usleep_range(1000, 2000);
+
+ if (is_atomic)
+ udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY);
+ else
+ usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP,
+ QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2);
}
DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
index 511ab214eb9c..980e7289b481 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
@@ -999,13 +999,14 @@ static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn,
}
static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn,
- struct qed_iscsi_stats *stats)
+ struct qed_iscsi_stats *stats,
+ bool is_atomic)
{
struct qed_ptt *p_ptt;
memset(stats, 0, sizeof(*stats));
- p_ptt = qed_ptt_acquire(p_hwfn);
+ p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
if (!p_ptt) {
DP_ERR(p_hwfn, "Failed to acquire ptt\n");
return -EAGAIN;
@@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev,
QED_SPQ_MODE_EBLOCK, NULL);
}
+static int qed_iscsi_stats_context(struct qed_dev *cdev,
+ struct qed_iscsi_stats *stats,
+ bool is_atomic)
+{
+ return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
{
- return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats);
+ return qed_iscsi_stats_context(cdev, stats, false);
}
static int qed_iscsi_change_mac(struct qed_dev *cdev,
@@ -1358,13 +1366,14 @@ static int qed_iscsi_change_mac(struct qed_dev *cdev,
}
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats)
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic)
{
struct qed_iscsi_stats proto_stats;
/* Retrieve FW statistics */
memset(&proto_stats, 0, sizeof(proto_stats));
- if (qed_iscsi_stats(cdev, &proto_stats)) {
+ if (qed_iscsi_stats_context(cdev, &proto_stats, is_atomic)) {
DP_VERBOSE(cdev, QED_MSG_STORAGE,
"Failed to collect ISCSI statistics\n");
return;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
index dec2b00259d4..974cb8d26608 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
@@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn);
*
* @cdev: Qed dev pointer.
* @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
*
+ * Context: The function should not sleep in case is_atomic == true.
* Return: Void.
*/
void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats);
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic);
#else /* IS_ENABLED(CONFIG_QED_ISCSI) */
static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
{
@@ -56,7 +59,8 @@ static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn) {}
static inline void
qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
- struct qed_mcp_iscsi_stats *stats) {}
+ struct qed_mcp_iscsi_stats *stats,
+ bool is_atomic) {}
#endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 7776d3bdd459..970b9aabbc3d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -1863,7 +1863,8 @@ static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn,
}
static void _qed_get_vport_stats(struct qed_dev *cdev,
- struct qed_eth_stats *stats)
+ struct qed_eth_stats *stats,
+ bool is_atomic)
{
u8 fw_vport = 0;
int i;
@@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
for_each_hwfn(cdev, i) {
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
- struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn)
- : NULL;
+ struct qed_ptt *p_ptt;
bool b_get_port_stats;
+ p_ptt = IS_PF(cdev) ? qed_ptt_acquire_context(p_hwfn, is_atomic)
+ : NULL;
if (IS_PF(cdev)) {
/* The main vport index is relative first */
if (qed_fw_vport(p_hwfn, 0, &fw_vport)) {
@@ -1901,6 +1903,13 @@ out:
void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
{
+ qed_get_vport_stats_context(cdev, stats, false);
+}
+
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+ struct qed_eth_stats *stats,
+ bool is_atomic)
+{
u32 i;
if (!cdev || cdev->recov_in_prog) {
@@ -1908,7 +1917,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
return;
}
- _qed_get_vport_stats(cdev, stats);
+ _qed_get_vport_stats(cdev, stats, is_atomic);
if (!cdev->reset_stats)
return;
@@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev)
if (!cdev->reset_stats) {
DP_INFO(cdev, "Reset stats not allocated\n");
} else {
- _qed_get_vport_stats(cdev, cdev->reset_stats);
+ _qed_get_vport_stats(cdev, cdev->reset_stats, false);
cdev->reset_stats->common.link_change_count = 0;
}
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.h b/drivers/net/ethernet/qlogic/qed/qed_l2.h
index a538cf478c14..2d2f82c785ad 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.h
@@ -249,8 +249,32 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
enum spq_mode comp_mode,
struct qed_spq_comp_cb *p_comp_data);
+/**
+ * qed_get_vport_stats(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ *
+ * Return: Void.
+ */
void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats);
+/**
+ * qed_get_vport_stats_context(): Fills provided statistics
+ * struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+ struct qed_eth_stats *stats,
+ bool is_atomic);
+
void qed_reset_vport_stats(struct qed_dev *cdev);
/**
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f5af83342856..c278f8893042 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -3092,7 +3092,7 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
switch (type) {
case QED_MCP_LAN_STATS:
- qed_get_vport_stats(cdev, &eth_stats);
+ qed_get_vport_stats_context(cdev, &eth_stats, true);
stats->lan_stats.ucast_rx_pkts =
eth_stats.common.rx_ucast_pkts;
stats->lan_stats.ucast_tx_pkts =
@@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
stats->lan_stats.fcs_err = -1;
break;
case QED_MCP_FCOE_STATS:
- qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
+ qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true);
break;
case QED_MCP_ISCSI_STATS:
- qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
+ qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true);
break;
default:
DP_VERBOSE(cdev, QED_MSG_SP,
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 4b004a728190..99df00c30b8c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -176,6 +176,15 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
}
#endif
+static int __maybe_unused qede_suspend(struct device *dev)
+{
+ dev_info(dev, "Device does not support suspend operation\n");
+
+ return -EOPNOTSUPP;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(qede_pm_ops, qede_suspend, NULL);
+
static const struct pci_error_handlers qede_err_handler = {
.error_detected = qede_io_error_detected,
};
@@ -190,6 +199,7 @@ static struct pci_driver qede_pci_driver = {
.sriov_configure = qede_sriov_configure,
#endif
.err_handler = &qede_err_handler,
+ .driver.pm = &qede_pm_ops,
};
static struct qed_eth_cb_ops qede_ll_ops = {
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index 0d80447d4d3b..d5c688a8d7be 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -1260,8 +1260,11 @@ static int emac_tso_csum(struct emac_adapter *adpt,
if (skb->protocol == htons(ETH_P_IP)) {
u32 pkt_len = ((unsigned char *)ip_hdr(skb) - skb->data)
+ ntohs(ip_hdr(skb)->tot_len);
- if (skb->len > pkt_len)
- pskb_trim(skb, pkt_len);
+ if (skb->len > pkt_len) {
+ ret = pskb_trim(skb, pkt_len);
+ if (unlikely(ret))
+ return ret;
+ }
}
hdr_len = skb_tcp_all_headers(skb);
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 4b19803a7dd0..6351a2dc13bc 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -623,6 +623,7 @@ struct rtl8169_private {
int cfg9346_usage_count;
unsigned supports_gmii:1;
+ unsigned aspm_manageable:1;
dma_addr_t counters_phys_addr;
struct rtl8169_counters *counters;
struct rtl8169_tc_offsets tc_offset;
@@ -2746,7 +2747,15 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
if (tp->mac_version < RTL_GIGA_MAC_VER_32)
return;
- if (enable) {
+ /* Don't enable ASPM in the chip if OS can't control ASPM */
+ if (enable && tp->aspm_manageable) {
+ /* On these chip versions ASPM can even harm
+ * bus communication of other PCI devices.
+ */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_43)
+ return;
+
rtl_mod_config5(tp, 0, ASPM_en);
rtl_mod_config2(tp, 0, ClkReqEn);
@@ -4514,10 +4523,6 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
}
if (napi_schedule_prep(&tp->napi)) {
- rtl_unlock_config_regs(tp);
- rtl_hw_aspm_clkreq_enable(tp, false);
- rtl_lock_config_regs(tp);
-
rtl_irq_disable(tp);
__napi_schedule(&tp->napi);
}
@@ -4577,14 +4582,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
work_done = rtl_rx(dev, tp, budget);
- if (work_done < budget && napi_complete_done(napi, work_done)) {
+ if (work_done < budget && napi_complete_done(napi, work_done))
rtl_irq_enable(tp);
- rtl_unlock_config_regs(tp);
- rtl_hw_aspm_clkreq_enable(tp, true);
- rtl_lock_config_regs(tp);
- }
-
return work_done;
}
@@ -5158,12 +5158,23 @@ done:
rtl_rar_set(tp, mac_addr);
}
+/* register is set if system vendor successfully tested ASPM 1.2 */
+static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
+{
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
+ r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
+ return true;
+
+ return false;
+}
+
static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct rtl8169_private *tp;
int jumbo_max, region, rc;
enum mac_version chipset;
struct net_device *dev;
+ u32 txconfig;
u16 xid;
dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
@@ -5195,40 +5206,46 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pcim_enable_device(pdev);
- if (rc < 0) {
- dev_err(&pdev->dev, "enable failure\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "enable failure\n");
if (pcim_set_mwi(pdev) < 0)
dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n");
/* use first MMIO region */
region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
- if (region < 0) {
- dev_err(&pdev->dev, "no MMIO resource found\n");
- return -ENODEV;
- }
+ if (region < 0)
+ return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n");
rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME);
- if (rc < 0) {
- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n");
tp->mmio_addr = pcim_iomap_table(pdev)[region];
- xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
+ txconfig = RTL_R32(tp, TxConfig);
+ if (txconfig == ~0U)
+ return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n");
+
+ xid = (txconfig >> 20) & 0xfcf;
/* Identify chip attached to board */
chipset = rtl8169_get_mac_version(xid, tp->supports_gmii);
- if (chipset == RTL_GIGA_MAC_NONE) {
- dev_err(&pdev->dev, "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", xid);
- return -ENODEV;
- }
-
+ if (chipset == RTL_GIGA_MAC_NONE)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n",
+ xid);
tp->mac_version = chipset;
+ /* Disable ASPM L1 as that cause random device stop working
+ * problems as well as full system hangs for some PCIe devices users.
+ */
+ if (rtl_aspm_is_safe(tp))
+ rc = 0;
+ else
+ rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
+ tp->aspm_manageable = !rc;
+
tp->dash_type = rtl_check_dash(tp);
tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
@@ -5246,10 +5263,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_hw_reset(tp);
rc = rtl_alloc_irq(tp);
- if (rc < 0) {
- dev_err(&pdev->dev, "Can't allocate interrupt\n");
- return rc;
- }
+ if (rc < 0)
+ return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n");
+
tp->irq = pci_irq_vector(pdev, 0);
INIT_WORK(&tp->wk.work, rtl_task);
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index fa6d6202b129..449ed1f5624c 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -90,6 +90,11 @@ static int rswitch_bpool_config(struct rswitch_private *priv)
return rswitch_reg_wait(priv->addr, CABPIRM, CABPIRM_BPR, CABPIRM_BPR);
}
+static void rswitch_coma_init(struct rswitch_private *priv)
+{
+ iowrite32(CABPPFLC_INIT_VALUE, priv->addr + CABPPFLC0);
+}
+
/* R-Switch-2 block (TOP) */
static void rswitch_top_init(struct rswitch_private *priv)
{
@@ -156,24 +161,6 @@ static int rswitch_gwca_axi_ram_reset(struct rswitch_private *priv)
return rswitch_reg_wait(priv->addr, GWARIRM, GWARIRM_ARR, GWARIRM_ARR);
}
-static void rswitch_gwca_set_rate_limit(struct rswitch_private *priv, int rate)
-{
- u32 gwgrlulc, gwgrlc;
-
- switch (rate) {
- case 1000:
- gwgrlulc = 0x0000005f;
- gwgrlc = 0x00010260;
- break;
- default:
- dev_err(&priv->pdev->dev, "%s: This rate is not supported (%d)\n", __func__, rate);
- return;
- }
-
- iowrite32(gwgrlulc, priv->addr + GWGRLULC);
- iowrite32(gwgrlc, priv->addr + GWGRLC);
-}
-
static bool rswitch_is_any_data_irq(struct rswitch_private *priv, u32 *dis, bool tx)
{
u32 *mask = tx ? priv->gwca.tx_irq_bits : priv->gwca.rx_irq_bits;
@@ -391,7 +378,7 @@ static int rswitch_gwca_queue_format(struct net_device *ndev,
linkfix->die_dt = DT_LINKFIX;
rswitch_desc_set_dptr(linkfix, gq->ring_dma);
- iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_EDE,
+ iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | GWDCC_EDE,
priv->addr + GWDCC_OFFS(gq->index));
return 0;
@@ -489,7 +476,8 @@ static int rswitch_gwca_queue_ext_ts_format(struct net_device *ndev,
linkfix->die_dt = DT_LINKFIX;
rswitch_desc_set_dptr(linkfix, gq->ring_dma);
- iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_ETS | GWDCC_EDE,
+ iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) |
+ GWDCC_ETS | GWDCC_EDE,
priv->addr + GWDCC_OFFS(gq->index));
return 0;
@@ -660,7 +648,8 @@ static int rswitch_gwca_hw_init(struct rswitch_private *priv)
iowrite32(lower_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC10);
iowrite32(upper_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC00);
iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDCC0);
- rswitch_gwca_set_rate_limit(priv, priv->gwca.speed);
+
+ iowrite32(GWTPC_PPPL(GWCA_IPV_NUM), priv->addr + GWTPC0);
for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
err = rswitch_rxdmac_init(priv, i);
@@ -740,7 +729,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
}
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
- netif_receive_skb(skb);
+ napi_gro_receive(&rdev->napi, skb);
rdev->ndev->stats.rx_packets++;
rdev->ndev->stats.rx_bytes += pkt_len;
@@ -827,10 +816,10 @@ retry:
netif_wake_subqueue(ndev, 0);
- napi_complete(napi);
-
- rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
- rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+ if (napi_complete_done(napi, budget - quota)) {
+ rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
+ rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+ }
out:
return budget - quota;
@@ -1513,7 +1502,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
rswitch_desc_set_dptr(&desc->desc, dma_addr);
desc->desc.info_ds = cpu_to_le16(skb->len);
- desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | INFO1_FMT);
+ desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) |
+ INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT);
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
struct rswitch_gwca_ts_info *ts_info;
@@ -1783,6 +1773,8 @@ static int rswitch_init(struct rswitch_private *priv)
if (err < 0)
return err;
+ rswitch_coma_init(priv);
+
err = rswitch_gwca_linkfix_alloc(priv);
if (err < 0)
return -ENOMEM;
diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h
index b3e0411b408e..bb9ed971a97c 100644
--- a/drivers/net/ethernet/renesas/rswitch.h
+++ b/drivers/net/ethernet/renesas/rswitch.h
@@ -48,6 +48,7 @@
#define GWCA_NUM_IRQS 8
#define GWCA_INDEX 0
#define AGENT_INDEX_GWCA 3
+#define GWCA_IPV_NUM 0
#define GWRO RSWITCH_GWCA0_OFFSET
#define GWCA_TS_IRQ_RESOURCE_NAME "gwca0_rxts0"
@@ -768,11 +769,14 @@ enum rswitch_gwca_mode {
#define GWARIRM_ARR BIT(1)
#define GWDCC_BALR BIT(24)
+#define GWDCC_DCP_MASK GENMASK(18, 16)
+#define GWDCC_DCP(prio) FIELD_PREP(GWDCC_DCP_MASK, (prio))
#define GWDCC_DQT BIT(11)
#define GWDCC_ETS BIT(9)
#define GWDCC_EDE BIT(8)
#define GWTRC(queue) (GWTRC0 + (queue) / 32 * 4)
+#define GWTPC_PPPL(ipv) BIT(ipv)
#define GWDCC_OFFS(queue) (GWDCC0 + (queue) * 4)
#define GWDIS(i) (GWDIS0 + (i) * 0x10)
@@ -789,6 +793,8 @@ enum rswitch_gwca_mode {
#define CABPIRM_BPIOG BIT(0)
#define CABPIRM_BPR BIT(1)
+#define CABPPFLC_INIT_VALUE 0x00800080
+
/* MFWD */
#define FWPC0_LTHTA BIT(0)
#define FWPC0_IP4UE BIT(3)
@@ -863,6 +869,7 @@ enum DIE_DT {
/* For transmission */
#define INFO1_TSUN(val) ((u64)(val) << 8ULL)
+#define INFO1_IPV(prio) ((u64)(prio) << 28ULL)
#define INFO1_CSD0(index) ((u64)(index) << 32ULL)
#define INFO1_CSD1(index) ((u64)(index) << 40ULL)
#define INFO1_DV(port_vector) ((u64)(port_vector) << 48ULL)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 0f45107db8dd..d14e0cfc3a6b 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -511,7 +511,7 @@ struct sxgbe_priv_data {
struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
struct sxgbe_plat_data *plat_dat,
void __iomem *addr);
-int sxgbe_drv_remove(struct net_device *ndev);
+void sxgbe_drv_remove(struct net_device *ndev);
void sxgbe_set_ethtool_ops(struct net_device *netdev);
int sxgbe_mdio_unregister(struct net_device *ndev);
int sxgbe_mdio_register(struct net_device *ndev);
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 9664f029fa16..71439825ea4e 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2203,7 +2203,7 @@ error_free_netdev:
* Description: this function resets the TX/RX processes, disables the MAC RX/TX
* changes the link status, releases the DMA descriptor rings.
*/
-int sxgbe_drv_remove(struct net_device *ndev)
+void sxgbe_drv_remove(struct net_device *ndev)
{
struct sxgbe_priv_data *priv = netdev_priv(ndev);
u8 queue_num;
@@ -2231,8 +2231,6 @@ int sxgbe_drv_remove(struct net_device *ndev)
kfree(priv->hw);
free_netdev(ndev);
-
- return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
index 4e5526303f07..fb59ff94509a 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
@@ -172,9 +172,10 @@ err_out:
static int sxgbe_platform_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
- int ret = sxgbe_drv_remove(ndev);
- return ret;
+ sxgbe_drv_remove(ndev);
+
+ return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 4af36ba8906b..3eb55dcfa8a6 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -50,6 +50,7 @@ config SFC_MCDI_MON
config SFC_SRIOV
bool "Solarflare SFC9100-family SR-IOV support"
depends on SFC && PCI_IOV
+ depends on INET
default y
help
This enables support for the Single Root I/O Virtualization
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index 55b9c73cd8ef..16293b58e0a8 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -10,7 +10,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \
efx_devlink.o
sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
- mae.o tc.o tc_bindings.o tc_counters.o
+ mae.o tc.o tc_bindings.o tc_counters.o \
+ tc_encap_actions.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index b63e47af6365..8c019f382a7f 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1297,8 +1297,10 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ spin_lock_bh(&efx->stats_lock);
kfree(nic_data->mc_stats);
nic_data->mc_stats = NULL;
+ spin_unlock_bh(&efx->stats_lock);
}
static int efx_ef10_init_nic(struct efx_nic *efx)
@@ -1852,9 +1854,14 @@ static size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
efx_ef10_get_stat_mask(efx, mask);
- efx_nic_copy_stats(efx, nic_data->mc_stats);
- efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
- mask, stats, nic_data->mc_stats, false);
+ /* If NIC was fini'd (probably resetting), then we can't read
+ * updated stats right now.
+ */
+ if (nic_data->mc_stats) {
+ efx_nic_copy_stats(efx, nic_data->mc_stats);
+ efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
+ mask, stats, nic_data->mc_stats, false);
+ }
/* Update derived statistics */
efx_nic_fix_nodesc_drop_stat(efx,
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index be395cd8770b..7f7d560cb2b4 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -24,6 +24,7 @@
#include "rx_common.h"
#include "ef100_sriov.h"
#include "tc_bindings.h"
+#include "tc_encap_actions.h"
#include "efx_devlink.h"
static void ef100_update_name(struct efx_nic *efx)
@@ -40,19 +41,26 @@ static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis)
unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels;
unsigned int rx_vis = efx->n_rx_channels;
unsigned int min_vis, max_vis;
+ int rc;
EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1);
tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel;
max_vis = max(rx_vis, tx_vis);
- /* Currently don't handle resource starvation and only accept
- * our maximum needs and no less.
+ /* We require at least a single complete TX channel worth of queues. */
+ min_vis = efx->tx_queues_per_channel;
+
+ rc = efx_mcdi_alloc_vis(efx, min_vis, max_vis,
+ NULL, allocated_vis);
+
+ /* We retry allocating VIs by reallocating channels when we have not
+ * been able to allocate the maximum VIs.
*/
- min_vis = max_vis;
+ if (!rc && *allocated_vis < max_vis)
+ rc = -EAGAIN;
- return efx_mcdi_alloc_vis(efx, min_vis, max_vis,
- NULL, allocated_vis);
+ return rc;
}
static int ef100_remap_bar(struct efx_nic *efx, int max_vis)
@@ -133,9 +141,41 @@ static int ef100_net_open(struct net_device *net_dev)
goto fail;
rc = ef100_alloc_vis(efx, &allocated_vis);
- if (rc)
+ if (rc && rc != -EAGAIN)
goto fail;
+ /* Try one more time but with the maximum number of channels
+ * equal to the allocated VIs, which would more likely succeed.
+ */
+ if (rc == -EAGAIN) {
+ rc = efx_mcdi_free_vis(efx);
+ if (rc)
+ goto fail;
+
+ efx_remove_interrupts(efx);
+ efx->max_channels = allocated_vis;
+
+ rc = efx_probe_interrupts(efx);
+ if (rc)
+ goto fail;
+
+ rc = efx_set_channels(efx);
+ if (rc)
+ goto fail;
+
+ rc = ef100_alloc_vis(efx, &allocated_vis);
+ if (rc && rc != -EAGAIN)
+ goto fail;
+
+ /* It should be very unlikely that we failed here again, but in
+ * such a case we return ENOSPC.
+ */
+ if (rc == -EAGAIN) {
+ rc = -ENOSPC;
+ goto fail;
+ }
+ }
+
rc = efx_probe_channels(efx);
if (rc)
return rc;
@@ -261,14 +301,38 @@ int ef100_netdev_event(struct notifier_block *this,
{
struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
+ struct ef100_nic_data *nic_data = efx->nic_data;
+ int err;
if (efx->net_dev == net_dev &&
(event == NETDEV_CHANGENAME || event == NETDEV_REGISTER))
ef100_update_name(efx);
+ if (!nic_data->grp_mae)
+ return NOTIFY_DONE;
+ err = efx_tc_netdev_event(efx, event, net_dev);
+ if (err & NOTIFY_STOP_MASK)
+ return err;
+
return NOTIFY_DONE;
}
+static int ef100_netevent_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct efx_nic *efx = container_of(this, struct efx_nic, netevent_notifier);
+ struct ef100_nic_data *nic_data = efx->nic_data;
+ int err;
+
+ if (!nic_data->grp_mae)
+ return NOTIFY_DONE;
+ err = efx_tc_netevent_event(efx, event, ptr);
+ if (err & NOTIFY_STOP_MASK)
+ return err;
+
+ return NOTIFY_DONE;
+};
+
static int ef100_register_netdev(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
@@ -328,6 +392,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
rtnl_unlock();
unregister_netdevice_notifier(&efx->netdev_notifier);
+ unregister_netevent_notifier(&efx->netevent_notifier);
#if defined(CONFIG_SFC_SRIOV)
if (!efx->type->is_vf)
efx_ef100_pci_sriov_disable(efx, true);
@@ -448,6 +513,14 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
goto fail;
}
+ efx->netevent_notifier.notifier_call = ef100_netevent_event;
+ rc = register_netevent_notifier(&efx->netevent_notifier);
+ if (rc) {
+ netif_err(efx, probe, efx->net_dev,
+ "Failed to register netevent notifier, rc=%d\n", rc);
+ goto fail;
+ }
+
efx_probe_devlink_unlock(efx);
return rc;
fail:
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 7adde9639c8a..35d8e9811998 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1194,7 +1194,7 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
net_dev->features |= NETIF_F_HW_TC;
efx->fixed_features |= NETIF_F_HW_TC;
}
- return rc;
+ return 0;
}
int ef100_probe_vf(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index a4f22d8e6ac7..d670a319b379 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -32,6 +32,7 @@
#include "io.h"
#include "selftest.h"
#include "sriov.h"
+#include "efx_devlink.h"
#include "mcdi_port_common.h"
#include "mcdi_pcol.h"
@@ -877,6 +878,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
if (efx->type->sriov_fini)
efx->type->sriov_fini(efx);
+ efx_fini_devlink_lock(efx);
efx_unregister_netdev(efx);
efx_mtd_remove(efx);
@@ -886,6 +888,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_fini_io(efx);
pci_dbg(efx->pci_dev, "shutdown successful\n");
+ efx_fini_devlink_and_unlock(efx);
efx_fini_struct(efx);
free_netdev(efx->net_dev);
probe_data = container_of(efx, struct efx_probe_data, efx);
@@ -1025,7 +1028,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
NETDEV_XDP_ACT_REDIRECT |
NETDEV_XDP_ACT_NDO_XMIT;
+ /* devlink creation, registration and lock */
+ rc = efx_probe_devlink_and_lock(efx);
+ if (rc)
+ pci_err(efx->pci_dev, "devlink registration failed");
+
rc = efx_register_netdev(efx);
+ efx_probe_devlink_unlock(efx);
if (!rc)
return 0;
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index ef9971cbb695..3cd750820fdd 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -25,40 +25,6 @@ struct efx_devlink {
};
#ifdef CONFIG_SFC_SRIOV
-static void efx_devlink_del_port(struct devlink_port *dl_port)
-{
- if (!dl_port)
- return;
- devl_port_unregister(dl_port);
-}
-
-static int efx_devlink_add_port(struct efx_nic *efx,
- struct mae_mport_desc *mport)
-{
- bool external = false;
-
- if (!ef100_mport_on_local_intf(efx, mport))
- external = true;
-
- switch (mport->mport_type) {
- case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
- if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
- devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
- mport->vf_idx,
- external);
- else
- devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
- external);
- break;
- default:
- /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
- return 0;
- }
-
- mport->dl_port.index = mport->mport_id;
-
- return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
-}
static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
int *hw_addr_len,
@@ -158,6 +124,48 @@ static int efx_devlink_port_addr_set(struct devlink_port *port,
return rc;
}
+static const struct devlink_port_ops sfc_devlink_port_ops = {
+ .port_fn_hw_addr_get = efx_devlink_port_addr_get,
+ .port_fn_hw_addr_set = efx_devlink_port_addr_set,
+};
+
+static void efx_devlink_del_port(struct devlink_port *dl_port)
+{
+ if (!dl_port)
+ return;
+ devl_port_unregister(dl_port);
+}
+
+static int efx_devlink_add_port(struct efx_nic *efx,
+ struct mae_mport_desc *mport)
+{
+ bool external = false;
+
+ if (!ef100_mport_on_local_intf(efx, mport))
+ external = true;
+
+ switch (mport->mport_type) {
+ case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
+ if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
+ devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
+ mport->vf_idx,
+ external);
+ else
+ devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
+ external);
+ break;
+ default:
+ /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
+ return 0;
+ }
+
+ mport->dl_port.index = mport->mport_id;
+
+ return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
+ mport->mport_id,
+ &sfc_devlink_port_ops);
+}
+
#endif
static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
@@ -609,10 +617,6 @@ static int efx_devlink_info_get(struct devlink *devlink,
static const struct devlink_ops sfc_devlink_ops = {
.info_get = efx_devlink_info_get,
-#ifdef CONFIG_SFC_SRIOV
- .port_function_hw_addr_get = efx_devlink_port_addr_get,
- .port_function_hw_addr_set = efx_devlink_port_addr_set,
-#endif
};
#ifdef CONFIG_SFC_SRIOV
@@ -622,6 +626,9 @@ static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
u32 id;
int rc;
+ if (!efx->mae)
+ return NULL;
+
if (efx_mae_lookup_mport(efx, idx, &id)) {
/* This should not happen. */
if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
diff --git a/drivers/net/ethernet/sfc/falcon/selftest.c b/drivers/net/ethernet/sfc/falcon/selftest.c
index 6a454ac6f876..c3dc88e6c26c 100644
--- a/drivers/net/ethernet/sfc/falcon/selftest.c
+++ b/drivers/net/ethernet/sfc/falcon/selftest.c
@@ -39,12 +39,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct ef4_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EF4_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct ef4_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -284,7 +289,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct ef4_loopback_state *state = efx->loopback_selftest;
- struct ef4_loopback_payload *received;
+ struct ef4_loopback_payload received;
struct ef4_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -295,13 +300,14 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
payload = &state->payload;
- received = (struct ef4_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -309,7 +315,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -317,16 +323,16 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EF4_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EF4_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -334,7 +340,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -342,10 +348,10 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -365,7 +371,8 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EF4_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -387,14 +394,15 @@ static void ef4_iterate_state(struct ef4_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct ef4_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct ef4_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -431,6 +439,10 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct ef4_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EF4_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 49706a7b94bf..0cab508f2f9d 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -15,6 +15,7 @@
#include "mcdi.h"
#include "mcdi_pcol.h"
#include "mcdi_pcol_mae.h"
+#include "tc_encap_actions.h"
int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
{
@@ -482,12 +483,14 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
rc; \
})
/* Checks that the fields needed for encap-rule matches are supported by the
- * MAE. All the fields are exact-match.
+ * MAE. All the fields are exact-match, except possibly ENC_IP_TOS.
*/
int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
+ u8 ip_tos_mask, __be16 udp_sport_mask,
struct netlink_ext_ack *extack)
{
u8 *supported_fields = efx->tc->caps->outer_rule_fields;
+ enum mask_type typ;
int rc;
if (CHECK(ENC_ETHER_TYPE))
@@ -504,6 +507,22 @@ int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
if (CHECK(ENC_L4_DPORT) ||
CHECK(ENC_IP_PROTO))
return rc;
+ typ = classify_mask((const u8 *)&udp_sport_mask, sizeof(udp_sport_mask));
+ rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_L4_SPORT],
+ typ);
+ if (rc) {
+ NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s",
+ mask_type_name(typ), "enc_src_port");
+ return rc;
+ }
+ typ = classify_mask(&ip_tos_mask, sizeof(ip_tos_mask));
+ rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ENC_IP_TOS],
+ typ);
+ if (rc) {
+ NL_SET_ERR_MSG_FMT_MOD(extack, "No support for %s mask in field %s",
+ mask_type_name(typ), "enc_ip_tos");
+ return rc;
+ }
return 0;
}
#undef CHECK
@@ -592,6 +611,87 @@ static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type)
}
}
+int efx_mae_allocate_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(EFX_TC_MAX_ENCAP_HDR));
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
+ size_t inlen, outlen;
+ int rc;
+
+ rc = efx_mae_encap_type_to_mae_type(encap->type);
+ if (rc < 0)
+ return rc;
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, rc);
+ inlen = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(encap->encap_hdr_len);
+ if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */
+ return -EINVAL;
+ memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA),
+ encap->encap_hdr,
+ encap->encap_hdr_len);
+ rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_ALLOC, inbuf,
+ inlen, outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ return rc;
+ if (outlen < sizeof(outbuf))
+ return -EIO;
+ encap->fw_id = MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
+ return 0;
+}
+
+int efx_mae_update_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(EFX_TC_MAX_ENCAP_HDR));
+ size_t inlen;
+ int rc;
+
+ rc = efx_mae_encap_type_to_mae_type(encap->type);
+ if (rc < 0)
+ return rc;
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, rc);
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_EH_ID,
+ encap->fw_id);
+ inlen = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(encap->encap_hdr_len);
+ if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */
+ return -EINVAL;
+ memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA),
+ encap->encap_hdr,
+ encap->encap_hdr_len);
+
+ BUILD_BUG_ON(MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN != 0);
+ return efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_UPDATE, inbuf,
+ inlen, NULL, 0, NULL);
+}
+
+int efx_mae_free_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1));
+ size_t outlen;
+ int rc;
+
+ MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_FREE_IN_EH_ID, encap->fw_id);
+ rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_FREE, inbuf,
+ sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ return rc;
+ if (outlen < sizeof(outbuf))
+ return -EIO;
+ /* FW freed a different ID than we asked for, should also never happen.
+ * Warn because it means we've now got a different idea to the FW of
+ * what encap_mds exist, which could cause mayhem later.
+ */
+ if (WARN_ON(MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != encap->fw_id))
+ return -EIO;
+ /* We're probably about to free @encap, but let's just make sure its
+ * fw_id is blatted so that it won't look valid if it leaks out.
+ */
+ encap->fw_id = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL;
+ return 0;
+}
+
int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
{
struct ef100_nic_data *nic_data = efx->nic_data;
@@ -815,8 +915,12 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
act->vlan_proto[1]);
}
- MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
- MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
+ if (act->encap_md)
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+ act->encap_md->fw_id);
+ else
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
+ MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
if (act->deliver)
MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER,
act->dest_mport);
@@ -1001,8 +1105,16 @@ int efx_mae_register_encap_match(struct efx_nic *efx,
encap->udp_dport);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
~(__be16)0);
+ MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE,
+ encap->udp_sport);
+ MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK,
+ encap->udp_sport_mask);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO, IPPROTO_UDP);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK, ~0);
+ MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS,
+ encap->ip_tos);
+ MCDI_STRUCT_SET_BYTE(match_crit, MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK,
+ encap->ip_tos_mask);
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_OUTER_RULE_INSERT, inbuf,
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
if (rc)
@@ -1203,6 +1315,29 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
return 0;
}
+int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id)
+{
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN);
+ MCDI_DECLARE_STRUCT_PTR(response);
+
+ BUILD_BUG_ON(MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN);
+ response = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_RESPONSE);
+
+ MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_AR_ID, id);
+ if (efx_mae_asl_id(acts_id)) {
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, acts_id);
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID,
+ MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL);
+ } else {
+ /* We only had one AS, so we didn't wrap it in an ASL */
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID,
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
+ MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, acts_id);
+ }
+ return efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_UPDATE, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+}
+
int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index 9226219491a0..24abfe509690 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -82,6 +82,7 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
const struct efx_tc_match_fields *mask,
struct netlink_ext_ack *extack);
int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6,
+ u8 ip_tos_mask, __be16 udp_sport_mask,
struct netlink_ext_ack *extack);
int efx_mae_check_encap_type_supported(struct efx_nic *efx,
enum efx_encap_type typ);
@@ -89,6 +90,13 @@ int efx_mae_check_encap_type_supported(struct efx_nic *efx,
int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt);
+int efx_mae_allocate_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+int efx_mae_update_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+int efx_mae_free_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+
int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act);
int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id);
@@ -104,6 +112,7 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx,
int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
u32 prio, u32 acts_id, u32 *id);
+int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id);
int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
int efx_init_mae(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index fcd51d3992fa..a7a22b019794 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -27,6 +27,7 @@
#include <linux/mtd/mtd.h>
#include <net/busy_poll.h>
#include <net/xdp.h>
+#include <net/netevent.h>
#include "enum.h"
#include "bitfield.h"
@@ -996,6 +997,7 @@ struct efx_mae;
* @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their
* xdp_rxq_info structures?
* @netdev_notifier: Netdevice notifier.
+ * @netevent_notifier: Netevent notifier (for neighbour updates).
* @tc: state for TC offload (EF100).
* @devlink: reference to devlink structure owned by this device
* @dl_port: devlink port associated with the PF
@@ -1183,6 +1185,7 @@ struct efx_nic {
bool xdp_rxq_info_failed;
struct notifier_block netdev_notifier;
+ struct notifier_block netevent_notifier;
struct efx_tc_state *tc;
struct devlink *devlink;
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 0c40571133cb..00cf6de3bb2b 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -1485,7 +1485,9 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
goto fail;
rc = efx_ptp_insert_eth_multicast_filter(efx);
- if (rc < 0)
+
+ /* Not all firmware variants support this filter */
+ if (rc < 0 && rc != -EPROTONOSUPPORT)
goto fail;
}
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 3c5227afd497..563c1e317ce9 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -42,12 +42,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct efx_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EFX_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct efx_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -282,7 +287,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct efx_loopback_state *state = efx->loopback_selftest;
- struct efx_loopback_payload *received;
+ struct efx_loopback_payload received;
struct efx_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -293,13 +298,14 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
payload = &state->payload;
- received = (struct efx_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -307,7 +313,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -315,16 +321,16 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -332,7 +338,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -340,10 +346,10 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -363,7 +369,8 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -385,14 +392,15 @@ static void efx_iterate_state(struct efx_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -429,6 +437,10 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/siena/selftest.c b/drivers/net/ethernet/sfc/siena/selftest.c
index 07715a3d6bea..526da43d4b61 100644
--- a/drivers/net/ethernet/sfc/siena/selftest.c
+++ b/drivers/net/ethernet/sfc/siena/selftest.c
@@ -42,12 +42,17 @@
* Falcon only performs RSS on TCP/UDP packets.
*/
struct efx_loopback_payload {
- struct ethhdr header;
- struct iphdr ip;
- struct udphdr udp;
- __be16 iteration;
- char msg[64];
-} __packed;
+ char pad[2]; /* Ensures ip is 4-byte aligned */
+ struct_group_attr(packet, __packed,
+ struct ethhdr header;
+ struct iphdr ip;
+ struct udphdr udp;
+ __be16 iteration;
+ char msg[64];
+ );
+} __packed __aligned(4);
+#define EFX_LOOPBACK_PAYLOAD_LEN \
+ sizeof_field(struct efx_loopback_payload, packet)
/* Loopback test source MAC address */
static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -282,7 +287,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len)
{
struct efx_loopback_state *state = efx->loopback_selftest;
- struct efx_loopback_payload *received;
+ struct efx_loopback_payload received;
struct efx_loopback_payload *payload;
BUG_ON(!buf_ptr);
@@ -293,13 +298,14 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
payload = &state->payload;
- received = (struct efx_loopback_payload *) buf_ptr;
- received->ip.saddr = payload->ip.saddr;
+ memcpy(&received.packet, buf_ptr,
+ min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
+ received.ip.saddr = payload->ip.saddr;
if (state->offload_csum)
- received->ip.check = payload->ip.check;
+ received.ip.check = payload->ip.check;
/* Check that header exists */
- if (pkt_len < sizeof(received->header)) {
+ if (pkt_len < sizeof(received.header)) {
netif_err(efx, drv, efx->net_dev,
"saw runt RX packet (length %d) in %s loopback "
"test\n", pkt_len, LOOPBACK_MODE(efx));
@@ -307,7 +313,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that the ethernet header exists */
- if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) {
+ if (memcmp(&received.header, &payload->header, ETH_HLEN) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw non-loopback RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -315,16 +321,16 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check packet length */
- if (pkt_len != sizeof(*payload)) {
+ if (pkt_len != EFX_LOOPBACK_PAYLOAD_LEN) {
netif_err(efx, drv, efx->net_dev,
"saw incorrect RX packet length %d (wanted %d) in "
- "%s loopback test\n", pkt_len, (int)sizeof(*payload),
- LOOPBACK_MODE(efx));
+ "%s loopback test\n", pkt_len,
+ (int)EFX_LOOPBACK_PAYLOAD_LEN, LOOPBACK_MODE(efx));
goto err;
}
/* Check that IP header matches */
- if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) {
+ if (memcmp(&received.ip, &payload->ip, sizeof(payload->ip)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted IP header in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -332,7 +338,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that msg and padding matches */
- if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) {
+ if (memcmp(&received.msg, &payload->msg, sizeof(received.msg)) != 0) {
netif_err(efx, drv, efx->net_dev,
"saw corrupted RX packet in %s loopback test\n",
LOOPBACK_MODE(efx));
@@ -340,10 +346,10 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
}
/* Check that iteration matches */
- if (received->iteration != payload->iteration) {
+ if (received.iteration != payload->iteration) {
netif_err(efx, drv, efx->net_dev,
"saw RX packet from iteration %d (wanted %d) in "
- "%s loopback test\n", ntohs(received->iteration),
+ "%s loopback test\n", ntohs(received.iteration),
ntohs(payload->iteration), LOOPBACK_MODE(efx));
goto err;
}
@@ -363,7 +369,8 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
buf_ptr, pkt_len, 0);
netif_err(efx, drv, efx->net_dev, "expected packet:\n");
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
- &state->payload, sizeof(state->payload), 0);
+ &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
+ 0);
}
#endif
atomic_inc(&state->rx_bad);
@@ -385,14 +392,15 @@ static void efx_iterate_state(struct efx_nic *efx)
payload->ip.daddr = htonl(INADDR_LOOPBACK);
payload->ip.ihl = 5;
payload->ip.check = (__force __sum16) htons(0xdead);
- payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
+ payload->ip.tot_len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, ip));
payload->ip.version = IPVERSION;
payload->ip.protocol = IPPROTO_UDP;
/* Initialise udp header */
payload->udp.source = 0;
- payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) -
- sizeof(struct iphdr));
+ payload->udp.len = htons(sizeof(*payload) -
+ offsetof(struct efx_loopback_payload, udp));
payload->udp.check = 0; /* checksum ignored */
/* Fill out payload */
@@ -429,6 +437,10 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
payload = skb_put(skb, sizeof(state->payload));
memcpy(payload, &state->payload, sizeof(state->payload));
payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
+ /* Strip off the leading padding */
+ skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+ /* Strip off the trailing padding */
+ skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
/* Ensure everything we've written is visible to the
* interrupt handler. */
diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c
index 93a32d61944f..a7a9ab304e13 100644
--- a/drivers/net/ethernet/sfc/siena/tx_common.c
+++ b/drivers/net/ethernet/sfc/siena/tx_common.c
@@ -12,6 +12,7 @@
#include "efx.h"
#include "nic_common.h"
#include "tx_common.h"
+#include <net/gso.h>
static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
{
diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c
index c004443c1d58..fe268b6c1cac 100644
--- a/drivers/net/ethernet/sfc/tc.c
+++ b/drivers/net/ethernet/sfc/tc.c
@@ -14,11 +14,12 @@
#include <net/geneve.h>
#include "tc.h"
#include "tc_bindings.h"
+#include "tc_encap_actions.h"
#include "mae.h"
#include "ef100_rep.h"
#include "efx.h"
-static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
+enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
{
if (netif_is_vxlan(net_dev))
return EFX_ENCAP_TYPE_VXLAN;
@@ -33,8 +34,8 @@ static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
* May return NULL for the PF (us), or an error pointer for a device that
* isn't supported as a TC offload endpoint
*/
-static struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
- struct net_device *dev)
+struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
+ struct net_device *dev)
{
struct efx_rep *efv;
@@ -70,7 +71,7 @@ static s64 efx_tc_flower_internal_mport(struct efx_nic *efx, struct efx_rep *efv
}
/* Convert a driver-internal vport ID into an external device (wire or VF) */
-static s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
+s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
{
u32 mport;
@@ -109,8 +110,17 @@ static void efx_tc_free_action_set(struct efx_nic *efx,
*/
list_del(&act->list);
}
- if (act->count)
+ if (act->count) {
+ spin_lock_bh(&act->count->cnt->lock);
+ if (!list_empty(&act->count_user))
+ list_del(&act->count_user);
+ spin_unlock_bh(&act->count->cnt->lock);
efx_tc_flower_put_counter_index(efx, act->count);
+ }
+ if (act->encap_md) {
+ list_del(&act->encap_user);
+ efx_tc_flower_release_encap_md(efx, act->encap_md);
+ }
kfree(act);
}
@@ -132,23 +142,6 @@ static void efx_tc_free_action_set_list(struct efx_nic *efx,
/* Don't kfree, as acts is embedded inside a struct efx_tc_flow_rule */
}
-static void efx_tc_flow_free(void *ptr, void *arg)
-{
- struct efx_tc_flow_rule *rule = ptr;
- struct efx_nic *efx = arg;
-
- netif_err(efx, drv, efx->net_dev,
- "tc rule %lx still present at teardown, removing\n",
- rule->cookie);
-
- efx_mae_delete_rule(efx, rule->fw_id);
-
- /* Release entries in subsidiary tables */
- efx_tc_free_action_set_list(efx, &rule->acts, true);
-
- kfree(rule);
-}
-
/* Boilerplate for the simple 'copy a field' cases */
#define _MAP_KEY_AND_MASK(_name, _type, _tcget, _tcfield, _field) \
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_##_name)) { \
@@ -219,6 +212,7 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
+ BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_TCP) |
@@ -363,20 +357,48 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
return 0;
}
+static void efx_tc_flower_release_encap_match(struct efx_nic *efx,
+ struct efx_tc_encap_match *encap)
+{
+ int rc;
+
+ if (!refcount_dec_and_test(&encap->ref))
+ return; /* still in use */
+
+ if (encap->type == EFX_TC_EM_DIRECT) {
+ rc = efx_mae_unregister_encap_match(efx, encap);
+ if (rc)
+ /* Display message but carry on and remove entry from our
+ * SW tables, because there's not much we can do about it.
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to release encap match %#x, rc %d\n",
+ encap->fw_id, rc);
+ }
+ rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
+ efx_tc_encap_match_ht_params);
+ if (encap->pseudo)
+ efx_tc_flower_release_encap_match(efx, encap->pseudo);
+ kfree(encap);
+}
+
static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
struct efx_tc_match *match,
enum efx_encap_type type,
+ enum efx_tc_em_pseudo_type em_type,
+ u8 child_ip_tos_mask,
+ __be16 child_udp_sport_mask,
struct netlink_ext_ack *extack)
{
- struct efx_tc_encap_match *encap, *old;
+ struct efx_tc_encap_match *encap, *old, *pseudo = NULL;
bool ipv6 = false;
int rc;
/* We require that the socket-defining fields (IP addrs and UDP dest
- * port) are present and exact-match. Other fields are currently not
- * allowed. This meets what OVS will ask for, and means that we don't
- * need to handle difficult checks for overlapping matches as could
- * come up if we allowed masks or varying sets of match fields.
+ * port) are present and exact-match. Other fields may only be used
+ * if the field-set (and any masks) are the same for all encap
+ * matches on the same <sip,dip,dport> tuple; this is enforced by
+ * pseudo encap matches.
*/
if (match->mask.enc_dst_ip | match->mask.enc_src_ip) {
if (!IS_ALL_ONES(match->mask.enc_dst_ip)) {
@@ -414,29 +436,42 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Egress encap match is not exact on dst UDP port");
return -EOPNOTSUPP;
}
- if (match->mask.enc_sport) {
- NL_SET_ERR_MSG_MOD(extack, "Egress encap match on src UDP port not supported");
- return -EOPNOTSUPP;
- }
- if (match->mask.enc_ip_tos) {
- NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP ToS not supported");
- return -EOPNOTSUPP;
+ if (match->mask.enc_sport || match->mask.enc_ip_tos) {
+ struct efx_tc_match pmatch = *match;
+
+ if (em_type == EFX_TC_EM_PSEUDO_MASK) { /* can't happen */
+ NL_SET_ERR_MSG_MOD(extack, "Bad recursion in egress encap match handler");
+ return -EOPNOTSUPP;
+ }
+ pmatch.value.enc_ip_tos = 0;
+ pmatch.mask.enc_ip_tos = 0;
+ pmatch.value.enc_sport = 0;
+ pmatch.mask.enc_sport = 0;
+ rc = efx_tc_flower_record_encap_match(efx, &pmatch, type,
+ EFX_TC_EM_PSEUDO_MASK,
+ match->mask.enc_ip_tos,
+ match->mask.enc_sport,
+ extack);
+ if (rc)
+ return rc;
+ pseudo = pmatch.encap;
}
if (match->mask.enc_ip_ttl) {
NL_SET_ERR_MSG_MOD(extack, "Egress encap match on IP TTL not supported");
- return -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
+ goto fail_pseudo;
}
- rc = efx_mae_check_encap_match_caps(efx, ipv6, extack);
- if (rc) {
- NL_SET_ERR_MSG_FMT_MOD(extack, "MAE hw reports no support for IPv%d encap matches",
- ipv6 ? 6 : 4);
- return -EOPNOTSUPP;
- }
+ rc = efx_mae_check_encap_match_caps(efx, ipv6, match->mask.enc_ip_tos,
+ match->mask.enc_sport, extack);
+ if (rc)
+ goto fail_pseudo;
encap = kzalloc(sizeof(*encap), GFP_USER);
- if (!encap)
- return -ENOMEM;
+ if (!encap) {
+ rc = -ENOMEM;
+ goto fail_pseudo;
+ }
encap->src_ip = match->value.enc_src_ip;
encap->dst_ip = match->value.enc_dst_ip;
#ifdef CONFIG_IPV6
@@ -445,12 +480,66 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
#endif
encap->udp_dport = match->value.enc_dport;
encap->tun_type = type;
+ encap->ip_tos = match->value.enc_ip_tos;
+ encap->ip_tos_mask = match->mask.enc_ip_tos;
+ encap->child_ip_tos_mask = child_ip_tos_mask;
+ encap->udp_sport = match->value.enc_sport;
+ encap->udp_sport_mask = match->mask.enc_sport;
+ encap->child_udp_sport_mask = child_udp_sport_mask;
+ encap->type = em_type;
+ encap->pseudo = pseudo;
old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_match_ht,
&encap->linkage,
efx_tc_encap_match_ht_params);
if (old) {
/* don't need our new entry */
kfree(encap);
+ if (pseudo) /* don't need our new pseudo either */
+ efx_tc_flower_release_encap_match(efx, pseudo);
+ /* check old and new em_types are compatible */
+ switch (old->type) {
+ case EFX_TC_EM_DIRECT:
+ /* old EM is in hardware, so mustn't overlap with a
+ * pseudo, but may be shared with another direct EM
+ */
+ if (em_type == EFX_TC_EM_DIRECT)
+ break;
+ NL_SET_ERR_MSG_MOD(extack, "Pseudo encap match conflicts with existing direct entry");
+ return -EEXIST;
+ case EFX_TC_EM_PSEUDO_MASK:
+ /* old EM is protecting a ToS- or src port-qualified
+ * filter, so may only be shared with another pseudo
+ * for the same ToS and src port masks.
+ */
+ if (em_type != EFX_TC_EM_PSEUDO_MASK) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "%s encap match conflicts with existing pseudo(MASK) entry",
+ em_type ? "Pseudo" : "Direct");
+ return -EEXIST;
+ }
+ if (child_ip_tos_mask != old->child_ip_tos_mask) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "Pseudo encap match for TOS mask %#04x conflicts with existing pseudo(MASK) entry for TOS mask %#04x",
+ child_ip_tos_mask,
+ old->child_ip_tos_mask);
+ return -EEXIST;
+ }
+ if (child_udp_sport_mask != old->child_udp_sport_mask) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "Pseudo encap match for UDP src port mask %#x conflicts with existing pseudo(MASK) entry for mask %#x",
+ child_udp_sport_mask,
+ old->child_udp_sport_mask);
+ return -EEXIST;
+ }
+ break;
+ default: /* Unrecognised pseudo-type. Just say no */
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+ "%s encap match conflicts with existing pseudo(%d) entry",
+ em_type ? "Pseudo" : "Direct",
+ old->type);
+ return -EEXIST;
+ }
+ /* check old and new tun_types are compatible */
if (old->tun_type != type) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"Egress encap match with conflicting tun_type %u != %u",
@@ -462,10 +551,12 @@ static int efx_tc_flower_record_encap_match(struct efx_nic *efx,
/* existing entry found */
encap = old;
} else {
- rc = efx_mae_register_encap_match(efx, encap);
- if (rc) {
- NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW");
- goto fail;
+ if (em_type == EFX_TC_EM_DIRECT) {
+ rc = efx_mae_register_encap_match(efx, encap);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to record egress encap match in HW");
+ goto fail;
+ }
}
refcount_set(&encap->ref, 1);
}
@@ -475,30 +566,12 @@ fail:
rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
efx_tc_encap_match_ht_params);
kfree(encap);
+fail_pseudo:
+ if (pseudo)
+ efx_tc_flower_release_encap_match(efx, pseudo);
return rc;
}
-static void efx_tc_flower_release_encap_match(struct efx_nic *efx,
- struct efx_tc_encap_match *encap)
-{
- int rc;
-
- if (!refcount_dec_and_test(&encap->ref))
- return; /* still in use */
-
- rc = efx_mae_unregister_encap_match(efx, encap);
- if (rc)
- /* Display message but carry on and remove entry from our
- * SW tables, because there's not much we can do about it.
- */
- netif_err(efx, drv, efx->net_dev,
- "Failed to release encap match %#x, rc %d\n",
- encap->fw_id, rc);
- rhashtable_remove_fast(&efx->tc->encap_match_ht, &encap->linkage,
- efx_tc_encap_match_ht_params);
- kfree(encap);
-}
-
static void efx_tc_delete_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule)
{
efx_mae_delete_rule(efx, rule->fw_id);
@@ -531,6 +604,7 @@ enum efx_tc_action_order {
EFX_TC_AO_VLAN_POP,
EFX_TC_AO_VLAN_PUSH,
EFX_TC_AO_COUNT,
+ EFX_TC_AO_ENCAP,
EFX_TC_AO_DELIVER
};
/* Determine whether we can add @new action without violating order */
@@ -560,6 +634,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act,
if (act->count)
return false;
fallthrough;
+ case EFX_TC_AO_ENCAP:
+ if (act->encap_md)
+ return false;
+ fallthrough;
case EFX_TC_AO_DELIVER:
return !act->deliver;
default:
@@ -650,6 +728,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
}
rc = efx_tc_flower_record_encap_match(efx, &match, type,
+ EFX_TC_EM_DIRECT, 0, 0,
extack);
if (rc)
return rc;
@@ -722,6 +801,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx,
goto release;
}
act->count = ctr;
+ INIT_LIST_HEAD(&act->count_user);
}
if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) {
@@ -854,11 +934,13 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
{
struct flow_rule *fr = flow_cls_offload_flow_rule(tc);
struct netlink_ext_ack *extack = tc->common.extack;
+ const struct ip_tunnel_info *encap_info = NULL;
struct efx_tc_flow_rule *rule = NULL, *old;
struct efx_tc_action_set *act = NULL;
const struct flow_action_entry *fa;
struct efx_rep *from_efv, *to_efv;
struct efx_tc_match match;
+ u32 acts_id;
s64 rc;
int i;
@@ -1007,6 +1089,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
goto release;
}
act->count = ctr;
+ INIT_LIST_HEAD(&act->count_user);
}
switch (fa->id) {
@@ -1023,6 +1106,59 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
case FLOW_ACTION_MIRRED:
save = *act;
+ if (encap_info) {
+ struct efx_tc_encap_action *encap;
+
+ if (!efx_tc_flower_action_order_ok(act,
+ EFX_TC_AO_ENCAP)) {
+ rc = -EOPNOTSUPP;
+ NL_SET_ERR_MSG_MOD(extack, "Encap action violates action order");
+ goto release;
+ }
+ encap = efx_tc_flower_create_encap_md(
+ efx, encap_info, fa->dev, extack);
+ if (IS_ERR_OR_NULL(encap)) {
+ rc = PTR_ERR(encap);
+ if (!rc)
+ rc = -EIO; /* arbitrary */
+ goto release;
+ }
+ act->encap_md = encap;
+ list_add_tail(&act->encap_user, &encap->users);
+ act->dest_mport = encap->dest_mport;
+ act->deliver = 1;
+ if (act->count && !WARN_ON(!act->count->cnt)) {
+ /* This counter is used by an encap
+ * action, which needs a reference back
+ * so it can prod neighbouring whenever
+ * traffic is seen.
+ */
+ spin_lock_bh(&act->count->cnt->lock);
+ list_add_tail(&act->count_user,
+ &act->count->cnt->users);
+ spin_unlock_bh(&act->count->cnt->lock);
+ }
+ rc = efx_mae_alloc_action_set(efx, act);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to write action set to hw (encap)");
+ goto release;
+ }
+ list_add_tail(&act->list, &rule->acts.list);
+ act->user = &rule->acts;
+ act = NULL;
+ if (fa->id == FLOW_ACTION_REDIRECT)
+ break; /* end of the line */
+ /* Mirror, so continue on with saved act */
+ save.count = NULL;
+ act = kzalloc(sizeof(*act), GFP_USER);
+ if (!act) {
+ rc = -ENOMEM;
+ goto release;
+ }
+ *act = save;
+ break;
+ }
+
if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) {
/* can't happen */
rc = -EOPNOTSUPP;
@@ -1086,6 +1222,37 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
act->vlan_proto[act->vlan_push] = fa->vlan.proto;
act->vlan_push++;
break;
+ case FLOW_ACTION_TUNNEL_ENCAP:
+ if (encap_info) {
+ /* Can't specify encap multiple times.
+ * If you want to overwrite an existing
+ * encap_info, use an intervening
+ * FLOW_ACTION_TUNNEL_DECAP to clear it.
+ */
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel key set when already set");
+ rc = -EINVAL;
+ goto release;
+ }
+ if (!fa->tunnel) {
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel key set is missing key");
+ rc = -EOPNOTSUPP;
+ goto release;
+ }
+ encap_info = fa->tunnel;
+ break;
+ case FLOW_ACTION_TUNNEL_DECAP:
+ if (encap_info) {
+ encap_info = NULL;
+ break;
+ }
+ /* Since we don't support enc_key matches on ingress
+ * (and if we did there'd be no tunnel-device to give
+ * us a type), we can't offload a decap that's not
+ * just undoing a previous encap action.
+ */
+ NL_SET_ERR_MSG_MOD(extack, "Cannot offload tunnel decap action without tunnel device");
+ rc = -EOPNOTSUPP;
+ goto release;
default:
NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u",
fa->id);
@@ -1129,8 +1296,21 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
NL_SET_ERR_MSG_MOD(extack, "Failed to write action set list to hw");
goto release;
}
+ if (from_efv == EFX_EFV_PF)
+ /* PF netdev, so rule applies to traffic from wire */
+ rule->fallback = &efx->tc->facts.pf;
+ else
+ /* repdev, so rule applies to traffic from representee */
+ rule->fallback = &efx->tc->facts.reps;
+ if (!efx_tc_check_ready(efx, rule)) {
+ netif_dbg(efx, drv, efx->net_dev, "action not ready for hw\n");
+ acts_id = rule->fallback->fw_id;
+ } else {
+ netif_dbg(efx, drv, efx->net_dev, "ready for hw\n");
+ acts_id = rule->acts.fw_id;
+ }
rc = efx_mae_insert_rule(efx, &rule->match, EFX_TC_PRIO_TC,
- rule->acts.fw_id, &rule->fw_id);
+ acts_id, &rule->fw_id);
if (rc) {
NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw");
goto release_acts;
@@ -1327,6 +1507,58 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
}
+static int efx_tc_configure_fallback_acts(struct efx_nic *efx, u32 eg_port,
+ struct efx_tc_action_set_list *acts)
+{
+ struct efx_tc_action_set *act;
+ int rc;
+
+ act = kzalloc(sizeof(*act), GFP_KERNEL);
+ if (!act)
+ return -ENOMEM;
+ act->deliver = 1;
+ act->dest_mport = eg_port;
+ rc = efx_mae_alloc_action_set(efx, act);
+ if (rc)
+ goto fail1;
+ EFX_WARN_ON_PARANOID(!list_empty(&acts->list));
+ list_add_tail(&act->list, &acts->list);
+ rc = efx_mae_alloc_action_set_list(efx, acts);
+ if (rc)
+ goto fail2;
+ return 0;
+fail2:
+ list_del(&act->list);
+ efx_mae_free_action_set(efx, act->fw_id);
+fail1:
+ kfree(act);
+ return rc;
+}
+
+static int efx_tc_configure_fallback_acts_pf(struct efx_nic *efx)
+{
+ struct efx_tc_action_set_list *acts = &efx->tc->facts.pf;
+ u32 eg_port;
+
+ efx_mae_mport_uplink(efx, &eg_port);
+ return efx_tc_configure_fallback_acts(efx, eg_port, acts);
+}
+
+static int efx_tc_configure_fallback_acts_reps(struct efx_nic *efx)
+{
+ struct efx_tc_action_set_list *acts = &efx->tc->facts.reps;
+ u32 eg_port;
+
+ efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port);
+ return efx_tc_configure_fallback_acts(efx, eg_port, acts);
+}
+
+static void efx_tc_deconfigure_fallback_acts(struct efx_nic *efx,
+ struct efx_tc_action_set_list *acts)
+{
+ efx_tc_free_action_set_list(efx, acts, true);
+}
+
static int efx_tc_configure_rep_mport(struct efx_nic *efx)
{
u32 rep_mport_label;
@@ -1419,10 +1651,16 @@ int efx_init_tc(struct efx_nic *efx)
rc = efx_tc_configure_rep_mport(efx);
if (rc)
return rc;
- efx->tc->up = true;
+ rc = efx_tc_configure_fallback_acts_pf(efx);
+ if (rc)
+ return rc;
+ rc = efx_tc_configure_fallback_acts_reps(efx);
+ if (rc)
+ return rc;
rc = flow_indr_dev_register(efx_tc_indr_setup_cb, efx);
if (rc)
return rc;
+ efx->tc->up = true;
return 0;
}
@@ -1436,6 +1674,8 @@ void efx_fini_tc(struct efx_nic *efx)
efx_tc_deconfigure_rep_mport(efx);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
+ efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf);
+ efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps);
efx->tc->up = false;
}
@@ -1451,6 +1691,21 @@ static void efx_tc_encap_match_free(void *ptr, void *__unused)
kfree(encap);
}
+static void efx_tc_flow_free(void *ptr, void *arg)
+{
+ struct efx_tc_flow_rule *rule = ptr;
+ struct efx_nic *efx = arg;
+
+ netif_err(efx, drv, efx->net_dev,
+ "tc rule %lx still present at teardown, removing\n",
+ rule->cookie);
+
+ /* Also releases entries in subsidiary tables */
+ efx_tc_delete_rule(efx, rule);
+
+ kfree(rule);
+}
+
int efx_init_struct_tc(struct efx_nic *efx)
{
int rc;
@@ -1470,6 +1725,9 @@ int efx_init_struct_tc(struct efx_nic *efx)
mutex_init(&efx->tc->mutex);
init_waitqueue_head(&efx->tc->flush_wq);
+ rc = efx_tc_init_encap_actions(efx);
+ if (rc < 0)
+ goto fail_encap_actions;
rc = efx_tc_init_counters(efx);
if (rc < 0)
goto fail_counters;
@@ -1485,6 +1743,10 @@ int efx_init_struct_tc(struct efx_nic *efx)
efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list);
efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
+ INIT_LIST_HEAD(&efx->tc->facts.pf.list);
+ efx->tc->facts.pf.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
+ INIT_LIST_HEAD(&efx->tc->facts.reps.list);
+ efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type;
return 0;
fail_match_action_ht:
@@ -1492,6 +1754,8 @@ fail_match_action_ht:
fail_encap_match_ht:
efx_tc_destroy_counters(efx);
fail_counters:
+ efx_tc_destroy_encap_actions(efx);
+fail_encap_actions:
mutex_destroy(&efx->tc->mutex);
kfree(efx->tc->caps);
fail_alloc_caps:
@@ -1510,11 +1774,16 @@ void efx_fini_struct_tc(struct efx_nic *efx)
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id !=
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
+ EFX_WARN_ON_PARANOID(efx->tc->facts.pf.fw_id !=
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
+ EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id !=
+ MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free,
efx);
rhashtable_free_and_destroy(&efx->tc->encap_match_ht,
efx_tc_encap_match_free, NULL);
efx_tc_fini_counters(efx);
+ efx_tc_fini_encap_actions(efx);
mutex_unlock(&efx->tc->mutex);
mutex_destroy(&efx->tc->mutex);
kfree(efx->tc->caps);
diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h
index 04cced6a2d39..1549c3df43bb 100644
--- a/drivers/net/ethernet/sfc/tc.h
+++ b/drivers/net/ethernet/sfc/tc.h
@@ -25,6 +25,8 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr)
}
#endif
+struct efx_tc_encap_action; /* see tc_encap_actions.h */
+
struct efx_tc_action_set {
u16 vlan_push:2;
u16 vlan_pop:2;
@@ -33,6 +35,10 @@ struct efx_tc_action_set {
__be16 vlan_tci[2]; /* TCIs for vlan_push */
__be16 vlan_proto[2]; /* Ethertypes for vlan_push */
struct efx_tc_counter_index *count;
+ struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */
+ struct list_head encap_user; /* entry on encap_md->users list */
+ struct efx_tc_action_set_list *user; /* Only populated if encap_md */
+ struct list_head count_user; /* entry on counter->users list, if encap */
u32 dest_mport;
u32 fw_id; /* index of this entry in firmware actions table */
struct list_head list;
@@ -74,14 +80,41 @@ static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask)
mask->enc_ip_ttl || mask->enc_sport || mask->enc_dport;
}
+/**
+ * enum efx_tc_em_pseudo_type - &struct efx_tc_encap_match pseudo type
+ *
+ * These are used to classify "pseudo" encap matches, which don't refer
+ * to an entry in hardware but rather indicate that a section of the
+ * match space is in use by another Outer Rule.
+ *
+ * @EFX_TC_EM_DIRECT: real HW entry in Outer Rule table; not a pseudo.
+ * Hardware index in &struct efx_tc_encap_match.fw_id is valid.
+ * @EFX_TC_EM_PSEUDO_MASK: registered by an encap match which includes a
+ * match on an optional field (currently ip_tos and/or udp_sport),
+ * to prevent an overlapping encap match _without_ optional fields.
+ * The pseudo encap match may be referenced again by an encap match
+ * with different values for these fields, but all masks must match the
+ * first (stored in our child_* fields).
+ */
+enum efx_tc_em_pseudo_type {
+ EFX_TC_EM_DIRECT,
+ EFX_TC_EM_PSEUDO_MASK,
+};
+
struct efx_tc_encap_match {
__be32 src_ip, dst_ip;
struct in6_addr src_ip6, dst_ip6;
__be16 udp_dport;
+ __be16 udp_sport, udp_sport_mask;
+ u8 ip_tos, ip_tos_mask;
struct rhash_head linkage;
enum efx_encap_type tun_type;
+ u8 child_ip_tos_mask;
+ __be16 child_udp_sport_mask;
refcount_t ref;
+ enum efx_tc_em_pseudo_type type;
u32 fw_id; /* index of this entry in firmware encap match table */
+ struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */
};
struct efx_tc_match {
@@ -100,6 +133,7 @@ struct efx_tc_flow_rule {
struct rhash_head linkage;
struct efx_tc_match match;
struct efx_tc_action_set_list acts;
+ struct efx_tc_action_set_list *fallback; /* what to use when unready? */
u32 fw_id;
};
@@ -117,8 +151,10 @@ enum efx_tc_rule_prios {
* @mutex: Used to serialise operations on TC hashtables
* @counter_ht: Hashtable of TC counters (FW IDs and counter values)
* @counter_id_ht: Hashtable mapping TC counter cookies to counters
+ * @encap_ht: Hashtable of TC encap actions
* @encap_match_ht: Hashtable of TC encap matches
* @match_action_ht: Hashtable of TC match-action rules
+ * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder)
* @reps_mport_id: MAE port allocated for representor RX
* @reps_filter_uc: VNIC filter for representor unicast RX (promisc)
* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti)
@@ -133,6 +169,11 @@ enum efx_tc_rule_prios {
* %EFX_TC_PRIO_DFLT. Named by *ingress* port
* @dflt.pf: rule for traffic ingressing from PF (egresses to wire)
* @dflt.wire: rule for traffic ingressing from wire (egresses to PF)
+ * @facts: Fallback action-set-lists for unready rules. Named by *egress* port
+ * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to
+ * traffic from wire, and egressing to PF
+ * @facts.reps: action-set-list for unready rules on representors, hence
+ * applying to traffic from representees, and egressing to the reps mport
* @up: have TC datastructures been set up?
*/
struct efx_tc_state {
@@ -141,8 +182,10 @@ struct efx_tc_state {
struct mutex mutex;
struct rhashtable counter_ht;
struct rhashtable counter_id_ht;
+ struct rhashtable encap_ht;
struct rhashtable encap_match_ht;
struct rhashtable match_action_ht;
+ struct rhashtable neigh_ht;
u32 reps_mport_id, reps_mport_vport_id;
s32 reps_filter_uc, reps_filter_mc;
bool flush_counters;
@@ -153,11 +196,19 @@ struct efx_tc_state {
struct efx_tc_flow_rule pf;
struct efx_tc_flow_rule wire;
} dflt;
+ struct {
+ struct efx_tc_action_set_list pf;
+ struct efx_tc_action_set_list reps;
+ } facts;
bool up;
};
struct efx_rep;
+enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev);
+struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
+ struct net_device *dev);
+s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv);
int efx_tc_configure_default_rule_rep(struct efx_rep *efv);
void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
struct efx_tc_flow_rule *rule);
diff --git a/drivers/net/ethernet/sfc/tc_bindings.c b/drivers/net/ethernet/sfc/tc_bindings.c
index c18d64519c2d..1b79c535c54e 100644
--- a/drivers/net/ethernet/sfc/tc_bindings.c
+++ b/drivers/net/ethernet/sfc/tc_bindings.c
@@ -10,6 +10,7 @@
#include "tc_bindings.h"
#include "tc.h"
+#include "tc_encap_actions.h"
struct efx_tc_block_binding {
struct list_head list;
@@ -226,3 +227,15 @@ int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type,
return -EOPNOTSUPP;
}
+
+int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev)
+{
+ if (efx->type->is_vf)
+ return NOTIFY_DONE;
+
+ if (event == NETDEV_UNREGISTER)
+ efx_tc_unregister_egdev(efx, net_dev);
+
+ return NOTIFY_OK;
+}
diff --git a/drivers/net/ethernet/sfc/tc_bindings.h b/drivers/net/ethernet/sfc/tc_bindings.h
index c210bb09150e..a326d23d322b 100644
--- a/drivers/net/ethernet/sfc/tc_bindings.h
+++ b/drivers/net/ethernet/sfc/tc_bindings.h
@@ -12,6 +12,7 @@
#define EFX_TC_BINDINGS_H
#include "net_driver.h"
+#if IS_ENABLED(CONFIG_SFC_SRIOV)
#include <net/sch_generic.h>
struct efx_rep;
@@ -26,4 +27,17 @@ int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch,
void *cb_priv, enum tc_setup_type type,
void *type_data, void *data,
void (*cleanup)(struct flow_block_cb *block_cb));
+int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev);
+
+#else /* CONFIG_SFC_SRIOV */
+
+static inline int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
+ struct net_device *net_dev)
+{
+ return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_SFC_SRIOV */
+
#endif /* EFX_TC_BINDINGS_H */
diff --git a/drivers/net/ethernet/sfc/tc_counters.c b/drivers/net/ethernet/sfc/tc_counters.c
index d1a91d54c6bb..979f49058a0c 100644
--- a/drivers/net/ethernet/sfc/tc_counters.c
+++ b/drivers/net/ethernet/sfc/tc_counters.c
@@ -9,6 +9,7 @@
*/
#include "tc_counters.h"
+#include "tc_encap_actions.h"
#include "mae_counter_format.h"
#include "mae.h"
#include "rx_common.h"
@@ -31,6 +32,15 @@ static void efx_tc_counter_free(void *ptr, void *__unused)
{
struct efx_tc_counter *cnt = ptr;
+ WARN_ON(!list_empty(&cnt->users));
+ /* We'd like to synchronize_rcu() here, but unfortunately we aren't
+ * removing the element from the hashtable (it's not clear that's a
+ * safe thing to do in an rhashtable_free_and_destroy free_fn), so
+ * threads could still be obtaining new pointers to *cnt if they can
+ * race against this function at all.
+ */
+ flush_work(&cnt->work);
+ EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock));
kfree(cnt);
}
@@ -74,6 +84,49 @@ void efx_tc_fini_counters(struct efx_nic *efx)
rhashtable_free_and_destroy(&efx->tc->counter_ht, efx_tc_counter_free, NULL);
}
+static void efx_tc_counter_work(struct work_struct *work)
+{
+ struct efx_tc_counter *cnt = container_of(work, struct efx_tc_counter, work);
+ struct efx_tc_encap_action *encap;
+ struct efx_tc_action_set *act;
+ unsigned long touched;
+ struct neighbour *n;
+
+ spin_lock_bh(&cnt->lock);
+ touched = READ_ONCE(cnt->touched);
+
+ list_for_each_entry(act, &cnt->users, count_user) {
+ encap = act->encap_md;
+ if (!encap)
+ continue;
+ if (!encap->neigh) /* can't happen */
+ continue;
+ if (time_after_eq(encap->neigh->used, touched))
+ continue;
+ encap->neigh->used = touched;
+ /* We have passed traffic using this ARP entry, so
+ * indicate to the ARP cache that it's still active
+ */
+ if (encap->neigh->dst_ip)
+ n = neigh_lookup(&arp_tbl, &encap->neigh->dst_ip,
+ encap->neigh->egdev);
+ else
+#if IS_ENABLED(CONFIG_IPV6)
+ n = neigh_lookup(ipv6_stub->nd_tbl,
+ &encap->neigh->dst_ip6,
+ encap->neigh->egdev);
+#else
+ n = NULL;
+#endif
+ if (!n)
+ continue;
+
+ neigh_event_send(n, NULL);
+ neigh_release(n);
+ }
+ spin_unlock_bh(&cnt->lock);
+}
+
/* Counter allocation */
static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx,
@@ -87,12 +140,14 @@ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx
return ERR_PTR(-ENOMEM);
spin_lock_init(&cnt->lock);
+ INIT_WORK(&cnt->work, efx_tc_counter_work);
cnt->touched = jiffies;
cnt->type = type;
rc = efx_mae_allocate_counter(efx, cnt);
if (rc)
goto fail1;
+ INIT_LIST_HEAD(&cnt->users);
rc = rhashtable_insert_fast(&efx->tc->counter_ht, &cnt->linkage,
efx_tc_counter_ht_params);
if (rc)
@@ -126,6 +181,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx,
netif_warn(efx, hw, efx->net_dev,
"Failed to free MAE counter %u, rc %d\n",
cnt->fw_id, rc);
+ WARN_ON(!list_empty(&cnt->users));
/* This doesn't protect counter updates coming in arbitrarily long
* after we deleted the counter. The RCU just ensures that we won't
* free the counter while another thread has a pointer to it.
@@ -133,6 +189,7 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx,
* is handled by the generation count.
*/
synchronize_rcu();
+ flush_work(&cnt->work);
EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock));
kfree(cnt);
}
@@ -302,6 +359,7 @@ static void efx_tc_counter_update(struct efx_nic *efx,
cnt->touched = jiffies;
}
spin_unlock_bh(&cnt->lock);
+ schedule_work(&cnt->work);
out:
rcu_read_unlock();
}
diff --git a/drivers/net/ethernet/sfc/tc_counters.h b/drivers/net/ethernet/sfc/tc_counters.h
index 8fc7c4bbb29c..41e57f34b763 100644
--- a/drivers/net/ethernet/sfc/tc_counters.h
+++ b/drivers/net/ethernet/sfc/tc_counters.h
@@ -32,6 +32,9 @@ struct efx_tc_counter {
u64 old_packets, old_bytes; /* Values last time passed to userspace */
/* jiffies of the last time we saw packets increase */
unsigned long touched;
+ struct work_struct work; /* For notifying encap actions */
+ /* owners of corresponding count actions */
+ struct list_head users;
};
struct efx_tc_counter_index {
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c
new file mode 100644
index 000000000000..7e8bcdb222ad
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.c
@@ -0,0 +1,747 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include "tc_encap_actions.h"
+#include "tc.h"
+#include "mae.h"
+#include <net/vxlan.h>
+#include <net/geneve.h>
+#include <net/netevent.h>
+#include <net/arp.h>
+
+static const struct rhashtable_params efx_neigh_ht_params = {
+ .key_len = offsetof(struct efx_neigh_binder, ha),
+ .key_offset = 0,
+ .head_offset = offsetof(struct efx_neigh_binder, linkage),
+};
+
+static const struct rhashtable_params efx_tc_encap_ht_params = {
+ .key_len = offsetofend(struct efx_tc_encap_action, key),
+ .key_offset = 0,
+ .head_offset = offsetof(struct efx_tc_encap_action, linkage),
+};
+
+static void efx_tc_encap_free(void *ptr, void *__unused)
+{
+ struct efx_tc_encap_action *enc = ptr;
+
+ WARN_ON(refcount_read(&enc->ref));
+ kfree(enc);
+}
+
+static void efx_neigh_free(void *ptr, void *__unused)
+{
+ struct efx_neigh_binder *neigh = ptr;
+
+ WARN_ON(refcount_read(&neigh->ref));
+ WARN_ON(!list_empty(&neigh->users));
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ kfree(neigh);
+}
+
+int efx_tc_init_encap_actions(struct efx_nic *efx)
+{
+ int rc;
+
+ rc = rhashtable_init(&efx->tc->neigh_ht, &efx_neigh_ht_params);
+ if (rc < 0)
+ goto fail_neigh_ht;
+ rc = rhashtable_init(&efx->tc->encap_ht, &efx_tc_encap_ht_params);
+ if (rc < 0)
+ goto fail_encap_ht;
+ return 0;
+fail_encap_ht:
+ rhashtable_destroy(&efx->tc->neigh_ht);
+fail_neigh_ht:
+ return rc;
+}
+
+/* Only call this in init failure teardown.
+ * Normal exit should fini instead as there may be entries in the table.
+ */
+void efx_tc_destroy_encap_actions(struct efx_nic *efx)
+{
+ rhashtable_destroy(&efx->tc->encap_ht);
+ rhashtable_destroy(&efx->tc->neigh_ht);
+}
+
+void efx_tc_fini_encap_actions(struct efx_nic *efx)
+{
+ rhashtable_free_and_destroy(&efx->tc->encap_ht, efx_tc_encap_free, NULL);
+ rhashtable_free_and_destroy(&efx->tc->neigh_ht, efx_neigh_free, NULL);
+}
+
+static void efx_neigh_update(struct work_struct *work);
+
+static int efx_bind_neigh(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap, struct net *net,
+ struct netlink_ext_ack *extack)
+{
+ struct efx_neigh_binder *neigh, *old;
+ struct flowi6 flow6 = {};
+ struct flowi4 flow4 = {};
+ int rc;
+
+ /* GCC stupidly thinks that only values explicitly listed in the enum
+ * definition can _possibly_ be sensible case values, so without this
+ * cast it complains about the IPv6 versions.
+ */
+ switch ((int)encap->type) {
+ case EFX_ENCAP_TYPE_VXLAN:
+ case EFX_ENCAP_TYPE_GENEVE:
+ flow4.flowi4_proto = IPPROTO_UDP;
+ flow4.fl4_dport = encap->key.tp_dst;
+ flow4.flowi4_tos = encap->key.tos;
+ flow4.daddr = encap->key.u.ipv4.dst;
+ flow4.saddr = encap->key.u.ipv4.src;
+ break;
+ case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6:
+ case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6:
+ flow6.flowi6_proto = IPPROTO_UDP;
+ flow6.fl6_dport = encap->key.tp_dst;
+ flow6.flowlabel = ip6_make_flowinfo(encap->key.tos,
+ encap->key.label);
+ flow6.daddr = encap->key.u.ipv6.dst;
+ flow6.saddr = encap->key.u.ipv6.src;
+ break;
+ default:
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported encap type %d",
+ (int)encap->type);
+ return -EOPNOTSUPP;
+ }
+
+ neigh = kzalloc(sizeof(*neigh), GFP_KERNEL_ACCOUNT);
+ if (!neigh)
+ return -ENOMEM;
+ neigh->net = get_net_track(net, &neigh->ns_tracker, GFP_KERNEL_ACCOUNT);
+ neigh->dst_ip = flow4.daddr;
+ neigh->dst_ip6 = flow6.daddr;
+
+ old = rhashtable_lookup_get_insert_fast(&efx->tc->neigh_ht,
+ &neigh->linkage,
+ efx_neigh_ht_params);
+ if (old) {
+ /* don't need our new entry */
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ kfree(neigh);
+ if (!refcount_inc_not_zero(&old->ref))
+ return -EAGAIN;
+ /* existing entry found, ref taken */
+ neigh = old;
+ } else {
+ /* New entry. We need to initiate a lookup */
+ struct neighbour *n;
+ struct rtable *rt;
+
+ if (encap->type & EFX_ENCAP_FLAG_IPV6) {
+#if IS_ENABLED(CONFIG_IPV6)
+ struct dst_entry *dst;
+
+ dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6,
+ NULL);
+ rc = PTR_ERR_OR_ZERO(dst);
+ if (rc) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap");
+ goto out_free;
+ }
+ neigh->egdev = dst->dev;
+ netdev_hold(neigh->egdev, &neigh->dev_tracker,
+ GFP_KERNEL_ACCOUNT);
+ neigh->ttl = ip6_dst_hoplimit(dst);
+ n = dst_neigh_lookup(dst, &flow6.daddr);
+ dst_release(dst);
+#else
+ /* We shouldn't ever get here, because if IPv6 isn't
+ * enabled how did someone create an IPv6 tunnel_key?
+ */
+ rc = -EOPNOTSUPP;
+ NL_SET_ERR_MSG_MOD(extack, "No IPv6 support (neigh bind)");
+ goto out_free;
+#endif
+ } else {
+ rt = ip_route_output_key(net, &flow4);
+ if (IS_ERR_OR_NULL(rt)) {
+ rc = PTR_ERR_OR_ZERO(rt);
+ if (!rc)
+ rc = -EIO;
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for encap");
+ goto out_free;
+ }
+ neigh->egdev = rt->dst.dev;
+ netdev_hold(neigh->egdev, &neigh->dev_tracker,
+ GFP_KERNEL_ACCOUNT);
+ neigh->ttl = ip4_dst_hoplimit(&rt->dst);
+ n = dst_neigh_lookup(&rt->dst, &flow4.daddr);
+ ip_rt_put(rt);
+ }
+ if (!n) {
+ rc = -ENETUNREACH;
+ NL_SET_ERR_MSG_MOD(extack, "Failed to lookup neighbour for encap");
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ goto out_free;
+ }
+ refcount_set(&neigh->ref, 1);
+ INIT_LIST_HEAD(&neigh->users);
+ read_lock_bh(&n->lock);
+ ether_addr_copy(neigh->ha, n->ha);
+ neigh->n_valid = n->nud_state & NUD_VALID;
+ read_unlock_bh(&n->lock);
+ rwlock_init(&neigh->lock);
+ INIT_WORK(&neigh->work, efx_neigh_update);
+ neigh->efx = efx;
+ neigh->used = jiffies;
+ if (!neigh->n_valid)
+ /* Prod ARP to find us a neighbour */
+ neigh_event_send(n, NULL);
+ neigh_release(n);
+ }
+ /* Add us to this neigh */
+ encap->neigh = neigh;
+ list_add_tail(&encap->list, &neigh->users);
+ return 0;
+
+out_free:
+ /* cleanup common to several error paths */
+ rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage,
+ efx_neigh_ht_params);
+ synchronize_rcu();
+ put_net_track(net, &neigh->ns_tracker);
+ kfree(neigh);
+ return rc;
+}
+
+static void efx_free_neigh(struct efx_neigh_binder *neigh)
+{
+ struct efx_nic *efx = neigh->efx;
+
+ rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage,
+ efx_neigh_ht_params);
+ synchronize_rcu();
+ netdev_put(neigh->egdev, &neigh->dev_tracker);
+ put_net_track(neigh->net, &neigh->ns_tracker);
+ kfree(neigh);
+}
+
+static void efx_release_neigh(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+
+ if (!neigh)
+ return;
+ list_del(&encap->list);
+ encap->neigh = NULL;
+ if (!refcount_dec_and_test(&neigh->ref))
+ return; /* still in use */
+ efx_free_neigh(neigh);
+}
+
+static void efx_gen_tun_header_eth(struct efx_tc_encap_action *encap, u16 proto)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ethhdr *eth;
+
+ encap->encap_hdr_len = sizeof(*eth);
+ eth = (struct ethhdr *)encap->encap_hdr;
+
+ if (encap->neigh->n_valid)
+ ether_addr_copy(eth->h_dest, neigh->ha);
+ else
+ eth_zero_addr(eth->h_dest);
+ ether_addr_copy(eth->h_source, neigh->egdev->dev_addr);
+ eth->h_proto = htons(proto);
+}
+
+static void efx_gen_tun_header_ipv4(struct efx_tc_encap_action *encap, u8 ipproto, u8 len)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ip_tunnel_key *key = &encap->key;
+ struct iphdr *ip;
+
+ ip = (struct iphdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*ip);
+
+ ip->daddr = key->u.ipv4.dst;
+ ip->saddr = key->u.ipv4.src;
+ ip->ttl = neigh->ttl;
+ ip->protocol = ipproto;
+ ip->version = 0x4;
+ ip->ihl = 0x5;
+ ip->tot_len = cpu_to_be16(ip->ihl * 4 + len);
+ ip_send_check(ip);
+}
+
+#ifdef CONFIG_IPV6
+static void efx_gen_tun_header_ipv6(struct efx_tc_encap_action *encap, u8 ipproto, u8 len)
+{
+ struct efx_neigh_binder *neigh = encap->neigh;
+ struct ip_tunnel_key *key = &encap->key;
+ struct ipv6hdr *ip;
+
+ ip = (struct ipv6hdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*ip);
+
+ ip6_flow_hdr(ip, key->tos, key->label);
+ ip->daddr = key->u.ipv6.dst;
+ ip->saddr = key->u.ipv6.src;
+ ip->hop_limit = neigh->ttl;
+ ip->nexthdr = ipproto;
+ ip->version = 0x6;
+ ip->payload_len = cpu_to_be16(len);
+}
+#endif
+
+static void efx_gen_tun_header_udp(struct efx_tc_encap_action *encap, u8 len)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct udphdr *udp;
+
+ udp = (struct udphdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*udp);
+
+ udp->dest = key->tp_dst;
+ udp->len = cpu_to_be16(sizeof(*udp) + len);
+}
+
+static void efx_gen_tun_header_vxlan(struct efx_tc_encap_action *encap)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct vxlanhdr *vxlan;
+
+ vxlan = (struct vxlanhdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*vxlan);
+
+ vxlan->vx_flags = VXLAN_HF_VNI;
+ vxlan->vx_vni = vxlan_vni_field(tunnel_id_to_key32(key->tun_id));
+}
+
+static void efx_gen_tun_header_geneve(struct efx_tc_encap_action *encap)
+{
+ struct ip_tunnel_key *key = &encap->key;
+ struct genevehdr *geneve;
+ u32 vni;
+
+ geneve = (struct genevehdr *)(encap->encap_hdr + encap->encap_hdr_len);
+ encap->encap_hdr_len += sizeof(*geneve);
+
+ geneve->proto_type = htons(ETH_P_TEB);
+ /* convert tun_id to host-endian so we can use host arithmetic to
+ * extract individual bytes.
+ */
+ vni = ntohl(tunnel_id_to_key32(key->tun_id));
+ geneve->vni[0] = vni >> 16;
+ geneve->vni[1] = vni >> 8;
+ geneve->vni[2] = vni;
+}
+
+#define vxlan_header_l4_len (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
+#define vxlan4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + vxlan_header_l4_len)
+static void efx_gen_vxlan_header_ipv4(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan4_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IP);
+ efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, vxlan_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr));
+ efx_gen_tun_header_vxlan(encap);
+}
+
+#define geneve_header_l4_len (sizeof(struct udphdr) + sizeof(struct genevehdr))
+#define geneve4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + geneve_header_l4_len)
+static void efx_gen_geneve_header_ipv4(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve4_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IP);
+ efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, geneve_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct genevehdr));
+ efx_gen_tun_header_geneve(encap);
+}
+
+#ifdef CONFIG_IPV6
+#define vxlan6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vxlan_header_l4_len)
+static void efx_gen_vxlan_header_ipv6(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan6_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IPV6);
+ efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, vxlan_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr));
+ efx_gen_tun_header_vxlan(encap);
+}
+
+#define geneve6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + geneve_header_l4_len)
+static void efx_gen_geneve_header_ipv6(struct efx_tc_encap_action *encap)
+{
+ BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve6_header_len);
+ efx_gen_tun_header_eth(encap, ETH_P_IPV6);
+ efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, geneve_header_l4_len);
+ efx_gen_tun_header_udp(encap, sizeof(struct genevehdr));
+ efx_gen_tun_header_geneve(encap);
+}
+#endif
+
+static void efx_gen_encap_header(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ encap->n_valid = encap->neigh->n_valid;
+
+ /* GCC stupidly thinks that only values explicitly listed in the enum
+ * definition can _possibly_ be sensible case values, so without this
+ * cast it complains about the IPv6 versions.
+ */
+ switch ((int)encap->type) {
+ case EFX_ENCAP_TYPE_VXLAN:
+ efx_gen_vxlan_header_ipv4(encap);
+ break;
+ case EFX_ENCAP_TYPE_GENEVE:
+ efx_gen_geneve_header_ipv4(encap);
+ break;
+#ifdef CONFIG_IPV6
+ case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6:
+ efx_gen_vxlan_header_ipv6(encap);
+ break;
+ case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6:
+ efx_gen_geneve_header_ipv6(encap);
+ break;
+#endif
+ default:
+ /* unhandled encap type, can't happen */
+ if (net_ratelimit())
+ netif_err(efx, drv, efx->net_dev,
+ "Bogus encap type %d, can't generate\n",
+ encap->type);
+
+ /* Use fallback action. */
+ encap->n_valid = false;
+ break;
+ }
+}
+
+static void efx_tc_update_encap(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ struct efx_tc_action_set_list *acts, *fallback;
+ struct efx_tc_flow_rule *rule;
+ struct efx_tc_action_set *act;
+ int rc;
+
+ if (encap->n_valid) {
+ /* Make sure no rules are using this encap while we change it */
+ list_for_each_entry(act, &encap->users, encap_user) {
+ acts = act->user;
+ if (WARN_ON(!acts)) /* can't happen */
+ continue;
+ rule = container_of(acts, struct efx_tc_flow_rule, acts);
+ if (rule->fallback)
+ fallback = rule->fallback;
+ else /* fallback fallback: deliver to PF */
+ fallback = &efx->tc->facts.pf;
+ rc = efx_mae_update_rule(efx, fallback->fw_id,
+ rule->fw_id);
+ if (rc)
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update (f) rule %08x rc %d\n",
+ rule->fw_id, rc);
+ else
+ netif_dbg(efx, drv, efx->net_dev, "Updated (f) rule %08x\n",
+ rule->fw_id);
+ }
+ }
+
+ /* Make sure we don't leak arbitrary bytes on the wire;
+ * set an all-0s ethernet header. A successful call to
+ * efx_gen_encap_header() will overwrite this.
+ */
+ memset(encap->encap_hdr, 0, sizeof(encap->encap_hdr));
+ encap->encap_hdr_len = ETH_HLEN;
+
+ if (encap->neigh) {
+ read_lock_bh(&encap->neigh->lock);
+ efx_gen_encap_header(efx, encap);
+ read_unlock_bh(&encap->neigh->lock);
+ } else {
+ encap->n_valid = false;
+ }
+
+ rc = efx_mae_update_encap_md(efx, encap);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update encap hdr %08x rc %d\n",
+ encap->fw_id, rc);
+ return;
+ }
+ netif_dbg(efx, drv, efx->net_dev, "Updated encap hdr %08x\n",
+ encap->fw_id);
+ if (!encap->n_valid)
+ return;
+ /* Update rule users: use the action if they are now ready */
+ list_for_each_entry(act, &encap->users, encap_user) {
+ acts = act->user;
+ if (WARN_ON(!acts)) /* can't happen */
+ continue;
+ rule = container_of(acts, struct efx_tc_flow_rule, acts);
+ if (!efx_tc_check_ready(efx, rule))
+ continue;
+ rc = efx_mae_update_rule(efx, acts->fw_id, rule->fw_id);
+ if (rc)
+ netif_err(efx, drv, efx->net_dev,
+ "Failed to update rule %08x rc %d\n",
+ rule->fw_id, rc);
+ else
+ netif_dbg(efx, drv, efx->net_dev, "Updated rule %08x\n",
+ rule->fw_id);
+ }
+}
+
+static void efx_neigh_update(struct work_struct *work)
+{
+ struct efx_neigh_binder *neigh = container_of(work, struct efx_neigh_binder, work);
+ struct efx_tc_encap_action *encap;
+ struct efx_nic *efx = neigh->efx;
+
+ mutex_lock(&efx->tc->mutex);
+ list_for_each_entry(encap, &neigh->users, list)
+ efx_tc_update_encap(neigh->efx, encap);
+ /* release ref taken in efx_neigh_event() */
+ if (refcount_dec_and_test(&neigh->ref))
+ efx_free_neigh(neigh);
+ mutex_unlock(&efx->tc->mutex);
+}
+
+static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n)
+{
+ struct efx_neigh_binder keys = {NULL}, *neigh;
+ bool n_valid, ipv6 = false;
+ char ha[ETH_ALEN];
+ size_t keysize;
+
+ if (WARN_ON(!efx->tc))
+ return NOTIFY_DONE;
+
+ if (n->tbl == &arp_tbl) {
+ keysize = sizeof(keys.dst_ip);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (n->tbl == ipv6_stub->nd_tbl) {
+ ipv6 = true;
+ keysize = sizeof(keys.dst_ip6);
+#endif
+ } else {
+ return NOTIFY_DONE;
+ }
+ if (!n->parms) {
+ netif_warn(efx, drv, efx->net_dev, "neigh_event with no parms!\n");
+ return NOTIFY_DONE;
+ }
+ keys.net = read_pnet(&n->parms->net);
+ if (n->tbl->key_len != keysize) {
+ netif_warn(efx, drv, efx->net_dev, "neigh_event with bad key_len %u\n",
+ n->tbl->key_len);
+ return NOTIFY_DONE;
+ }
+ read_lock_bh(&n->lock); /* Get a consistent view */
+ memcpy(ha, n->ha, ETH_ALEN);
+ n_valid = (n->nud_state & NUD_VALID) && !n->dead;
+ read_unlock_bh(&n->lock);
+ if (ipv6)
+ memcpy(&keys.dst_ip6, n->primary_key, n->tbl->key_len);
+ else
+ memcpy(&keys.dst_ip, n->primary_key, n->tbl->key_len);
+ rcu_read_lock();
+ neigh = rhashtable_lookup_fast(&efx->tc->neigh_ht, &keys,
+ efx_neigh_ht_params);
+ if (!neigh || neigh->dying)
+ /* We're not interested in this neighbour */
+ goto done;
+ write_lock_bh(&neigh->lock);
+ if (n_valid == neigh->n_valid && !memcmp(ha, neigh->ha, ETH_ALEN)) {
+ write_unlock_bh(&neigh->lock);
+ /* Nothing has changed; no work to do */
+ goto done;
+ }
+ neigh->n_valid = n_valid;
+ memcpy(neigh->ha, ha, ETH_ALEN);
+ write_unlock_bh(&neigh->lock);
+ if (refcount_inc_not_zero(&neigh->ref)) {
+ rcu_read_unlock();
+ if (!schedule_work(&neigh->work))
+ /* failed to schedule, release the ref we just took */
+ if (refcount_dec_and_test(&neigh->ref))
+ efx_free_neigh(neigh);
+ } else {
+done:
+ rcu_read_unlock();
+ }
+ return NOTIFY_DONE;
+}
+
+bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule)
+{
+ struct efx_tc_action_set *act;
+
+ /* Encap actions can only be offloaded if they have valid
+ * neighbour info for the outer Ethernet header.
+ */
+ list_for_each_entry(act, &rule->acts.list, list)
+ if (act->encap_md && !act->encap_md->n_valid)
+ return false;
+ return true;
+}
+
+struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
+ struct efx_nic *efx, const struct ip_tunnel_info *info,
+ struct net_device *egdev, struct netlink_ext_ack *extack)
+{
+ enum efx_encap_type type = efx_tc_indr_netdev_type(egdev);
+ struct efx_tc_encap_action *encap, *old;
+ struct efx_rep *to_efv;
+ s64 rc;
+
+ if (type == EFX_ENCAP_TYPE_NONE) {
+ /* dest is not an encap device */
+ NL_SET_ERR_MSG_MOD(extack, "Not a (supported) tunnel device but tunnel_key is set");
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ rc = efx_mae_check_encap_type_supported(efx, type);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Firmware reports no support for this tunnel type");
+ return ERR_PTR(rc);
+ }
+ /* No support yet for Geneve options */
+ if (info->options_len) {
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel options");
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ switch (info->mode) {
+ case IP_TUNNEL_INFO_TX:
+ break;
+ case IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6:
+ type |= EFX_ENCAP_FLAG_IPV6;
+ break;
+ default:
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported tunnel mode %u",
+ info->mode);
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+ encap = kzalloc(sizeof(*encap), GFP_KERNEL_ACCOUNT);
+ if (!encap)
+ return ERR_PTR(-ENOMEM);
+ encap->type = type;
+ encap->key = info->key;
+ INIT_LIST_HEAD(&encap->users);
+ old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_ht,
+ &encap->linkage,
+ efx_tc_encap_ht_params);
+ if (old) {
+ /* don't need our new entry */
+ kfree(encap);
+ if (!refcount_inc_not_zero(&old->ref))
+ return ERR_PTR(-EAGAIN);
+ /* existing entry found, ref taken */
+ return old;
+ }
+
+ rc = efx_bind_neigh(efx, encap, dev_net(egdev), extack);
+ if (rc < 0)
+ goto out_remove;
+ to_efv = efx_tc_flower_lookup_efv(efx, encap->neigh->egdev);
+ if (IS_ERR(to_efv)) {
+ /* neigh->egdev isn't ours */
+ NL_SET_ERR_MSG_MOD(extack, "Tunnel egress device not on switch");
+ rc = PTR_ERR(to_efv);
+ goto out_release;
+ }
+ rc = efx_tc_flower_external_mport(efx, to_efv);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to identify tunnel egress m-port");
+ goto out_release;
+ }
+ encap->dest_mport = rc;
+ read_lock_bh(&encap->neigh->lock);
+ efx_gen_encap_header(efx, encap);
+ read_unlock_bh(&encap->neigh->lock);
+
+ rc = efx_mae_allocate_encap_md(efx, encap);
+ if (rc < 0) {
+ NL_SET_ERR_MSG_MOD(extack, "Failed to write tunnel header to hw");
+ goto out_release;
+ }
+
+ /* ref and return */
+ refcount_set(&encap->ref, 1);
+ return encap;
+out_release:
+ efx_release_neigh(efx, encap);
+out_remove:
+ rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage,
+ efx_tc_encap_ht_params);
+ kfree(encap);
+ return ERR_PTR(rc);
+}
+
+void efx_tc_flower_release_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap)
+{
+ if (!refcount_dec_and_test(&encap->ref))
+ return; /* still in use */
+ efx_release_neigh(efx, encap);
+ rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage,
+ efx_tc_encap_ht_params);
+ efx_mae_free_encap_md(efx, encap);
+ kfree(encap);
+}
+
+static void efx_tc_remove_neigh_users(struct efx_nic *efx, struct efx_neigh_binder *neigh)
+{
+ struct efx_tc_encap_action *encap, *next;
+
+ list_for_each_entry_safe(encap, next, &neigh->users, list) {
+ /* Should cause neigh usage count to fall to zero, freeing it */
+ efx_release_neigh(efx, encap);
+ /* The encap has lost its neigh, so it's now unready */
+ efx_tc_update_encap(efx, encap);
+ }
+}
+
+void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev)
+{
+ struct efx_neigh_binder *neigh;
+ struct rhashtable_iter walk;
+
+ mutex_lock(&efx->tc->mutex);
+ rhashtable_walk_enter(&efx->tc->neigh_ht, &walk);
+ rhashtable_walk_start(&walk);
+ while ((neigh = rhashtable_walk_next(&walk)) != NULL) {
+ if (IS_ERR(neigh))
+ continue;
+ if (neigh->egdev != net_dev)
+ continue;
+ neigh->dying = true;
+ rhashtable_walk_stop(&walk);
+ synchronize_rcu(); /* Make sure any updates see dying flag */
+ efx_tc_remove_neigh_users(efx, neigh); /* might sleep */
+ rhashtable_walk_start(&walk);
+ }
+ rhashtable_walk_stop(&walk);
+ rhashtable_walk_exit(&walk);
+ mutex_unlock(&efx->tc->mutex);
+}
+
+int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event,
+ void *ptr)
+{
+ if (efx->type->is_vf)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETEVENT_NEIGH_UPDATE:
+ return efx_neigh_event(efx, ptr);
+ default:
+ return NOTIFY_DONE;
+ }
+}
diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.h b/drivers/net/ethernet/sfc/tc_encap_actions.h
new file mode 100644
index 000000000000..c3c7904ad7ff
--- /dev/null
+++ b/drivers/net/ethernet/sfc/tc_encap_actions.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for Solarflare network controllers and boards
+ * Copyright 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef EFX_TC_ENCAP_ACTIONS_H
+#define EFX_TC_ENCAP_ACTIONS_H
+#include "net_driver.h"
+
+#if IS_ENABLED(CONFIG_SFC_SRIOV)
+#include <linux/refcount.h>
+#include <net/tc_act/tc_tunnel_key.h>
+
+/**
+ * struct efx_neigh_binder - driver state for a neighbour entry
+ * @net: the network namespace in which this neigh resides
+ * @dst_ip: the IPv4 destination address resolved by this neigh
+ * @dst_ip6: the IPv6 destination address resolved by this neigh
+ * @ha: the hardware (Ethernet) address of the neighbour
+ * @n_valid: true if the neighbour is in NUD_VALID state
+ * @lock: protects @ha and @n_valid
+ * @ttl: Time To Live associated with the route used
+ * @dying: set when egdev is going away, to skip further updates
+ * @egdev: egress device from the route lookup. Holds a reference
+ * @dev_tracker: reference tracker entry for @egdev
+ * @ns_tracker: reference tracker entry for @ns
+ * @ref: counts encap actions referencing this entry
+ * @used: jiffies of last time traffic hit any encap action using this.
+ * When counter reads update this, a new neighbour event is sent to
+ * indicate that the neighbour entry is still in use.
+ * @users: list of &struct efx_tc_encap_action
+ * @linkage: entry in efx->neigh_ht (keys are @net, @dst_ip, @dst_ip6).
+ * @work: processes neighbour state changes, updates the encap actions
+ * @efx: owning NIC instance.
+ *
+ * Associates a neighbour entry with the encap actions that are
+ * interested in it, allowing the latter to be updated when the
+ * neighbour details change.
+ * Whichever of @dst_ip and @dst_ip6 is not in use will be all-zeroes,
+ * this distinguishes IPv4 from IPv6 entries.
+ */
+struct efx_neigh_binder {
+ struct net *net;
+ __be32 dst_ip;
+ struct in6_addr dst_ip6;
+ char ha[ETH_ALEN];
+ bool n_valid;
+ rwlock_t lock;
+ u8 ttl;
+ bool dying;
+ struct net_device *egdev;
+ netdevice_tracker dev_tracker;
+ netns_tracker ns_tracker;
+ refcount_t ref;
+ unsigned long used;
+ struct list_head users;
+ struct rhash_head linkage;
+ struct work_struct work;
+ struct efx_nic *efx;
+};
+
+/* This limit is arbitrary; current hardware (SN1022) handles encap headers
+ * of up to 126 bytes, but that limit is not enshrined in the MCDI protocol.
+ */
+#define EFX_TC_MAX_ENCAP_HDR 126
+struct efx_tc_encap_action {
+ enum efx_encap_type type;
+ struct ip_tunnel_key key; /* 52 bytes */
+ u32 dest_mport; /* is copied into struct efx_tc_action_set */
+ u8 encap_hdr_len;
+ bool n_valid;
+ u8 encap_hdr[EFX_TC_MAX_ENCAP_HDR];
+ struct efx_neigh_binder *neigh;
+ struct list_head list; /* entry on neigh->users list */
+ struct list_head users; /* action sets using this encap_md */
+ struct rhash_head linkage; /* efx->tc_encap_ht */
+ refcount_t ref;
+ u32 fw_id; /* index of this entry in firmware encap table */
+};
+
+/* create/uncreate/teardown hashtables */
+int efx_tc_init_encap_actions(struct efx_nic *efx);
+void efx_tc_destroy_encap_actions(struct efx_nic *efx);
+void efx_tc_fini_encap_actions(struct efx_nic *efx);
+
+struct efx_tc_flow_rule;
+bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule);
+
+struct efx_tc_encap_action *efx_tc_flower_create_encap_md(
+ struct efx_nic *efx, const struct ip_tunnel_info *info,
+ struct net_device *egdev, struct netlink_ext_ack *extack);
+void efx_tc_flower_release_encap_md(struct efx_nic *efx,
+ struct efx_tc_encap_action *encap);
+
+void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev);
+int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event,
+ void *ptr);
+
+#else /* CONFIG_SFC_SRIOV */
+
+static inline int efx_tc_netevent_event(struct efx_nic *efx,
+ unsigned long event, void *ptr)
+{
+ return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_SFC_SRIOV */
+
+#endif /* EFX_TC_ENCAP_ACTIONS_H */
diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c
index 755aa92bf823..9f2393d34371 100644
--- a/drivers/net/ethernet/sfc/tx_common.c
+++ b/drivers/net/ethernet/sfc/tx_common.c
@@ -12,6 +12,7 @@
#include "efx.h"
#include "nic_common.h"
#include "tx_common.h"
+#include <net/gso.h>
static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue)
{
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 2d7347b71c41..0dcd6a568b06 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev,
return err;
}
+ /*
+ * SynQuacer is physically configured with TX and RX delays
+ * but the standard firmware claimed otherwise for a long
+ * time, ignore it.
+ */
+ if (of_machine_is_compatible("socionext,developer-box") &&
+ priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) {
+ dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n");
+ priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+ }
+
priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
if (!priv->phy_np) {
dev_err(&pdev->dev, "missing required property 'phy-handle'\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 5f5a997f21f3..5583f0b055ec 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -158,6 +158,9 @@ config DWMAC_SOCFPGA
default ARCH_INTEL_SOCFPGA
depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST)
select MFD_SYSCON
+ select MDIO_REGMAP
+ select REGMAP_MMIO
+ select PCS_LYNX
help
Support for ethernet controller on Altera SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 8738fdbb4b2d..7dd3d388068b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o
obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o
obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o
stmmac-platform-objs:= stmmac_platform.o
-dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o
+dwmac-altr-socfpga-objs := dwmac-socfpga.o
obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
deleted file mode 100644
index 00f6d347eaf7..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright Altera Corporation (C) 2016. All rights reserved.
- *
- * Author: Tien Hock Loh <thloh@altera.com>
- */
-
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_net.h>
-#include <linux/phy.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-#include <linux/stmmac.h>
-
-#include "stmmac.h"
-#include "stmmac_platform.h"
-#include "altr_tse_pcs.h"
-
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1)
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2)
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0)
-
-#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12)
-#define TSE_PCS_CONTROL_REG 0x00
-#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9)
-#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140
-#define TSE_PCS_IF_MODE_REG 0x28
-#define TSE_PCS_LINK_TIMER_0_REG 0x24
-#define TSE_PCS_LINK_TIMER_1_REG 0x26
-#define TSE_PCS_SIZE 0x40
-#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5)
-#define TSE_PCS_STATUS_LINK_MASK 0x0004
-#define TSE_PCS_STATUS_REG 0x02
-#define TSE_PCS_SGMII_SPEED_1000 BIT(3)
-#define TSE_PCS_SGMII_SPEED_100 BIT(2)
-#define TSE_PCS_SGMII_SPEED_10 0x0
-#define TSE_PCS_SW_RST_MASK 0x8000
-#define TSE_PCS_PARTNER_ABILITY_REG 0x0A
-#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000
-#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000
-#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000
-#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10)
-#define TSE_PCS_PARTNER_SPEED_1000 BIT(11)
-#define TSE_PCS_PARTNER_SPEED_100 BIT(10)
-#define TSE_PCS_PARTNER_SPEED_10 0x0000
-#define TSE_PCS_PARTNER_SPEED_1000 BIT(11)
-#define TSE_PCS_PARTNER_SPEED_100 BIT(10)
-#define TSE_PCS_PARTNER_SPEED_10 0x0000
-#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2)
-#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40
-#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003
-#define TSE_PCS_SW_RESET_TIMEOUT 100
-#define TSE_PCS_USE_SGMII_AN_MASK BIT(1)
-#define TSE_PCS_USE_SGMII_ENA BIT(0)
-#define TSE_PCS_IF_USE_SGMII 0x03
-
-#define AUTONEGO_LINK_TIMER 20
-
-static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs)
-{
- int counter = 0;
- u16 val;
-
- val = readw(base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_SW_RST_MASK;
- writew(val, base + TSE_PCS_CONTROL_REG);
-
- while (counter < TSE_PCS_SW_RESET_TIMEOUT) {
- val = readw(base + TSE_PCS_CONTROL_REG);
- val &= TSE_PCS_SW_RST_MASK;
- if (val == 0)
- break;
- counter++;
- udelay(1);
- }
- if (counter >= TSE_PCS_SW_RESET_TIMEOUT) {
- dev_err(pcs->dev, "PCS could not get out of sw reset\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs)
-{
- int ret = 0;
-
- writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG);
-
- writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG);
-
- writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG);
- writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG);
-
- ret = tse_pcs_reset(base, pcs);
- if (ret == 0)
- writew(SGMII_ADAPTER_ENABLE,
- pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
-
- return ret;
-}
-
-static void pcs_link_timer_callback(struct tse_pcs *pcs)
-{
- u16 val = 0;
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
-
- val = readw(tse_pcs_base + TSE_PCS_STATUS_REG);
- val &= TSE_PCS_STATUS_LINK_MASK;
-
- if (val != 0) {
- dev_dbg(pcs->dev, "Adapter: Link is established\n");
- writew(SGMII_ADAPTER_ENABLE,
- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- } else {
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
-
-static void auto_nego_timer_callback(struct tse_pcs *pcs)
-{
- u16 val = 0;
- u16 speed = 0;
- u16 duplex = 0;
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
-
- val = readw(tse_pcs_base + TSE_PCS_STATUS_REG);
- val &= TSE_PCS_STATUS_AN_COMPLETED_MASK;
-
- if (val != 0) {
- dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n");
- val = readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG);
- speed = val & TSE_PCS_PARTNER_SPEED_MASK;
- duplex = val & TSE_PCS_PARTNER_DUPLEX_MASK;
-
- if (speed == TSE_PCS_PARTNER_SPEED_10 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 10/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_100 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 100/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_1000 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_FULL)
- dev_dbg(pcs->dev,
- "Adapter: Link Partner is Up - 1000/Full\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_10 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_100 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else if (speed == TSE_PCS_PARTNER_SPEED_1000 &&
- duplex == TSE_PCS_PARTNER_DUPLEX_HALF)
- dev_err(pcs->dev,
- "Adapter does not support Half Duplex\n");
- else
- dev_err(pcs->dev,
- "Adapter: Invalid Partner Speed and Duplex\n");
-
- if (duplex == TSE_PCS_PARTNER_DUPLEX_FULL &&
- (speed == TSE_PCS_PARTNER_SPEED_10 ||
- speed == TSE_PCS_PARTNER_SPEED_100 ||
- speed == TSE_PCS_PARTNER_SPEED_1000))
- writew(SGMII_ADAPTER_ENABLE,
- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- } else {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_RESTART_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- tse_pcs_reset(tse_pcs_base, pcs);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
-
-static void aneg_link_timer_callback(struct timer_list *t)
-{
- struct tse_pcs *pcs = from_timer(pcs, t, aneg_link_timer);
-
- if (pcs->autoneg == AUTONEG_ENABLE)
- auto_nego_timer_callback(pcs);
- else if (pcs->autoneg == AUTONEG_DISABLE)
- pcs_link_timer_callback(pcs);
-}
-
-void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
- unsigned int speed)
-{
- void __iomem *tse_pcs_base = pcs->tse_pcs_base;
- u32 val;
-
- pcs->autoneg = phy_dev->autoneg;
-
- if (phy_dev->autoneg == AUTONEG_ENABLE) {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_AN_EN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val |= TSE_PCS_USE_SGMII_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val |= TSE_PCS_CONTROL_RESTART_AN_MASK;
-
- tse_pcs_reset(tse_pcs_base, pcs);
-
- timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback,
- 0);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- } else if (phy_dev->autoneg == AUTONEG_DISABLE) {
- val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG);
- val &= ~TSE_PCS_CONTROL_AN_EN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val &= ~TSE_PCS_USE_SGMII_AN_MASK;
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG);
- val &= ~TSE_PCS_SGMII_SPEED_MASK;
-
- switch (speed) {
- case 1000:
- val |= TSE_PCS_SGMII_SPEED_1000;
- break;
- case 100:
- val |= TSE_PCS_SGMII_SPEED_100;
- break;
- case 10:
- val |= TSE_PCS_SGMII_SPEED_10;
- break;
- default:
- return;
- }
- writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG);
-
- tse_pcs_reset(tse_pcs_base, pcs);
-
- timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback,
- 0);
- mod_timer(&pcs->aneg_link_timer, jiffies +
- msecs_to_jiffies(AUTONEGO_LINK_TIMER));
- }
-}
diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
deleted file mode 100644
index 694ac25ef426..000000000000
--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright Altera Corporation (C) 2016. All rights reserved.
- *
- * Author: Tien Hock Loh <thloh@altera.com>
- */
-
-#ifndef __TSE_PCS_H__
-#define __TSE_PCS_H__
-
-#include <linux/phy.h>
-#include <linux/timer.h>
-
-#define SGMII_ADAPTER_CTRL_REG 0x00
-#define SGMII_ADAPTER_ENABLE 0x0000
-#define SGMII_ADAPTER_DISABLE 0x0001
-
-struct tse_pcs {
- struct device *dev;
- void __iomem *tse_pcs_base;
- void __iomem *sgmii_adapter_base;
- struct timer_list aneg_link_timer;
- int autoneg;
-};
-
-int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs);
-void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
- unsigned int speed);
-
-#endif /* __TSE_PCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 4ad692c4116c..16e67c18b6f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -519,6 +519,7 @@ struct mac_device_info {
const struct stmmac_tc_ops *tc;
const struct stmmac_mmc_ops *mmc;
struct dw_xpcs *xpcs;
+ struct phylink_pcs *lynx_pcs; /* Lynx external PCS */
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
void __iomem *pcsr; /* vpointer to device CSRs */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
index 9354bf419112..58a7f08e8d78 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c
@@ -141,7 +141,7 @@ MODULE_DEVICE_TABLE(of, anarion_dwmac_match);
static struct platform_driver anarion_dwmac_driver = {
.probe = anarion_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "anarion-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 18acf7dd74e5..9f88530c5e8c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -464,7 +464,7 @@ remove_config:
return ret;
}
-static int dwc_eth_dwmac_remove(struct platform_device *pdev)
+static void dwc_eth_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -477,8 +477,6 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
data->remove(pdev);
stmmac_remove_config_dt(pdev, priv->plat);
-
- return 0;
}
static const struct of_device_id dwc_eth_dwmac_match[] = {
@@ -490,7 +488,7 @@ MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match);
static struct platform_driver dwc_eth_dwmac_driver = {
.probe = dwc_eth_dwmac_probe,
- .remove = dwc_eth_dwmac_remove,
+ .remove_new = dwc_eth_dwmac_remove,
.driver = {
.name = "dwc-eth-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
index ef8f3a940938..20fc455b3337 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -46,22 +46,12 @@ static int dwmac_generic_probe(struct platform_device *pdev)
plat_dat->unicast_filter_entries = 1;
}
- /* Custom initialisation (if needed) */
- if (plat_dat->init) {
- ret = plat_dat->init(pdev, plat_dat->bsp_priv);
- if (ret)
- goto err_remove_config_dt;
- }
-
- ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
if (ret)
- goto err_exit;
+ goto err_remove_config_dt;
return 0;
-err_exit:
- if (plat_dat->exit)
- plat_dat->exit(pdev, plat_dat->bsp_priv);
err_remove_config_dt:
if (pdev->dev.of_node)
stmmac_remove_config_dt(pdev, plat_dat);
@@ -87,7 +77,7 @@ MODULE_DEVICE_TABLE(of, dwmac_generic_match);
static struct platform_driver dwmac_generic_driver = {
.probe = dwmac_generic_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
index 7c228bd0d099..b9378a63f0e8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
@@ -376,7 +376,7 @@ MODULE_DEVICE_TABLE(of, imx_dwmac_match);
static struct platform_driver imx_dwmac_driver = {
.probe = imx_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "imx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
index 378b4dd826bb..8063ba1c3ce8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c
@@ -386,7 +386,7 @@ MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
static struct platform_driver ingenic_mac_driver = {
.probe = ingenic_mac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "ingenic-mac",
.pm = pm_ptr(&ingenic_mac_pm_ops),
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
index 06d287f104be..a5e639ab0b9e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
@@ -169,20 +169,17 @@ err_remove_config_dt:
return ret;
}
-static int intel_eth_plat_remove(struct platform_device *pdev)
+static void intel_eth_plat_remove(struct platform_device *pdev)
{
struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
- int ret;
- ret = stmmac_pltfr_remove(pdev);
+ stmmac_pltfr_remove(pdev);
clk_disable_unprepare(dwmac->tx_clk);
-
- return ret;
}
static struct platform_driver intel_eth_plat_driver = {
.probe = intel_eth_plat_probe,
- .remove = intel_eth_plat_remove,
+ .remove_new = intel_eth_plat_remove,
.driver = {
.name = "intel-eth-plat",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index e888c8a9c830..e39406df8516 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -498,7 +498,7 @@ MODULE_DEVICE_TABLE(of, ipq806x_gmac_dwmac_match);
static struct platform_driver ipq806x_gmac_dwmac_driver = {
.probe = ipq806x_gmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "ipq806x-gmac-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
index 9d77c647badd..18e84ba693a6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
@@ -83,7 +83,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dwmac_match);
static struct platform_driver lpc18xx_dwmac_driver = {
.probe = lpc18xx_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "lpc18xx-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
index 9ae31e3dc821..73c1dfa7ecb1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
@@ -678,15 +678,12 @@ err_remove_config_dt:
return ret;
}
-static int mediatek_dwmac_remove(struct platform_device *pdev)
+static void mediatek_dwmac_remove(struct platform_device *pdev)
{
struct mediatek_dwmac_plat_data *priv_plat = get_stmmac_bsp_priv(&pdev->dev);
- int ret;
- ret = stmmac_pltfr_remove(pdev);
+ stmmac_pltfr_remove(pdev);
mediatek_dwmac_clks_config(priv_plat, false);
-
- return ret;
}
static const struct of_device_id mediatek_dwmac_match[] = {
@@ -701,7 +698,7 @@ MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);
static struct platform_driver mediatek_dwmac_driver = {
.probe = mediatek_dwmac_probe,
- .remove = mediatek_dwmac_remove,
+ .remove_new = mediatek_dwmac_remove,
.driver = {
.name = "dwmac-mediatek",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
index 16fb66a0ca72..7aa5e6bc04eb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
@@ -91,7 +91,7 @@ MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
static struct platform_driver meson6_dwmac_driver = {
.probe = meson6_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "meson6-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index f6754e3643f3..92b16048f91c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -539,7 +539,7 @@ MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
static struct platform_driver meson8b_dwmac_driver = {
.probe = meson8b_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "meson8b-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
index 62a69a91ab22..42954020de2c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c
@@ -231,7 +231,7 @@ MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
static struct platform_driver oxnas_dwmac_driver = {
.probe = oxnas_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "oxnas-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index f07905f00f98..e62940414e54 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -6,6 +6,9 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/property.h>
+
#include "stmmac.h"
#include "stmmac_platform.h"
@@ -72,6 +75,10 @@
#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
+/* MAC_CTRL_REG bits */
+#define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14)
+#define ETHQOS_MAC_CTRL_PORT_SEL BIT(15)
+
struct ethqos_emac_por {
unsigned int offset;
unsigned int value;
@@ -81,22 +88,28 @@ struct ethqos_emac_driver_data {
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
- bool has_emac3;
+ bool has_emac_ge_3;
+ const char *link_clk_name;
+ bool has_integrated_pcs;
struct dwmac4_addrs dwmac4_addrs;
};
struct qcom_ethqos {
struct platform_device *pdev;
void __iomem *rgmii_base;
+ void __iomem *mac_base;
+ int (*configure_func)(struct qcom_ethqos *ethqos);
- unsigned int rgmii_clk_rate;
- struct clk *rgmii_clk;
+ unsigned int link_clk_rate;
+ struct clk *link_clk;
+ struct phy *serdes_phy;
unsigned int speed;
+ int phy_mode;
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
- bool has_emac3;
+ bool has_emac_ge_3;
};
static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
@@ -115,7 +128,7 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
{
unsigned int temp;
- temp = rgmii_readl(ethqos, offset);
+ temp = rgmii_readl(ethqos, offset);
temp = (temp & ~(mask)) | val;
rgmii_writel(ethqos, temp, offset);
}
@@ -123,25 +136,26 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
static void rgmii_dump(void *priv)
{
struct qcom_ethqos *ethqos = priv;
+ struct device *dev = &ethqos->pdev->dev;
- dev_dbg(&ethqos->pdev->dev, "Rgmii register dump\n");
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
+ dev_dbg(dev, "Rgmii register dump\n");
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
- dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
- dev_dbg(&ethqos->pdev->dev, "SDC4_STATUS: %x\n",
+ dev_dbg(dev, "SDC4_STATUS: %x\n",
rgmii_readl(ethqos, SDC4_STATUS));
- dev_dbg(&ethqos->pdev->dev, "SDCC_USR_CTL: %x\n",
+ dev_dbg(dev, "SDCC_USR_CTL: %x\n",
rgmii_readl(ethqos, SDCC_USR_CTL));
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
- dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
- dev_dbg(&ethqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
+ dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
}
@@ -151,23 +165,23 @@ static void rgmii_dump(void *priv)
#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
static void
-ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed)
+ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed)
{
switch (speed) {
case SPEED_1000:
- ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_1000_NOM_CLK_FREQ;
break;
case SPEED_100:
- ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
break;
case SPEED_10:
- ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
+ ethqos->link_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
break;
}
- clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate);
+ clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate);
}
static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
@@ -189,7 +203,7 @@ static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
.por = emac_v2_3_0_por,
.num_por = ARRAY_SIZE(emac_v2_3_0_por),
.rgmii_config_loopback_en = true,
- .has_emac3 = false,
+ .has_emac_ge_3 = false,
};
static const struct ethqos_emac_por emac_v2_1_0_por[] = {
@@ -205,7 +219,7 @@ static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
.por = emac_v2_1_0_por,
.num_por = ARRAY_SIZE(emac_v2_1_0_por),
.rgmii_config_loopback_en = false,
- .has_emac3 = false,
+ .has_emac_ge_3 = false,
};
static const struct ethqos_emac_por emac_v3_0_0_por[] = {
@@ -221,7 +235,41 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
.por = emac_v3_0_0_por,
.num_por = ARRAY_SIZE(emac_v3_0_0_por),
.rgmii_config_loopback_en = false,
- .has_emac3 = true,
+ .has_emac_ge_3 = true,
+ .dwmac4_addrs = {
+ .dma_chan = 0x00008100,
+ .dma_chan_offset = 0x1000,
+ .mtl_chan = 0x00008000,
+ .mtl_chan_offset = 0x1000,
+ .mtl_ets_ctrl = 0x00008010,
+ .mtl_ets_ctrl_offset = 0x1000,
+ .mtl_txq_weight = 0x00008018,
+ .mtl_txq_weight_offset = 0x1000,
+ .mtl_send_slp_cred = 0x0000801c,
+ .mtl_send_slp_cred_offset = 0x1000,
+ .mtl_high_cred = 0x00008020,
+ .mtl_high_cred_offset = 0x1000,
+ .mtl_low_cred = 0x00008024,
+ .mtl_low_cred_offset = 0x1000,
+ },
+};
+
+static const struct ethqos_emac_por emac_v4_0_0_por[] = {
+ { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c },
+ { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 },
+ { .offset = SDCC_USR_CTL, .value = 0x00010800 },
+ { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 },
+};
+
+static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
+ .por = emac_v4_0_0_por,
+ .num_por = ARRAY_SIZE(emac_v3_0_0_por),
+ .rgmii_config_loopback_en = false,
+ .has_emac_ge_3 = true,
+ .link_clk_name = "phyaux",
+ .has_integrated_pcs = true,
.dwmac4_addrs = {
.dma_chan = 0x00008100,
.dma_chan_offset = 0x1000,
@@ -242,6 +290,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
unsigned int val;
int retry = 1000;
@@ -261,7 +310,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
- if (!ethqos->has_emac3) {
+ if (!ethqos->has_emac_ge_3) {
rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
0, SDCC_HC_REG_DLL_CONFIG);
@@ -279,7 +328,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
+ dev_err(dev, "Clear CK_OUT_EN timedout\n");
/* Set CK_OUT_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
@@ -296,13 +345,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev, "Set CK_OUT_EN timedout\n");
+ dev_err(dev, "Set CK_OUT_EN timedout\n");
/* Set DDR_CAL_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
- if (!ethqos->has_emac3) {
+ if (!ethqos->has_emac_ge_3) {
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
0, SDCC_HC_REG_DLL_CONFIG2);
@@ -322,14 +371,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
int phase_shift;
- int phy_mode;
int loopback;
/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
- phy_mode = device_get_phy_mode(&ethqos->pdev->dev);
- if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
- phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
+ if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
+ ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
phase_shift = 0;
else
phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
@@ -373,7 +421,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
/* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns,
* in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns
*/
- if (ethqos->has_emac3) {
+ if (ethqos->has_emac_ge_3) {
/* 0.9 ns */
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
115, SDCC_HC_REG_DDR_CONFIG);
@@ -408,7 +456,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
@@ -448,7 +496,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
@@ -468,16 +516,16 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
loopback, RGMII_IO_MACRO_CONFIG);
break;
default:
- dev_err(&ethqos->pdev->dev,
- "Invalid speed %d\n", ethqos->speed);
+ dev_err(dev, "Invalid speed %d\n", ethqos->speed);
return -EINVAL;
}
return 0;
}
-static int ethqos_configure(struct qcom_ethqos *ethqos)
+static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos)
{
+ struct device *dev = &ethqos->pdev->dev;
volatile unsigned int dll_lock;
unsigned int i, retry = 1000;
@@ -497,7 +545,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
- if (ethqos->has_emac3) {
+ if (ethqos->has_emac_ge_3) {
if (ethqos->speed == SPEED_1000) {
rgmii_writel(ethqos, 0x1800000, SDCC_TEST_CTL);
rgmii_writel(ethqos, 0x2C010800, SDCC_USR_CTL);
@@ -527,7 +575,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
SDCC_HC_REG_DLL_CONFIG);
/* Set USR_CTL bit 26 with mask of 3 bits */
- if (!ethqos->has_emac3)
+ if (!ethqos->has_emac_ge_3)
rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26),
SDCC_USR_CTL);
@@ -540,8 +588,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(&ethqos->pdev->dev,
- "Timeout while waiting for DLL lock\n");
+ dev_err(dev, "Timeout while waiting for DLL lock\n");
}
if (ethqos->speed == SPEED_1000)
@@ -552,24 +599,80 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
return 0;
}
+static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos)
+{
+ int val;
+
+ val = readl(ethqos->mac_base + MAC_CTRL_REG);
+
+ switch (ethqos->speed) {
+ case SPEED_1000:
+ val &= ~ETHQOS_MAC_CTRL_PORT_SEL;
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
+ RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
+ RGMII_IO_MACRO_CONFIG2);
+ break;
+ case SPEED_100:
+ val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE;
+ break;
+ case SPEED_10:
+ val |= ETHQOS_MAC_CTRL_PORT_SEL;
+ val &= ~ETHQOS_MAC_CTRL_SPEED_MODE;
+ break;
+ }
+
+ writel(val, ethqos->mac_base + MAC_CTRL_REG);
+
+ return val;
+}
+
+static int ethqos_configure(struct qcom_ethqos *ethqos)
+{
+ return ethqos->configure_func(ethqos);
+}
+
static void ethqos_fix_mac_speed(void *priv, unsigned int speed)
{
struct qcom_ethqos *ethqos = priv;
ethqos->speed = speed;
- ethqos_update_rgmii_clk(ethqos, speed);
+ ethqos_update_link_clk(ethqos, speed);
ethqos_configure(ethqos);
}
+static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
+{
+ struct qcom_ethqos *ethqos = priv;
+ int ret;
+
+ ret = phy_init(ethqos->serdes_phy);
+ if (ret)
+ return ret;
+
+ ret = phy_power_on(ethqos->serdes_phy);
+ if (ret)
+ return ret;
+
+ return phy_set_speed(ethqos->serdes_phy, ethqos->speed);
+}
+
+static void qcom_ethqos_serdes_powerdown(struct net_device *ndev, void *priv)
+{
+ struct qcom_ethqos *ethqos = priv;
+
+ phy_power_off(ethqos->serdes_phy);
+ phy_exit(ethqos->serdes_phy);
+}
+
static int ethqos_clks_config(void *priv, bool enabled)
{
struct qcom_ethqos *ethqos = priv;
int ret = 0;
if (enabled) {
- ret = clk_prepare_enable(ethqos->rgmii_clk);
+ ret = clk_prepare_enable(ethqos->link_clk);
if (ret) {
- dev_err(&ethqos->pdev->dev, "rgmii_clk enable failed\n");
+ dev_err(&ethqos->pdev->dev, "link_clk enable failed\n");
return ret;
}
@@ -580,18 +683,24 @@ static int ethqos_clks_config(void *priv, bool enabled)
*/
ethqos_set_func_clk_en(ethqos);
} else {
- clk_disable_unprepare(ethqos->rgmii_clk);
+ clk_disable_unprepare(ethqos->link_clk);
}
return ret;
}
+static void ethqos_clks_disable(void *data)
+{
+ ethqos_clks_config(data, false);
+}
+
static int qcom_ethqos_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ const struct ethqos_emac_driver_data *data;
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
- const struct ethqos_emac_driver_data *data;
+ struct device *dev = &pdev->dev;
struct qcom_ethqos *ethqos;
int ret;
@@ -599,90 +708,91 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
return ret;
- plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
+ plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
if (IS_ERR(plat_dat)) {
- dev_err(&pdev->dev, "dt configuration failed\n");
+ dev_err(dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
plat_dat->clks_config = ethqos_clks_config;
- ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
- if (!ethqos) {
- ret = -ENOMEM;
- goto err_mem;
+ ethqos = devm_kzalloc(dev, sizeof(*ethqos), GFP_KERNEL);
+ if (!ethqos)
+ return -ENOMEM;
+
+ ethqos->phy_mode = device_get_phy_mode(dev);
+ switch (ethqos->phy_mode) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ ethqos->configure_func = ethqos_configure_rgmii;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ ethqos->configure_func = ethqos_configure_sgmii;
+ break;
+ case -ENODEV:
+ return -ENODEV;
+ default:
+ return -EINVAL;
}
ethqos->pdev = pdev;
ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
- if (IS_ERR(ethqos->rgmii_base)) {
- ret = PTR_ERR(ethqos->rgmii_base);
- goto err_mem;
- }
+ if (IS_ERR(ethqos->rgmii_base))
+ return PTR_ERR(ethqos->rgmii_base);
+
+ ethqos->mac_base = stmmac_res.addr;
- data = of_device_get_match_data(&pdev->dev);
+ data = of_device_get_match_data(dev);
ethqos->por = data->por;
ethqos->num_por = data->num_por;
ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
- ethqos->has_emac3 = data->has_emac3;
+ ethqos->has_emac_ge_3 = data->has_emac_ge_3;
- ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
- if (IS_ERR(ethqos->rgmii_clk)) {
- ret = PTR_ERR(ethqos->rgmii_clk);
- goto err_mem;
- }
+ ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii");
+ if (IS_ERR(ethqos->link_clk))
+ return PTR_ERR(ethqos->link_clk);
ret = ethqos_clks_config(ethqos, true);
if (ret)
- goto err_mem;
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos);
+ if (ret)
+ return ret;
+
+ ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
+ if (IS_ERR(ethqos->serdes_phy))
+ return PTR_ERR(ethqos->serdes_phy);
ethqos->speed = SPEED_1000;
- ethqos_update_rgmii_clk(ethqos, SPEED_1000);
+ ethqos_update_link_clk(ethqos, SPEED_1000);
ethqos_set_func_clk_en(ethqos);
plat_dat->bsp_priv = ethqos;
plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
plat_dat->dump_debug_regs = rgmii_dump;
plat_dat->has_gmac4 = 1;
- if (ethqos->has_emac3)
+ if (ethqos->has_emac_ge_3)
plat_dat->dwmac4_addrs = &data->dwmac4_addrs;
plat_dat->pmt = 1;
plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
plat_dat->rx_clk_runs_in_lpi = 1;
+ plat_dat->has_integrated_pcs = data->has_integrated_pcs;
- ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
- if (ret)
- goto err_clk;
-
- return ret;
-
-err_clk:
- ethqos_clks_config(ethqos, false);
-
-err_mem:
- stmmac_remove_config_dt(pdev, plat_dat);
-
- return ret;
-}
-
-static int qcom_ethqos_remove(struct platform_device *pdev)
-{
- struct qcom_ethqos *ethqos;
- int ret;
-
- ethqos = get_stmmac_bsp_priv(&pdev->dev);
- if (!ethqos)
- return -ENODEV;
-
- ret = stmmac_pltfr_remove(pdev);
- ethqos_clks_config(ethqos, false);
+ if (ethqos->serdes_phy) {
+ plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
+ plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown;
+ }
- return ret;
+ return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
}
static const struct of_device_id qcom_ethqos_match[] = {
{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
+ { .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data},
{ .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data},
{ .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data},
{ }
@@ -691,7 +801,6 @@ MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
static struct platform_driver qcom_ethqos_driver = {
.probe = qcom_ethqos_probe,
- .remove = qcom_ethqos_remove,
.driver = {
.name = "qcom-ethqos",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 4ea31ccf24d0..d81591b470a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1863,15 +1863,13 @@ err_remove_config_dt:
return ret;
}
-static int rk_gmac_remove(struct platform_device *pdev)
+static void rk_gmac_remove(struct platform_device *pdev)
{
struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev);
stmmac_dvr_remove(&pdev->dev);
rk_gmac_powerdown(bsp_priv);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -1925,7 +1923,7 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
static struct platform_driver rk_gmac_dwmac_driver = {
.probe = rk_gmac_probe,
- .remove = rk_gmac_remove,
+ .remove_new = rk_gmac_remove,
.driver = {
.name = "rk_gmac-dwmac",
.pm = &rk_gmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 6b447d8f0bd8..6267bcb60206 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -10,14 +10,14 @@
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/regmap.h>
+#include <linux/mdio/mdio-regmap.h>
+#include <linux/pcs-lynx.h>
#include <linux/reset.h>
#include <linux/stmmac.h>
#include "stmmac.h"
#include "stmmac_platform.h"
-#include "altr_tse_pcs.h"
-
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
@@ -37,6 +37,10 @@
#define EMAC_SPLITTER_CTRL_SPEED_100 0x3
#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0
+#define SGMII_ADAPTER_CTRL_REG 0x00
+#define SGMII_ADAPTER_ENABLE 0x0000
+#define SGMII_ADAPTER_DISABLE 0x0001
+
struct socfpga_dwmac;
struct socfpga_dwmac_ops {
int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv);
@@ -50,16 +54,18 @@ struct socfpga_dwmac {
struct reset_control *stmmac_rst;
struct reset_control *stmmac_ocp_rst;
void __iomem *splitter_base;
+ void __iomem *tse_pcs_base;
+ void __iomem *sgmii_adapter_base;
bool f2h_ptp_ref_clk;
- struct tse_pcs pcs;
const struct socfpga_dwmac_ops *ops;
+ struct mdio_device *pcs_mdiodev;
};
static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
{
struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
void __iomem *splitter_base = dwmac->splitter_base;
- void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
+ void __iomem *sgmii_adapter_base = dwmac->sgmii_adapter_base;
struct device *dev = dwmac->dev;
struct net_device *ndev = dev_get_drvdata(dev);
struct phy_device *phy_dev = ndev->phydev;
@@ -89,11 +95,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
}
- if (phy_dev && sgmii_adapter_base) {
+ if (phy_dev && sgmii_adapter_base)
writew(SGMII_ADAPTER_ENABLE,
sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
- tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
- }
}
static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
@@ -183,11 +187,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
goto err_node_put;
}
- dwmac->pcs.sgmii_adapter_base =
+ dwmac->sgmii_adapter_base =
devm_ioremap_resource(dev, &res_sgmii_adapter);
- if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) {
- ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base);
+ if (IS_ERR(dwmac->sgmii_adapter_base)) {
+ ret = PTR_ERR(dwmac->sgmii_adapter_base);
goto err_node_put;
}
}
@@ -205,11 +209,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
goto err_node_put;
}
- dwmac->pcs.tse_pcs_base =
+ dwmac->tse_pcs_base =
devm_ioremap_resource(dev, &res_tse_pcs);
- if (IS_ERR(dwmac->pcs.tse_pcs_base)) {
- ret = PTR_ERR(dwmac->pcs.tse_pcs_base);
+ if (IS_ERR(dwmac->tse_pcs_base)) {
+ ret = PTR_ERR(dwmac->tse_pcs_base);
goto err_node_put;
}
}
@@ -235,6 +239,13 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac)
return priv->plat->interface;
}
+static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable)
+{
+ u16 val = enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE;
+
+ writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+}
+
static int socfpga_set_phy_mode_common(int phymode, u32 *val)
{
switch (phymode) {
@@ -310,12 +321,8 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac)
*/
reset_control_deassert(dwmac->stmmac_ocp_rst);
reset_control_deassert(dwmac->stmmac_rst);
- if (phymode == PHY_INTERFACE_MODE_SGMII) {
- if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
- dev_err(dwmac->dev, "Unable to initialize TSE PCS");
- return -EINVAL;
- }
- }
+ if (phymode == PHY_INTERFACE_MODE_SGMII)
+ socfpga_sgmii_config(dwmac, true);
return 0;
}
@@ -367,12 +374,8 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac)
*/
reset_control_deassert(dwmac->stmmac_ocp_rst);
reset_control_deassert(dwmac->stmmac_rst);
- if (phymode == PHY_INTERFACE_MODE_SGMII) {
- if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
- dev_err(dwmac->dev, "Unable to initialize TSE PCS");
- return -EINVAL;
- }
- }
+ if (phymode == PHY_INTERFACE_MODE_SGMII)
+ socfpga_sgmii_config(dwmac, true);
return 0;
}
@@ -443,6 +446,48 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
if (ret)
goto err_dvr_remove;
+ /* Create a regmap for the PCS so that it can be used by the PCS driver,
+ * if we have such a PCS
+ */
+ if (dwmac->tse_pcs_base) {
+ struct regmap_config pcs_regmap_cfg;
+ struct mdio_regmap_config mrc;
+ struct regmap *pcs_regmap;
+ struct mii_bus *pcs_bus;
+
+ memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg));
+ memset(&mrc, 0, sizeof(mrc));
+
+ pcs_regmap_cfg.reg_bits = 16;
+ pcs_regmap_cfg.val_bits = 16;
+ pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1);
+
+ pcs_regmap = devm_regmap_init_mmio(&pdev->dev, dwmac->tse_pcs_base,
+ &pcs_regmap_cfg);
+ if (IS_ERR(pcs_regmap)) {
+ ret = PTR_ERR(pcs_regmap);
+ goto err_dvr_remove;
+ }
+
+ mrc.regmap = pcs_regmap;
+ mrc.parent = &pdev->dev;
+ mrc.valid_addr = 0x0;
+ mrc.autoscan = false;
+
+ snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name);
+ pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc);
+ if (IS_ERR(pcs_bus)) {
+ ret = PTR_ERR(pcs_bus);
+ goto err_dvr_remove;
+ }
+
+ stpriv->hw->lynx_pcs = lynx_pcs_create_mdiodev(pcs_bus, 0);
+ if (IS_ERR(stpriv->hw->lynx_pcs)) {
+ ret = PTR_ERR(stpriv->hw->lynx_pcs);
+ goto err_dvr_remove;
+ }
+ }
+
return 0;
err_dvr_remove:
@@ -453,6 +498,17 @@ err_remove_config_dt:
return ret;
}
+static void socfpga_dwmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct phylink_pcs *pcs = priv->hw->lynx_pcs;
+
+ stmmac_pltfr_remove(pdev);
+
+ lynx_pcs_destroy(pcs);
+}
+
#ifdef CONFIG_PM_SLEEP
static int socfpga_dwmac_resume(struct device *dev)
{
@@ -524,7 +580,7 @@ MODULE_DEVICE_TABLE(of, socfpga_dwmac_match);
static struct platform_driver socfpga_dwmac_driver = {
.probe = socfpga_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = socfpga_dwmac_remove,
.driver = {
.name = "socfpga-dwmac",
.pm = &socfpga_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 4f51a7889642..d3a39d2fb3a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -156,7 +156,7 @@ MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
static struct platform_driver starfive_dwmac_driver = {
.probe = starfive_dwmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "starfive-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index 465ce66ef9c1..dcbb17c4f07a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -317,15 +317,13 @@ err_remove_config_dt:
return ret;
}
-static int sti_dwmac_remove(struct platform_device *pdev)
+static void sti_dwmac_remove(struct platform_device *pdev)
{
struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
stmmac_dvr_remove(&pdev->dev);
clk_disable_unprepare(dwmac->clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -365,7 +363,7 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match);
static struct platform_driver sti_dwmac_driver = {
.probe = sti_dwmac_probe,
- .remove = sti_dwmac_remove,
+ .remove_new = sti_dwmac_remove,
.driver = {
.name = "sti-dwmac",
.pm = &sti_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
index 0616b3a04ff3..bdb4de59a672 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -417,7 +417,7 @@ err_remove_config_dt:
return ret;
}
-static int stm32_dwmac_remove(struct platform_device *pdev)
+static void stm32_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -431,8 +431,6 @@ static int stm32_dwmac_remove(struct platform_device *pdev)
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
-
- return 0;
}
static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
@@ -528,7 +526,7 @@ MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
static struct platform_driver stm32_dwmac_driver = {
.probe = stm32_dwmac_probe,
- .remove = stm32_dwmac_remove,
+ .remove_new = stm32_dwmac_remove,
.driver = {
.name = "stm32-dwmac",
.pm = &stm32_dwmac_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index c2c592ba0eb8..1e714380d125 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1294,7 +1294,7 @@ dwmac_deconfig:
return ret;
}
-static int sun8i_dwmac_remove(struct platform_device *pdev)
+static void sun8i_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
@@ -1309,8 +1309,6 @@ static int sun8i_dwmac_remove(struct platform_device *pdev)
stmmac_pltfr_remove(pdev);
sun8i_dwmac_unset_syscon(gmac);
-
- return 0;
}
static void sun8i_dwmac_shutdown(struct platform_device *pdev)
@@ -1341,7 +1339,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
static struct platform_driver sun8i_dwmac_driver = {
.probe = sun8i_dwmac_probe,
- .remove = sun8i_dwmac_remove,
+ .remove_new = sun8i_dwmac_remove,
.shutdown = sun8i_dwmac_shutdown,
.driver = {
.name = "dwmac-sun8i",
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
index fc3b0acc8f99..50963e91c347 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -179,7 +179,7 @@ MODULE_DEVICE_TABLE(of, sun7i_dwmac_match);
static struct platform_driver sun7i_dwmac_driver = {
.probe = sun7i_gmac_probe,
- .remove = stmmac_pltfr_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "sun7i-dwmac",
.pm = &stmmac_pltfr_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
index bdf990cf2f31..fbb0ccf84afc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
@@ -234,7 +234,8 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
res.addr = mgbe->regs;
res.irq = irq;
- mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL);
+ mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks),
+ sizeof(*mgbe->clks), GFP_KERNEL);
if (!mgbe->clks)
return -ENOMEM;
@@ -353,15 +354,13 @@ disable_clks:
return err;
}
-static int tegra_mgbe_remove(struct platform_device *pdev)
+static void tegra_mgbe_remove(struct platform_device *pdev)
{
struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(&pdev->dev);
clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks);
stmmac_pltfr_remove(pdev);
-
- return 0;
}
static const struct of_device_id tegra_mgbe_match[] = {
@@ -374,7 +373,7 @@ static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resum
static struct platform_driver tegra_mgbe_driver = {
.probe = tegra_mgbe_probe,
- .remove = tegra_mgbe_remove,
+ .remove_new = tegra_mgbe_remove,
.driver = {
.name = "tegra-mgbe",
.pm = &tegra_mgbe_pm_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
index c3f10a92b62b..acbb284be174 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
@@ -198,7 +198,7 @@ static int visconti_eth_clock_probe(struct platform_device *pdev,
return 0;
}
-static int visconti_eth_clock_remove(struct platform_device *pdev)
+static void visconti_eth_clock_remove(struct platform_device *pdev)
{
struct visconti_eth *dwmac = get_stmmac_bsp_priv(&pdev->dev);
struct net_device *ndev = platform_get_drvdata(pdev);
@@ -206,8 +206,6 @@ static int visconti_eth_clock_remove(struct platform_device *pdev)
clk_disable_unprepare(dwmac->phy_ref_clk);
clk_disable_unprepare(priv->plat->stmmac_clk);
-
- return 0;
}
static int visconti_eth_dwmac_probe(struct platform_device *pdev)
@@ -259,23 +257,16 @@ remove_config:
return ret;
}
-static int visconti_eth_dwmac_remove(struct platform_device *pdev)
+static void visconti_eth_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
- int err;
- err = stmmac_pltfr_remove(pdev);
- if (err < 0)
- dev_err(&pdev->dev, "failed to remove platform: %d\n", err);
+ stmmac_pltfr_remove(pdev);
- err = visconti_eth_clock_remove(pdev);
- if (err < 0)
- dev_err(&pdev->dev, "failed to remove clock: %d\n", err);
+ visconti_eth_clock_remove(pdev);
stmmac_remove_config_dt(pdev, priv->plat);
-
- return err;
}
static const struct of_device_id visconti_eth_dwmac_match[] = {
@@ -286,7 +277,7 @@ MODULE_DEVICE_TABLE(of, visconti_eth_dwmac_match);
static struct platform_driver visconti_eth_dwmac_driver = {
.probe = visconti_eth_dwmac_probe,
- .remove = visconti_eth_dwmac_remove,
+ .remove_new = visconti_eth_dwmac_remove,
.driver = {
.name = "visconti-eth-dwmac",
.of_match_table = visconti_eth_dwmac_match,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index df41eac54058..03ceb6a94073 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -240,13 +240,15 @@ void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + GMAC_CONFIG);
+ u32 old_val = value;
if (enable)
value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
else
value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
- writel(value, ioaddr + GMAC_CONFIG);
+ if (value != old_val)
+ writel(value, ioaddr + GMAC_CONFIG);
}
void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
index dfd53264e036..070bd912580b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -368,10 +368,12 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv,
if (likely(intr_status & XGMAC_RI)) {
x->rx_normal_irq_n++;
+ x->rxq_stats[chan].rx_normal_irq_n++;
ret |= handle_rx;
}
if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) {
x->tx_normal_irq_n++;
+ x->txq_stats[chan].tx_normal_irq_n++;
ret |= handle_tx;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 87510951f4e8..6931973028ae 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -937,10 +937,13 @@ static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
{
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
- if (!priv->hw->xpcs)
- return NULL;
+ if (priv->hw->xpcs)
+ return &priv->hw->xpcs->pcs;
+
+ if (priv->hw->lynx_pcs)
+ return priv->hw->lynx_pcs;
- return &priv->hw->xpcs->pcs;
+ return NULL;
}
static void stmmac_mac_config(struct phylink_config *config, unsigned int mode,
@@ -2700,9 +2703,7 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
/* We still have pending packets, let's call for a new scheduling */
if (tx_q->dirty_tx != tx_q->cur_tx)
- hrtimer_start(&tx_q->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
- HRTIMER_MODE_REL);
+ stmmac_tx_timer_arm(priv, queue);
__netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
@@ -2983,9 +2984,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue)
{
struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+ u32 tx_coal_timer = priv->tx_coal_timer[queue];
+
+ if (!tx_coal_timer)
+ return;
hrtimer_start(&tx_q->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
+ STMMAC_COAL_TIMER(tx_coal_timer),
HRTIMER_MODE_REL);
}
@@ -3813,7 +3818,8 @@ static int __stmmac_open(struct net_device *dev,
if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI &&
(!priv->hw->xpcs ||
- xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) {
+ xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73) &&
+ !priv->hw->lynx_pcs) {
ret = stmmac_init_phy(dev);
if (ret) {
netdev_err(priv->dev,
@@ -5794,7 +5800,7 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
}
/* PCS link status */
- if (priv->hw->pcs) {
+ if (priv->hw->pcs && !priv->plat->has_integrated_pcs) {
if (priv->xstats.pcs_link)
netif_carrier_on(priv->dev);
else
@@ -7457,12 +7463,6 @@ void stmmac_dvr_remove(struct device *dev)
netif_carrier_off(ndev);
unregister_netdev(ndev);
- /* Serdes power down needs to happen after VLAN filter
- * is deleted that is triggered by unregister_netdev().
- */
- if (priv->plat->serdes_powerdown)
- priv->plat->serdes_powerdown(ndev, priv->plat->bsp_priv);
-
#ifdef CONFIG_DEBUG_FS
stmmac_exit_fs(ndev);
#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 6807c4c1a0a2..3db1cb0fd160 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -491,7 +491,6 @@ int stmmac_mdio_reset(struct mii_bus *bus)
int stmmac_xpcs_setup(struct mii_bus *bus)
{
struct net_device *ndev = bus->priv;
- struct mdio_device *mdiodev;
struct stmmac_priv *priv;
struct dw_xpcs *xpcs;
int mode, addr;
@@ -501,16 +500,10 @@ int stmmac_xpcs_setup(struct mii_bus *bus)
/* Try to probe the XPCS by scanning all addresses. */
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
- mdiodev = mdio_device_create(bus, addr);
- if (IS_ERR(mdiodev))
+ xpcs = xpcs_create_mdiodev(bus, addr, mode);
+ if (IS_ERR(xpcs))
continue;
- xpcs = xpcs_create(mdiodev, mode);
- if (IS_ERR_OR_NULL(xpcs)) {
- mdio_device_free(mdiodev);
- continue;
- }
-
priv->hw->xpcs = xpcs;
break;
}
@@ -669,10 +662,8 @@ int stmmac_mdio_unregister(struct net_device *ndev)
if (!priv->mii)
return 0;
- if (priv->hw->xpcs) {
- mdio_device_free(priv->hw->xpcs->mdiodev);
+ if (priv->hw->xpcs)
xpcs_destroy(priv->hw->xpcs);
- }
mdiobus_unregister(priv->mii);
priv->mii->priv = NULL;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index eb0b2898daa3..231152ee5a32 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -8,6 +8,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -629,6 +630,39 @@ error_pclk_get:
return ret;
}
+static void devm_stmmac_remove_config_dt(void *data)
+{
+ struct plat_stmmacenet_data *plat = data;
+
+ /* Platform data argument is unused */
+ stmmac_remove_config_dt(NULL, plat);
+}
+
+/**
+ * devm_stmmac_probe_config_dt
+ * @pdev: platform_device structure
+ * @mac: MAC address to use
+ * Description: Devres variant of stmmac_probe_config_dt(). Does not require
+ * the user to call stmmac_remove_config_dt() at driver detach.
+ */
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
+{
+ struct plat_stmmacenet_data *plat;
+ int ret;
+
+ plat = stmmac_probe_config_dt(pdev, mac);
+ if (IS_ERR(plat))
+ return plat;
+
+ ret = devm_add_action_or_reset(&pdev->dev,
+ devm_stmmac_remove_config_dt, plat);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return plat;
+}
+
/**
* stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt()
* @pdev: platform_device structure
@@ -651,12 +685,19 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
return ERR_PTR(-EINVAL);
}
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
+{
+ return ERR_PTR(-EINVAL);
+}
+
void stmmac_remove_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat)
{
}
#endif /* CONFIG_OF */
EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
+EXPORT_SYMBOL_GPL(devm_stmmac_probe_config_dt);
EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
int stmmac_get_platform_resources(struct platform_device *pdev,
@@ -702,25 +743,127 @@ int stmmac_get_platform_resources(struct platform_device *pdev,
EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
/**
- * stmmac_pltfr_remove
+ * stmmac_pltfr_init
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * Description: Call the platform's init callback (if any) and propagate
+ * the return value.
+ */
+int stmmac_pltfr_init(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ int ret = 0;
+
+ if (plat->init)
+ ret = plat->init(pdev, plat->bsp_priv);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_init);
+
+/**
+ * stmmac_pltfr_exit
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * Description: Call the platform's exit callback (if any).
+ */
+void stmmac_pltfr_exit(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat)
+{
+ if (plat->exit)
+ plat->exit(pdev, plat->bsp_priv);
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_exit);
+
+/**
+ * stmmac_pltfr_probe
* @pdev: platform device pointer
- * Description: this function calls the main to free the net resources
- * and calls the platforms hook and release the resources (e.g. mem).
+ * @plat: driver data platform structure
+ * @res: stmmac resources structure
+ * Description: This calls the platform's init() callback and probes the
+ * stmmac driver.
*/
-int stmmac_pltfr_remove(struct platform_device *pdev)
+int stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res)
+{
+ int ret;
+
+ ret = stmmac_pltfr_init(pdev, plat);
+ if (ret)
+ return ret;
+
+ ret = stmmac_dvr_probe(&pdev->dev, plat, res);
+ if (ret) {
+ stmmac_pltfr_exit(pdev, plat);
+ return ret;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_probe);
+
+static void devm_stmmac_pltfr_remove(void *data)
+{
+ struct platform_device *pdev = data;
+
+ stmmac_pltfr_remove_no_dt(pdev);
+}
+
+/**
+ * devm_stmmac_pltfr_probe
+ * @pdev: pointer to the platform device
+ * @plat: driver data platform structure
+ * @res: stmmac resources
+ * Description: Devres variant of stmmac_pltfr_probe(). Allows users to skip
+ * calling stmmac_pltfr_remove() on driver detach.
+ */
+int devm_stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res)
+{
+ int ret;
+
+ ret = stmmac_pltfr_probe(pdev, plat, res);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(&pdev->dev, devm_stmmac_pltfr_remove,
+ pdev);
+}
+EXPORT_SYMBOL_GPL(devm_stmmac_pltfr_probe);
+
+/**
+ * stmmac_pltfr_remove_no_dt
+ * @pdev: pointer to the platform device
+ * Description: This undoes the effects of stmmac_pltfr_probe() by removing the
+ * driver and calling the platform's exit() callback.
+ */
+void stmmac_pltfr_remove_no_dt(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
struct plat_stmmacenet_data *plat = priv->plat;
stmmac_dvr_remove(&pdev->dev);
+ stmmac_pltfr_exit(pdev, plat);
+}
+EXPORT_SYMBOL_GPL(stmmac_pltfr_remove_no_dt);
- if (plat->exit)
- plat->exit(pdev, plat->bsp_priv);
+/**
+ * stmmac_pltfr_remove
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and calls the platforms hook and release the resources (e.g. mem).
+ */
+void stmmac_pltfr_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ struct plat_stmmacenet_data *plat = priv->plat;
+ stmmac_pltfr_remove_no_dt(pdev);
stmmac_remove_config_dt(pdev, plat);
-
- return 0;
}
EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
@@ -739,8 +882,7 @@ static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
ret = stmmac_suspend(dev);
- if (priv->plat->exit)
- priv->plat->exit(pdev, priv->plat->bsp_priv);
+ stmmac_pltfr_exit(pdev, priv->plat);
return ret;
}
@@ -757,9 +899,11 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
+ int ret;
- if (priv->plat->init)
- priv->plat->init(pdev, priv->plat->bsp_priv);
+ ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv);
+ if (ret)
+ return ret;
return stmmac_resume(dev);
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
index 3fff3f59d73d..c5565b2a70ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
@@ -13,13 +13,27 @@
struct plat_stmmacenet_data *
stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
+struct plat_stmmacenet_data *
+devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac);
void stmmac_remove_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat);
int stmmac_get_platform_resources(struct platform_device *pdev,
struct stmmac_resources *stmmac_res);
-int stmmac_pltfr_remove(struct platform_device *pdev);
+int stmmac_pltfr_init(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat);
+void stmmac_pltfr_exit(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat);
+
+int stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res);
+int devm_stmmac_pltfr_probe(struct platform_device *pdev,
+ struct plat_stmmacenet_data *plat,
+ struct stmmac_resources *res);
+void stmmac_pltfr_remove_no_dt(struct platform_device *pdev);
+void stmmac_pltfr_remove(struct platform_device *pdev);
extern const struct dev_pm_ops stmmac_pltfr_pm_ops;
static inline void *get_stmmac_bsp_priv(struct device *dev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 9d55226479b4..ac41ef4cbd2f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -966,8 +966,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
return -EOPNOTSUPP;
}
- if (!qopt->enable)
+ if (qopt->cmd == TAPRIO_CMD_DESTROY)
goto disable;
+ else if (qopt->cmd != TAPRIO_CMD_REPLACE)
+ return -EOPNOTSUPP;
+
if (qopt->num_entries >= dep)
return -EINVAL;
if (!qopt->cycle_time)
@@ -988,7 +991,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
mutex_lock(&priv->plat->est->lock);
priv->plat->est->gcl_size = size;
- priv->plat->est->enable = qopt->enable;
+ priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
mutex_unlock(&priv->plat->est->lock);
for (i = 0; i < size; i++) {
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index d61dfa250feb..b317b9486455 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -1998,10 +1998,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->truesize += hlen - swivel;
skb->len += hlen - swivel;
- __skb_frag_set_page(frag, page->buffer);
+ skb_frag_fill_page_desc(frag, page->buffer, off, hlen - swivel);
__skb_frag_ref(frag);
- skb_frag_off_set(frag, off);
- skb_frag_size_set(frag, hlen - swivel);
/* any more data? */
if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
@@ -2024,10 +2022,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen;
frag++;
- __skb_frag_set_page(frag, page->buffer);
+ skb_frag_fill_page_desc(frag, page->buffer, 0, hlen);
__skb_frag_ref(frag);
- skb_frag_off_set(frag, 0);
- skb_frag_size_set(frag, hlen);
RX_USED_ADD(page, hlen + cp->crc_size);
}
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index a6211b95ed17..3525d5c0d694 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -25,6 +25,7 @@
#endif
#include <net/ip.h>
+#include <net/gso.h>
#include <net/icmp.h>
#include <net/route.h>
diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c
index 3a908db6e5b2..eced87fa261c 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c
@@ -450,7 +450,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev,
am65_cpsw_est_update_state(ndev);
- if (!est_new->taprio.enable) {
+ if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) {
am65_cpsw_stop_est(ndev);
return ret;
}
@@ -476,7 +476,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev,
am65_cpsw_est_set_sched_list(ndev, est_new);
am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf);
- am65_cpsw_est_set(ndev, est_new->taprio.enable);
+ am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE);
if (tact == TACT_PROG) {
ret = am65_cpsw_timer_set(ndev, est_new);
@@ -520,7 +520,7 @@ static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data)
am65_cpsw_cp_taprio(taprio, &est_new->taprio);
ret = am65_cpsw_configure_taprio(ndev, est_new);
if (!ret) {
- if (taprio->enable) {
+ if (taprio->cmd == TAPRIO_CMD_REPLACE) {
devm_kfree(&ndev->dev, port->qos.est_admin);
port->qos.est_admin = est_new;
@@ -564,8 +564,13 @@ purge_est:
static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data)
{
struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+ struct tc_taprio_qopt_offload *taprio = type_data;
struct am65_cpsw_common *common = port->common;
+ if (taprio->cmd != TAPRIO_CMD_REPLACE &&
+ taprio->cmd != TAPRIO_CMD_DESTROY)
+ return -EOPNOTSUPP;
+
if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS))
return -ENODEV;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0c5e783e574c..64bf22cd860c 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -106,23 +106,37 @@ struct cpsw_ale_dev_id {
static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
{
- int idx;
+ int idx, idx2;
+ u32 hi_val = 0;
idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be fetched exceed a word */
+ if (idx != idx2) {
+ idx2 = 2 - idx2; /* flip */
+ hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
+ }
start -= idx * 32;
idx = 2 - idx; /* flip */
- return (ale_entry[idx] >> start) & BITMASK(bits);
+ return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
}
static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
u32 value)
{
- int idx;
+ int idx, idx2;
value &= BITMASK(bits);
- idx = start / 32;
+ idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be set exceed a word */
+ if (idx != idx2) {
+ idx2 = 2 - idx2; /* flip */
+ ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
+ ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
+ }
start -= idx * 32;
- idx = 2 - idx; /* flip */
+ idx = 2 - idx; /* flip */
ale_entry[idx] &= ~(BITMASK(bits) << start);
ale_entry[idx] |= (value << start);
}
diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig
index c9d88673d306..39596cd13539 100644
--- a/drivers/net/ethernet/wangxun/Kconfig
+++ b/drivers/net/ethernet/wangxun/Kconfig
@@ -40,6 +40,16 @@ config NGBE
config TXGBE
tristate "Wangxun(R) 10GbE PCI Express adapters support"
depends on PCI
+ depends on COMMON_CLK
+ select REGMAP
+ select I2C
+ select I2C_DESIGNWARE_PLATFORM
+ select PHYLINK
+ select HWMON if TXGBE=y
+ select SFP
+ select GPIOLIB
+ select GPIOLIB_IRQCHIP
+ select PCS_XPCS
select LIBWX
help
This driver supports Wangxun(R) 10GbE PCI Express family of
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index ca409b4054d0..6321178fc814 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1182,12 +1182,28 @@ static void wx_enable_sec_rx_path(struct wx *wx)
WX_WRITE_FLUSH(wx);
}
+static void wx_vlan_strip_control(struct wx *wx, bool enable)
+{
+ int i, j;
+
+ for (i = 0; i < wx->num_rx_queues; i++) {
+ struct wx_ring *ring = wx->rx_ring[i];
+
+ j = ring->reg_idx;
+ wr32m(wx, WX_PX_RR_CFG(j), WX_PX_RR_CFG_VLAN,
+ enable ? WX_PX_RR_CFG_VLAN : 0);
+ }
+}
+
void wx_set_rx_mode(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);
+ netdev_features_t features;
u32 fctrl, vmolr, vlnctrl;
int count;
+ features = netdev->features;
+
/* Check for Promiscuous and All Multicast modes */
fctrl = rd32(wx, WX_PSR_CTL);
fctrl &= ~(WX_PSR_CTL_UPE | WX_PSR_CTL_MPE);
@@ -1254,6 +1270,13 @@ void wx_set_rx_mode(struct net_device *netdev)
wr32(wx, WX_PSR_VLAN_CTL, vlnctrl);
wr32(wx, WX_PSR_CTL, fctrl);
wr32(wx, WX_PSR_VM_L2CTL(0), vmolr);
+
+ if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
+ (features & NETIF_F_HW_VLAN_STAG_RX))
+ wx_vlan_strip_control(wx, true);
+ else
+ wx_vlan_strip_control(wx, false);
+
}
EXPORT_SYMBOL(wx_set_rx_mode);
@@ -1462,6 +1485,16 @@ static void wx_configure_tx(struct wx *wx)
WX_MAC_TX_CFG_TE, WX_MAC_TX_CFG_TE);
}
+static void wx_restore_vlan(struct wx *wx)
+{
+ u16 vid = 1;
+
+ wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), 0);
+
+ for_each_set_bit_from(vid, wx->active_vlans, VLAN_N_VID)
+ wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
+}
+
/**
* wx_configure_rx - Configure Receive Unit after Reset
* @wx: pointer to private structure
@@ -1478,7 +1511,6 @@ static void wx_configure_rx(struct wx *wx)
psrtype = WX_RDB_PL_CFG_L4HDR |
WX_RDB_PL_CFG_L3HDR |
WX_RDB_PL_CFG_L2HDR |
- WX_RDB_PL_CFG_TUN_TUNHDR |
WX_RDB_PL_CFG_TUN_TUNHDR;
wr32(wx, WX_RDB_PL_CFG(0), psrtype);
@@ -1527,7 +1559,7 @@ void wx_configure(struct wx *wx)
wx_configure_port(wx);
wx_set_rx_mode(wx->netdev);
-
+ wx_restore_vlan(wx);
wx_enable_sec_rx_path(wx);
wx_configure_tx(wx);
@@ -1727,4 +1759,241 @@ int wx_sw_init(struct wx *wx)
}
EXPORT_SYMBOL(wx_sw_init);
+/**
+ * wx_find_vlvf_slot - find the vlanid or the first empty slot
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ *
+ * return the VLVF index where this VLAN id should be placed
+ *
+ **/
+static int wx_find_vlvf_slot(struct wx *wx, u32 vlan)
+{
+ u32 bits = 0, first_empty_slot = 0;
+ int regindex;
+
+ /* short cut the special case */
+ if (vlan == 0)
+ return 0;
+
+ /* Search for the vlan id in the VLVF entries. Save off the first empty
+ * slot found along the way
+ */
+ for (regindex = 1; regindex < WX_PSR_VLAN_SWC_ENTRIES; regindex++) {
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, regindex);
+ bits = rd32(wx, WX_PSR_VLAN_SWC);
+ if (!bits && !(first_empty_slot))
+ first_empty_slot = regindex;
+ else if ((bits & 0x0FFF) == vlan)
+ break;
+ }
+
+ if (regindex >= WX_PSR_VLAN_SWC_ENTRIES) {
+ if (first_empty_slot)
+ regindex = first_empty_slot;
+ else
+ regindex = -ENOMEM;
+ }
+
+ return regindex;
+}
+
+/**
+ * wx_set_vlvf - Set VLAN Pool Filter
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ * @vfta_changed: pointer to boolean flag which indicates whether VFTA
+ * should be changed
+ *
+ * Turn on/off specified bit in VLVF table.
+ **/
+static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
+ bool *vfta_changed)
+{
+ int vlvf_index;
+ u32 vt, bits;
+
+ /* If VT Mode is set
+ * Either vlan_on
+ * make sure the vlan is in VLVF
+ * set the vind bit in the matching VLVFB
+ * Or !vlan_on
+ * clear the pool bit and possibly the vind
+ */
+ vt = rd32(wx, WX_CFG_PORT_CTL);
+ if (!(vt & WX_CFG_PORT_CTL_NUM_VT_MASK))
+ return 0;
+
+ vlvf_index = wx_find_vlvf_slot(wx, vlan);
+ if (vlvf_index < 0)
+ return vlvf_index;
+
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, vlvf_index);
+ if (vlan_on) {
+ /* set the pool bit */
+ if (vind < 32) {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ bits |= (1 << vind);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
+ } else {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ bits |= (1 << (vind - 32));
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
+ }
+ } else {
+ /* clear the pool bit */
+ if (vind < 32) {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ bits &= ~(1 << vind);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits);
+ bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ } else {
+ bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H);
+ bits &= ~(1 << (vind - 32));
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits);
+ bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_L);
+ }
+ }
+
+ if (bits) {
+ wr32(wx, WX_PSR_VLAN_SWC, (WX_PSR_VLAN_SWC_VIEN | vlan));
+ if (!vlan_on && vfta_changed)
+ *vfta_changed = false;
+ } else {
+ wr32(wx, WX_PSR_VLAN_SWC, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * wx_set_vfta - Set VLAN filter table
+ * @wx: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ *
+ * Turn on/off specified VLAN in the VLAN filter table.
+ **/
+static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
+{
+ u32 bitindex, vfta, targetbit;
+ bool vfta_changed = false;
+ int regindex, ret;
+
+ /* this is a 2 part operation - first the VFTA, then the
+ * VLVF and VLVFB if VT Mode is set
+ * We don't write the VFTA until we know the VLVF part succeeded.
+ */
+
+ /* Part 1
+ * The VFTA is a bitstring made up of 128 32-bit registers
+ * that enable the particular VLAN id, much like the MTA:
+ * bits[11-5]: which register
+ * bits[4-0]: which bit in the register
+ */
+ regindex = (vlan >> 5) & 0x7F;
+ bitindex = vlan & 0x1F;
+ targetbit = (1 << bitindex);
+ /* errata 5 */
+ vfta = wx->mac.vft_shadow[regindex];
+ if (vlan_on) {
+ if (!(vfta & targetbit)) {
+ vfta |= targetbit;
+ vfta_changed = true;
+ }
+ } else {
+ if ((vfta & targetbit)) {
+ vfta &= ~targetbit;
+ vfta_changed = true;
+ }
+ }
+ /* Part 2
+ * Call wx_set_vlvf to set VLVFB and VLVF
+ */
+ ret = wx_set_vlvf(wx, vlan, vind, vlan_on, &vfta_changed);
+ if (ret != 0)
+ return ret;
+
+ if (vfta_changed)
+ wr32(wx, WX_PSR_VLAN_TBL(regindex), vfta);
+ wx->mac.vft_shadow[regindex] = vfta;
+
+ return 0;
+}
+
+/**
+ * wx_clear_vfta - Clear VLAN filter table
+ * @wx: pointer to hardware structure
+ *
+ * Clears the VLAN filer table, and the VMDq index associated with the filter
+ **/
+static void wx_clear_vfta(struct wx *wx)
+{
+ u32 offset;
+
+ for (offset = 0; offset < wx->mac.vft_size; offset++) {
+ wr32(wx, WX_PSR_VLAN_TBL(offset), 0);
+ wx->mac.vft_shadow[offset] = 0;
+ }
+
+ for (offset = 0; offset < WX_PSR_VLAN_SWC_ENTRIES; offset++) {
+ wr32(wx, WX_PSR_VLAN_SWC_IDX, offset);
+ wr32(wx, WX_PSR_VLAN_SWC, 0);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_L, 0);
+ wr32(wx, WX_PSR_VLAN_SWC_VM_H, 0);
+ }
+}
+
+int wx_vlan_rx_add_vid(struct net_device *netdev,
+ __be16 proto, u16 vid)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ /* add VID to filter table */
+ wx_set_vfta(wx, vid, VMDQ_P(0), true);
+ set_bit(vid, wx->active_vlans);
+
+ return 0;
+}
+EXPORT_SYMBOL(wx_vlan_rx_add_vid);
+
+int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ /* remove VID from filter table */
+ if (vid)
+ wx_set_vfta(wx, vid, VMDQ_P(0), false);
+ clear_bit(vid, wx->active_vlans);
+
+ return 0;
+}
+EXPORT_SYMBOL(wx_vlan_rx_kill_vid);
+
+/**
+ * wx_start_hw - Prepare hardware for Tx/Rx
+ * @wx: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function
+ * and the generation start_hw function.
+ * Then performs revision-specific operations, if any.
+ **/
+void wx_start_hw(struct wx *wx)
+{
+ int i;
+
+ /* Clear the VLAN filter table */
+ wx_clear_vfta(wx);
+ WX_WRITE_FLUSH(wx);
+ /* Clear the rate limiters */
+ for (i = 0; i < wx->mac.max_tx_queues; i++) {
+ wr32(wx, WX_TDM_RP_IDX, i);
+ wr32(wx, WX_TDM_RP_RATE, 0);
+ }
+}
+EXPORT_SYMBOL(wx_start_hw);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
index c173c56f0ab5..1f93ca32c921 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
@@ -26,10 +26,13 @@ void wx_set_rx_mode(struct net_device *netdev);
int wx_change_mtu(struct net_device *netdev, int new_mtu);
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
void wx_configure(struct wx *wx);
+void wx_start_hw(struct wx *wx);
int wx_disable_pcie_master(struct wx *wx);
int wx_stop_adapter(struct wx *wx);
void wx_reset_misc(struct wx *wx);
int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
int wx_sw_init(struct wx *wx);
+int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
+int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
#endif /* _WX_HW_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 1e8d8b7b0c62..2c3f08be8c37 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -2,14 +2,157 @@
/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
#include <linux/etherdevice.h>
+#include <net/ip6_checksum.h>
#include <net/page_pool.h>
+#include <net/inet_ecn.h>
#include <linux/iopoll.h>
+#include <linux/sctp.h>
#include <linux/pci.h>
+#include <net/tcp.h>
+#include <net/ip.h>
#include "wx_type.h"
#include "wx_lib.h"
#include "wx_hw.h"
+/* Lookup table mapping the HW PTYPE to the bit field for decoding */
+static struct wx_dec_ptype wx_ptype_lookup[256] = {
+ /* L2: mac */
+ [0x11] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x12] = WX_PTT(L2, NONE, NONE, NONE, TS, PAY2),
+ [0x13] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x14] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x15] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+ [0x16] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2),
+ [0x17] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+
+ /* L2: ethertype filter */
+ [0x18 ... 0x1F] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE),
+
+ /* L3: ip non-tunnel */
+ [0x21] = WX_PTT(IP, FGV4, NONE, NONE, NONE, PAY3),
+ [0x22] = WX_PTT(IP, IPV4, NONE, NONE, NONE, PAY3),
+ [0x23] = WX_PTT(IP, IPV4, NONE, NONE, UDP, PAY4),
+ [0x24] = WX_PTT(IP, IPV4, NONE, NONE, TCP, PAY4),
+ [0x25] = WX_PTT(IP, IPV4, NONE, NONE, SCTP, PAY4),
+ [0x29] = WX_PTT(IP, FGV6, NONE, NONE, NONE, PAY3),
+ [0x2A] = WX_PTT(IP, IPV6, NONE, NONE, NONE, PAY3),
+ [0x2B] = WX_PTT(IP, IPV6, NONE, NONE, UDP, PAY3),
+ [0x2C] = WX_PTT(IP, IPV6, NONE, NONE, TCP, PAY4),
+ [0x2D] = WX_PTT(IP, IPV6, NONE, NONE, SCTP, PAY4),
+
+ /* L2: fcoe */
+ [0x30 ... 0x34] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3),
+ [0x38 ... 0x3C] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3),
+
+ /* IPv4 --> IPv4/IPv6 */
+ [0x81] = WX_PTT(IP, IPV4, IPIP, FGV4, NONE, PAY3),
+ [0x82] = WX_PTT(IP, IPV4, IPIP, IPV4, NONE, PAY3),
+ [0x83] = WX_PTT(IP, IPV4, IPIP, IPV4, UDP, PAY4),
+ [0x84] = WX_PTT(IP, IPV4, IPIP, IPV4, TCP, PAY4),
+ [0x85] = WX_PTT(IP, IPV4, IPIP, IPV4, SCTP, PAY4),
+ [0x89] = WX_PTT(IP, IPV4, IPIP, FGV6, NONE, PAY3),
+ [0x8A] = WX_PTT(IP, IPV4, IPIP, IPV6, NONE, PAY3),
+ [0x8B] = WX_PTT(IP, IPV4, IPIP, IPV6, UDP, PAY4),
+ [0x8C] = WX_PTT(IP, IPV4, IPIP, IPV6, TCP, PAY4),
+ [0x8D] = WX_PTT(IP, IPV4, IPIP, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> NONE/IPv4/IPv6 */
+ [0x90] = WX_PTT(IP, IPV4, IG, NONE, NONE, PAY3),
+ [0x91] = WX_PTT(IP, IPV4, IG, FGV4, NONE, PAY3),
+ [0x92] = WX_PTT(IP, IPV4, IG, IPV4, NONE, PAY3),
+ [0x93] = WX_PTT(IP, IPV4, IG, IPV4, UDP, PAY4),
+ [0x94] = WX_PTT(IP, IPV4, IG, IPV4, TCP, PAY4),
+ [0x95] = WX_PTT(IP, IPV4, IG, IPV4, SCTP, PAY4),
+ [0x99] = WX_PTT(IP, IPV4, IG, FGV6, NONE, PAY3),
+ [0x9A] = WX_PTT(IP, IPV4, IG, IPV6, NONE, PAY3),
+ [0x9B] = WX_PTT(IP, IPV4, IG, IPV6, UDP, PAY4),
+ [0x9C] = WX_PTT(IP, IPV4, IG, IPV6, TCP, PAY4),
+ [0x9D] = WX_PTT(IP, IPV4, IG, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC --> NONE/IPv4/IPv6 */
+ [0xA0] = WX_PTT(IP, IPV4, IGM, NONE, NONE, PAY3),
+ [0xA1] = WX_PTT(IP, IPV4, IGM, FGV4, NONE, PAY3),
+ [0xA2] = WX_PTT(IP, IPV4, IGM, IPV4, NONE, PAY3),
+ [0xA3] = WX_PTT(IP, IPV4, IGM, IPV4, UDP, PAY4),
+ [0xA4] = WX_PTT(IP, IPV4, IGM, IPV4, TCP, PAY4),
+ [0xA5] = WX_PTT(IP, IPV4, IGM, IPV4, SCTP, PAY4),
+ [0xA9] = WX_PTT(IP, IPV4, IGM, FGV6, NONE, PAY3),
+ [0xAA] = WX_PTT(IP, IPV4, IGM, IPV6, NONE, PAY3),
+ [0xAB] = WX_PTT(IP, IPV4, IGM, IPV6, UDP, PAY4),
+ [0xAC] = WX_PTT(IP, IPV4, IGM, IPV6, TCP, PAY4),
+ [0xAD] = WX_PTT(IP, IPV4, IGM, IPV6, SCTP, PAY4),
+
+ /* IPv4 --> GRE/NAT --> MAC+VLAN --> NONE/IPv4/IPv6 */
+ [0xB0] = WX_PTT(IP, IPV4, IGMV, NONE, NONE, PAY3),
+ [0xB1] = WX_PTT(IP, IPV4, IGMV, FGV4, NONE, PAY3),
+ [0xB2] = WX_PTT(IP, IPV4, IGMV, IPV4, NONE, PAY3),
+ [0xB3] = WX_PTT(IP, IPV4, IGMV, IPV4, UDP, PAY4),
+ [0xB4] = WX_PTT(IP, IPV4, IGMV, IPV4, TCP, PAY4),
+ [0xB5] = WX_PTT(IP, IPV4, IGMV, IPV4, SCTP, PAY4),
+ [0xB9] = WX_PTT(IP, IPV4, IGMV, FGV6, NONE, PAY3),
+ [0xBA] = WX_PTT(IP, IPV4, IGMV, IPV6, NONE, PAY3),
+ [0xBB] = WX_PTT(IP, IPV4, IGMV, IPV6, UDP, PAY4),
+ [0xBC] = WX_PTT(IP, IPV4, IGMV, IPV6, TCP, PAY4),
+ [0xBD] = WX_PTT(IP, IPV4, IGMV, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> IPv4/IPv6 */
+ [0xC1] = WX_PTT(IP, IPV6, IPIP, FGV4, NONE, PAY3),
+ [0xC2] = WX_PTT(IP, IPV6, IPIP, IPV4, NONE, PAY3),
+ [0xC3] = WX_PTT(IP, IPV6, IPIP, IPV4, UDP, PAY4),
+ [0xC4] = WX_PTT(IP, IPV6, IPIP, IPV4, TCP, PAY4),
+ [0xC5] = WX_PTT(IP, IPV6, IPIP, IPV4, SCTP, PAY4),
+ [0xC9] = WX_PTT(IP, IPV6, IPIP, FGV6, NONE, PAY3),
+ [0xCA] = WX_PTT(IP, IPV6, IPIP, IPV6, NONE, PAY3),
+ [0xCB] = WX_PTT(IP, IPV6, IPIP, IPV6, UDP, PAY4),
+ [0xCC] = WX_PTT(IP, IPV6, IPIP, IPV6, TCP, PAY4),
+ [0xCD] = WX_PTT(IP, IPV6, IPIP, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> NONE/IPv4/IPv6 */
+ [0xD0] = WX_PTT(IP, IPV6, IG, NONE, NONE, PAY3),
+ [0xD1] = WX_PTT(IP, IPV6, IG, FGV4, NONE, PAY3),
+ [0xD2] = WX_PTT(IP, IPV6, IG, IPV4, NONE, PAY3),
+ [0xD3] = WX_PTT(IP, IPV6, IG, IPV4, UDP, PAY4),
+ [0xD4] = WX_PTT(IP, IPV6, IG, IPV4, TCP, PAY4),
+ [0xD5] = WX_PTT(IP, IPV6, IG, IPV4, SCTP, PAY4),
+ [0xD9] = WX_PTT(IP, IPV6, IG, FGV6, NONE, PAY3),
+ [0xDA] = WX_PTT(IP, IPV6, IG, IPV6, NONE, PAY3),
+ [0xDB] = WX_PTT(IP, IPV6, IG, IPV6, UDP, PAY4),
+ [0xDC] = WX_PTT(IP, IPV6, IG, IPV6, TCP, PAY4),
+ [0xDD] = WX_PTT(IP, IPV6, IG, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC -> NONE/IPv4/IPv6 */
+ [0xE0] = WX_PTT(IP, IPV6, IGM, NONE, NONE, PAY3),
+ [0xE1] = WX_PTT(IP, IPV6, IGM, FGV4, NONE, PAY3),
+ [0xE2] = WX_PTT(IP, IPV6, IGM, IPV4, NONE, PAY3),
+ [0xE3] = WX_PTT(IP, IPV6, IGM, IPV4, UDP, PAY4),
+ [0xE4] = WX_PTT(IP, IPV6, IGM, IPV4, TCP, PAY4),
+ [0xE5] = WX_PTT(IP, IPV6, IGM, IPV4, SCTP, PAY4),
+ [0xE9] = WX_PTT(IP, IPV6, IGM, FGV6, NONE, PAY3),
+ [0xEA] = WX_PTT(IP, IPV6, IGM, IPV6, NONE, PAY3),
+ [0xEB] = WX_PTT(IP, IPV6, IGM, IPV6, UDP, PAY4),
+ [0xEC] = WX_PTT(IP, IPV6, IGM, IPV6, TCP, PAY4),
+ [0xED] = WX_PTT(IP, IPV6, IGM, IPV6, SCTP, PAY4),
+
+ /* IPv6 --> GRE/NAT -> MAC--> NONE/IPv */
+ [0xF0] = WX_PTT(IP, IPV6, IGMV, NONE, NONE, PAY3),
+ [0xF1] = WX_PTT(IP, IPV6, IGMV, FGV4, NONE, PAY3),
+ [0xF2] = WX_PTT(IP, IPV6, IGMV, IPV4, NONE, PAY3),
+ [0xF3] = WX_PTT(IP, IPV6, IGMV, IPV4, UDP, PAY4),
+ [0xF4] = WX_PTT(IP, IPV6, IGMV, IPV4, TCP, PAY4),
+ [0xF5] = WX_PTT(IP, IPV6, IGMV, IPV4, SCTP, PAY4),
+ [0xF9] = WX_PTT(IP, IPV6, IGMV, FGV6, NONE, PAY3),
+ [0xFA] = WX_PTT(IP, IPV6, IGMV, IPV6, NONE, PAY3),
+ [0xFB] = WX_PTT(IP, IPV6, IGMV, IPV6, UDP, PAY4),
+ [0xFC] = WX_PTT(IP, IPV6, IGMV, IPV6, TCP, PAY4),
+ [0xFD] = WX_PTT(IP, IPV6, IGMV, IPV6, SCTP, PAY4),
+};
+
+static struct wx_dec_ptype wx_decode_ptype(const u8 ptype)
+{
+ return wx_ptype_lookup[ptype];
+}
+
/* wx_test_staterr - tests bits in Rx descriptor status and error fields */
static __le32 wx_test_staterr(union wx_rx_desc *rx_desc,
const u32 stat_err_bits)
@@ -419,6 +562,116 @@ static bool wx_cleanup_headers(struct wx_ring *rx_ring,
return false;
}
+static void wx_rx_hash(struct wx_ring *ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ u16 rss_type;
+
+ if (!(ring->netdev->features & NETIF_F_RXHASH))
+ return;
+
+ rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
+ WX_RXD_RSSTYPE_MASK;
+
+ if (!rss_type)
+ return;
+
+ skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
+ (WX_RSS_L4_TYPES_MASK & (1ul << rss_type)) ?
+ PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
+}
+
+/**
+ * wx_rx_checksum - indicate in skb if hw indicated a good cksum
+ * @ring: structure containing ring specific data
+ * @rx_desc: current Rx descriptor being processed
+ * @skb: skb currently being received and modified
+ **/
+static void wx_rx_checksum(struct wx_ring *ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct wx_dec_ptype dptype = wx_decode_ptype(WX_RXD_PKTTYPE(rx_desc));
+
+ skb_checksum_none_assert(skb);
+ /* Rx csum disabled */
+ if (!(ring->netdev->features & NETIF_F_RXCSUM))
+ return;
+
+ /* if IPv4 header checksum error */
+ if ((wx_test_staterr(rx_desc, WX_RXD_STAT_IPCS) &&
+ wx_test_staterr(rx_desc, WX_RXD_ERR_IPE)) ||
+ (wx_test_staterr(rx_desc, WX_RXD_STAT_OUTERIPCS) &&
+ wx_test_staterr(rx_desc, WX_RXD_ERR_OUTERIPER))) {
+ ring->rx_stats.csum_err++;
+ return;
+ }
+
+ /* L4 checksum offload flag must set for the below code to work */
+ if (!wx_test_staterr(rx_desc, WX_RXD_STAT_L4CS))
+ return;
+
+ /* Hardware can't guarantee csum if IPv6 Dest Header found */
+ if (dptype.prot != WX_DEC_PTYPE_PROT_SCTP && WX_RXD_IPV6EX(rx_desc))
+ return;
+
+ /* if L4 checksum error */
+ if (wx_test_staterr(rx_desc, WX_RXD_ERR_TCPE)) {
+ ring->rx_stats.csum_err++;
+ return;
+ }
+
+ /* It must be a TCP or UDP or SCTP packet with a valid checksum */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ /* If there is an outer header present that might contain a checksum
+ * we need to bump the checksum level by 1 to reflect the fact that
+ * we are indicating we validated the inner checksum.
+ */
+ if (dptype.etype >= WX_DEC_PTYPE_ETYPE_IG)
+ __skb_incr_checksum_unnecessary(skb);
+ ring->rx_stats.csum_good_cnt++;
+}
+
+static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ u16 ethertype;
+ u8 idx = 0;
+
+ if ((ring->netdev->features &
+ (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) &&
+ wx_test_staterr(rx_desc, WX_RXD_STAT_VP)) {
+ idx = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) &
+ 0x1c0) >> 6;
+ ethertype = ring->q_vector->wx->tpid[idx];
+ __vlan_hwaccel_put_tag(skb, htons(ethertype),
+ le16_to_cpu(rx_desc->wb.upper.vlan));
+ }
+}
+
+/**
+ * wx_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, protocol, and
+ * other fields within the skb.
+ **/
+static void wx_process_skb_fields(struct wx_ring *rx_ring,
+ union wx_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ wx_rx_hash(rx_ring, rx_desc, skb);
+ wx_rx_checksum(rx_ring, rx_desc, skb);
+ wx_rx_vlan(rx_ring, rx_desc, skb);
+ skb_record_rx_queue(skb, rx_ring->queue_index);
+ skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
/**
* wx_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf
* @q_vector: structure containing interrupt and ring information
@@ -486,8 +739,8 @@ static int wx_clean_rx_irq(struct wx_q_vector *q_vector,
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
- skb_record_rx_queue(skb, rx_ring->queue_index);
- skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+ /* populate checksum, timestamp, VLAN, and protocol */
+ wx_process_skb_fields(rx_ring, rx_desc, skb);
napi_gro_receive(&q_vector->napi, skb);
/* update budget accounting */
@@ -707,11 +960,50 @@ static int wx_maybe_stop_tx(struct wx_ring *tx_ring, u16 size)
return 0;
}
+static u32 wx_tx_cmd_type(u32 tx_flags)
+{
+ /* set type for advanced descriptor with frame checksum insertion */
+ u32 cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS;
+
+ /* set HW vlan bit if vlan is present */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_HW_VLAN, WX_TXD_VLE);
+ /* set segmentation enable bits for TSO/FSO */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSO, WX_TXD_TSE);
+ /* set timestamp bit if present */
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSTAMP, WX_TXD_MAC_TSTAMP);
+ cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_LINKSEC, WX_TXD_LINKSEC);
+
+ return cmd_type;
+}
+
+static void wx_tx_olinfo_status(union wx_tx_desc *tx_desc,
+ u32 tx_flags, unsigned int paylen)
+{
+ u32 olinfo_status = paylen << WX_TXD_PAYLEN_SHIFT;
+
+ /* enable L4 checksum for TSO and TX checksum offload */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CSUM, WX_TXD_L4CS);
+ /* enable IPv4 checksum for TSO */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPV4, WX_TXD_IIPCS);
+ /* enable outer IPv4 checksum for TSO */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_OUTER_IPV4,
+ WX_TXD_EIPCS);
+ /* Check Context must be set if Tx switch is enabled, which it
+ * always is for case where virtual functions are running
+ */
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CC, WX_TXD_CC);
+ olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPSEC,
+ WX_TXD_IPSEC);
+ tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+}
+
static void wx_tx_map(struct wx_ring *tx_ring,
- struct wx_tx_buffer *first)
+ struct wx_tx_buffer *first,
+ const u8 hdr_len)
{
struct sk_buff *skb = first->skb;
struct wx_tx_buffer *tx_buffer;
+ u32 tx_flags = first->tx_flags;
u16 i = tx_ring->next_to_use;
unsigned int data_len, size;
union wx_tx_desc *tx_desc;
@@ -719,10 +1011,9 @@ static void wx_tx_map(struct wx_ring *tx_ring,
dma_addr_t dma;
u32 cmd_type;
- cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS;
+ cmd_type = wx_tx_cmd_type(tx_flags);
tx_desc = WX_TX_DESC(tx_ring, i);
-
- tx_desc->read.olinfo_status = cpu_to_le32(skb->len << WX_TXD_PAYLEN_SHIFT);
+ wx_tx_olinfo_status(tx_desc, tx_flags, skb->len - hdr_len);
size = skb_headlen(skb);
data_len = skb->data_len;
@@ -838,12 +1129,399 @@ dma_error:
tx_ring->next_to_use = i;
}
+static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens,
+ u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
+{
+ struct wx_tx_context_desc *context_desc;
+ u16 i = tx_ring->next_to_use;
+
+ context_desc = WX_TX_CTXTDESC(tx_ring, i);
+ i++;
+ tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
+
+ /* set bits to identify this as an advanced context descriptor */
+ type_tucmd |= WX_TXD_DTYP_CTXT;
+ context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
+ context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
+ context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
+ context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
+}
+
+static void wx_get_ipv6_proto(struct sk_buff *skb, int offset, u8 *nexthdr)
+{
+ struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset);
+
+ *nexthdr = hdr->nexthdr;
+ offset += sizeof(struct ipv6hdr);
+ while (ipv6_ext_hdr(*nexthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+
+ if (*nexthdr == NEXTHDR_NONE)
+ return;
+ hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr);
+ if (!hp)
+ return;
+ if (*nexthdr == NEXTHDR_FRAGMENT)
+ break;
+ *nexthdr = hp->nexthdr;
+ }
+}
+
+union network_header {
+ struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
+ void *raw;
+};
+
+static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first)
+{
+ u8 tun_prot = 0, l4_prot = 0, ptype = 0;
+ struct sk_buff *skb = first->skb;
+
+ if (skb->encapsulation) {
+ union network_header hdr;
+
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ ptype = WX_PTYPE_TUN_IPV4;
+ break;
+ case htons(ETH_P_IPV6):
+ wx_get_ipv6_proto(skb, skb_network_offset(skb), &tun_prot);
+ ptype = WX_PTYPE_TUN_IPV6;
+ break;
+ default:
+ return ptype;
+ }
+
+ if (tun_prot == IPPROTO_IPIP) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ ptype |= WX_PTYPE_PKT_IPIP;
+ } else if (tun_prot == IPPROTO_UDP) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
+ skb->inner_protocol != htons(ETH_P_TEB)) {
+ ptype |= WX_PTYPE_PKT_IG;
+ } else {
+ if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto
+ == htons(ETH_P_8021Q))
+ ptype |= WX_PTYPE_PKT_IGMV;
+ else
+ ptype |= WX_PTYPE_PKT_IGM;
+ }
+
+ } else if (tun_prot == IPPROTO_GRE) {
+ hdr.raw = (void *)inner_ip_hdr(skb);
+ if (skb->inner_protocol == htons(ETH_P_IP) ||
+ skb->inner_protocol == htons(ETH_P_IPV6)) {
+ ptype |= WX_PTYPE_PKT_IG;
+ } else {
+ if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto
+ == htons(ETH_P_8021Q))
+ ptype |= WX_PTYPE_PKT_IGMV;
+ else
+ ptype |= WX_PTYPE_PKT_IGM;
+ }
+ } else {
+ return ptype;
+ }
+
+ switch (hdr.ipv4->version) {
+ case IPVERSION:
+ l4_prot = hdr.ipv4->protocol;
+ break;
+ case 6:
+ wx_get_ipv6_proto(skb, skb_inner_network_offset(skb), &l4_prot);
+ ptype |= WX_PTYPE_PKT_IPV6;
+ break;
+ default:
+ return ptype;
+ }
+ } else {
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ l4_prot = ip_hdr(skb)->protocol;
+ ptype = WX_PTYPE_PKT_IP;
+ break;
+ case htons(ETH_P_IPV6):
+ wx_get_ipv6_proto(skb, skb_network_offset(skb), &l4_prot);
+ ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6;
+ break;
+ default:
+ return WX_PTYPE_PKT_MAC | WX_PTYPE_TYP_MAC;
+ }
+ }
+ switch (l4_prot) {
+ case IPPROTO_TCP:
+ ptype |= WX_PTYPE_TYP_TCP;
+ break;
+ case IPPROTO_UDP:
+ ptype |= WX_PTYPE_TYP_UDP;
+ break;
+ case IPPROTO_SCTP:
+ ptype |= WX_PTYPE_TYP_SCTP;
+ break;
+ default:
+ ptype |= WX_PTYPE_TYP_IP;
+ break;
+ }
+
+ return ptype;
+}
+
+static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
+ u8 *hdr_len, u8 ptype)
+{
+ u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
+ struct net_device *netdev = tx_ring->netdev;
+ u32 l4len, tunhdr_eiplen_tunlen = 0;
+ struct sk_buff *skb = first->skb;
+ bool enc = skb->encapsulation;
+ struct ipv6hdr *ipv6h;
+ struct tcphdr *tcph;
+ struct iphdr *iph;
+ u8 tun_prot = 0;
+ int err;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ if (!skb_is_gso(skb))
+ return 0;
+
+ err = skb_cow_head(skb, 0);
+ if (err < 0)
+ return err;
+
+ /* indicates the inner headers in the skbuff are valid. */
+ iph = enc ? inner_ip_hdr(skb) : ip_hdr(skb);
+ if (iph->version == 4) {
+ tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+ iph->tot_len = 0;
+ iph->check = 0;
+ tcph->check = ~csum_tcpudp_magic(iph->saddr,
+ iph->daddr, 0,
+ IPPROTO_TCP, 0);
+ first->tx_flags |= WX_TX_FLAGS_TSO |
+ WX_TX_FLAGS_CSUM |
+ WX_TX_FLAGS_IPV4 |
+ WX_TX_FLAGS_CC;
+ } else if (iph->version == 6 && skb_is_gso_v6(skb)) {
+ ipv6h = enc ? inner_ipv6_hdr(skb) : ipv6_hdr(skb);
+ tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb);
+ ipv6h->payload_len = 0;
+ tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
+ &ipv6h->daddr, 0,
+ IPPROTO_TCP, 0);
+ first->tx_flags |= WX_TX_FLAGS_TSO |
+ WX_TX_FLAGS_CSUM |
+ WX_TX_FLAGS_CC;
+ }
+
+ /* compute header lengths */
+ l4len = enc ? inner_tcp_hdrlen(skb) : tcp_hdrlen(skb);
+ *hdr_len = enc ? (skb_inner_transport_header(skb) - skb->data) :
+ skb_transport_offset(skb);
+ *hdr_len += l4len;
+
+ /* update gso size and bytecount with header size */
+ first->gso_segs = skb_shinfo(skb)->gso_segs;
+ first->bytecount += (first->gso_segs - 1) * *hdr_len;
+
+ /* mss_l4len_id: use 0 as index for TSO */
+ mss_l4len_idx = l4len << WX_TXD_L4LEN_SHIFT;
+ mss_l4len_idx |= skb_shinfo(skb)->gso_size << WX_TXD_MSS_SHIFT;
+
+ /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
+ if (enc) {
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ first->tx_flags |= WX_TX_FLAGS_OUTER_IPV4;
+ break;
+ case htons(ETH_P_IPV6):
+ tun_prot = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ break;
+ }
+ switch (tun_prot) {
+ case IPPROTO_UDP:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_GRE:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_IPIP:
+ tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) -
+ (char *)ip_hdr(skb)) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+ vlan_macip_lens = skb_inner_network_header_len(skb) >> 1;
+ } else {
+ vlan_macip_lens = skb_network_header_len(skb) >> 1;
+ }
+
+ vlan_macip_lens |= skb_network_offset(skb) << WX_TXD_MACLEN_SHIFT;
+ vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK;
+
+ type_tucmd = ptype << 24;
+ if (skb->vlan_proto == htons(ETH_P_8021AD) &&
+ netdev->features & NETIF_F_HW_VLAN_STAG_TX)
+ type_tucmd |= WX_SET_FLAG(first->tx_flags,
+ WX_TX_FLAGS_HW_VLAN,
+ 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT);
+ wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen,
+ type_tucmd, mss_l4len_idx);
+
+ return 1;
+}
+
+static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first,
+ u8 ptype)
+{
+ u32 tunhdr_eiplen_tunlen = 0, vlan_macip_lens = 0;
+ struct net_device *netdev = tx_ring->netdev;
+ u32 mss_l4len_idx = 0, type_tucmd;
+ struct sk_buff *skb = first->skb;
+ u8 tun_prot = 0;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ if (!(first->tx_flags & WX_TX_FLAGS_HW_VLAN) &&
+ !(first->tx_flags & WX_TX_FLAGS_CC))
+ return;
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ } else {
+ u8 l4_prot = 0;
+ union {
+ struct iphdr *ipv4;
+ struct ipv6hdr *ipv6;
+ u8 *raw;
+ } network_hdr;
+ union {
+ struct tcphdr *tcphdr;
+ u8 *raw;
+ } transport_hdr;
+
+ if (skb->encapsulation) {
+ network_hdr.raw = skb_inner_network_header(skb);
+ transport_hdr.raw = skb_inner_transport_header(skb);
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ switch (first->protocol) {
+ case htons(ETH_P_IP):
+ tun_prot = ip_hdr(skb)->protocol;
+ break;
+ case htons(ETH_P_IPV6):
+ tun_prot = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ return;
+ }
+ switch (tun_prot) {
+ case IPPROTO_UDP:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP;
+ tunhdr_eiplen_tunlen |=
+ ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_GRE:
+ tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE;
+ tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT) |
+ (((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) >> 1) <<
+ WX_TXD_TUNNEL_LEN_SHIFT);
+ break;
+ case IPPROTO_IPIP:
+ tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) -
+ (char *)ip_hdr(skb)) >> 2) <<
+ WX_TXD_OUTER_IPLEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ } else {
+ network_hdr.raw = skb_network_header(skb);
+ transport_hdr.raw = skb_transport_header(skb);
+ vlan_macip_lens = skb_network_offset(skb) <<
+ WX_TXD_MACLEN_SHIFT;
+ }
+
+ switch (network_hdr.ipv4->version) {
+ case IPVERSION:
+ vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1;
+ l4_prot = network_hdr.ipv4->protocol;
+ break;
+ case 6:
+ vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1;
+ l4_prot = network_hdr.ipv6->nexthdr;
+ break;
+ default:
+ break;
+ }
+
+ switch (l4_prot) {
+ case IPPROTO_TCP:
+ mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_SCTP:
+ mss_l4len_idx = sizeof(struct sctphdr) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ case IPPROTO_UDP:
+ mss_l4len_idx = sizeof(struct udphdr) <<
+ WX_TXD_L4LEN_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ /* update TX checksum flag */
+ first->tx_flags |= WX_TX_FLAGS_CSUM;
+ }
+ first->tx_flags |= WX_TX_FLAGS_CC;
+ /* vlan_macip_lens: MACLEN, VLAN tag */
+ vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK;
+
+ type_tucmd = ptype << 24;
+ if (skb->vlan_proto == htons(ETH_P_8021AD) &&
+ netdev->features & NETIF_F_HW_VLAN_STAG_TX)
+ type_tucmd |= WX_SET_FLAG(first->tx_flags,
+ WX_TX_FLAGS_HW_VLAN,
+ 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT);
+ wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen,
+ type_tucmd, mss_l4len_idx);
+}
+
static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb,
struct wx_ring *tx_ring)
{
u16 count = TXD_USE_COUNT(skb_headlen(skb));
struct wx_tx_buffer *first;
+ u8 hdr_len = 0, ptype;
unsigned short f;
+ u32 tx_flags = 0;
+ int tso;
/* need: 1 descriptor per page * PAGE_SIZE/WX_MAX_DATA_PER_TXD,
* + 1 desc for skb_headlen/WX_MAX_DATA_PER_TXD,
@@ -864,7 +1542,29 @@ static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb,
first->bytecount = skb->len;
first->gso_segs = 1;
- wx_tx_map(tx_ring, first);
+ /* if we have a HW VLAN tag being added default to the HW one */
+ if (skb_vlan_tag_present(skb)) {
+ tx_flags |= skb_vlan_tag_get(skb) << WX_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= WX_TX_FLAGS_HW_VLAN;
+ }
+
+ /* record initial flags and protocol */
+ first->tx_flags = tx_flags;
+ first->protocol = vlan_get_protocol(skb);
+
+ ptype = wx_encode_tx_desc_ptype(first);
+
+ tso = wx_tso(tx_ring, first, &hdr_len, ptype);
+ if (tso < 0)
+ goto out_drop;
+ else if (!tso)
+ wx_tx_csum(tx_ring, first, ptype);
+ wx_tx_map(tx_ring, first, hdr_len);
+
+ return NETDEV_TX_OK;
+out_drop:
+ dev_kfree_skb_any(first->skb);
+ first->skb = NULL;
return NETDEV_TX_OK;
}
@@ -1348,7 +2048,8 @@ void wx_free_irq(struct wx *wx)
free_irq(entry->vector, q_vector);
}
- free_irq(wx->msix_entries[vector].vector, wx);
+ if (wx->mac.type == wx_mac_em)
+ free_irq(wx->msix_entries[vector].vector, wx);
}
EXPORT_SYMBOL(wx_free_irq);
@@ -2004,4 +2705,24 @@ void wx_get_stats64(struct net_device *netdev,
}
EXPORT_SYMBOL(wx_get_stats64);
+int wx_set_features(struct net_device *netdev, netdev_features_t features)
+{
+ netdev_features_t changed = netdev->features ^ features;
+ struct wx *wx = netdev_priv(netdev);
+
+ if (changed & NETIF_F_RXHASH)
+ wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
+ WX_RDB_RA_CTL_RSS_EN);
+ else
+ wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
+
+ if (changed &
+ (NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_STAG_RX))
+ wx_set_rx_mode(netdev);
+
+ return 1;
+}
+EXPORT_SYMBOL(wx_set_features);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index 50ee41f1fa10..df1f4a5951f0 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -28,5 +28,6 @@ void wx_free_resources(struct wx *wx);
int wx_setup_resources(struct wx *wx);
void wx_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats);
+int wx_set_features(struct net_device *netdev, netdev_features_t features);
#endif /* _NGBE_LIB_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 32f952d93009..29dfb561887d 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -6,6 +6,8 @@
#include <linux/bitfield.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
#define WX_NCSI_SUP 0x8000
#define WX_NCSI_MASK 0x8000
@@ -64,6 +66,8 @@
#define WX_CFG_PORT_CTL_QINQ BIT(2)
#define WX_CFG_PORT_CTL_D_VLAN BIT(0) /* double vlan*/
#define WX_CFG_TAG_TPID(_i) (0x14430 + ((_i) * 4))
+#define WX_CFG_PORT_CTL_NUM_VT_MASK GENMASK(13, 12) /* number of TVs */
+
/* GPIO Registers */
#define WX_GPIO_DR 0x14800
@@ -79,7 +83,9 @@
#define WX_GPIO_INTMASK 0x14834
#define WX_GPIO_INTTYPE_LEVEL 0x14838
#define WX_GPIO_POLARITY 0x1483C
+#define WX_GPIO_INTSTATUS 0x14844
#define WX_GPIO_EOI 0x1484C
+#define WX_GPIO_EXT 0x14850
/*********************** Transmit DMA registers **************************/
/* transmit global control */
@@ -87,6 +93,8 @@
/* TDM CTL BIT */
#define WX_TDM_CTL_TE BIT(0) /* Transmit Enable */
#define WX_TDM_PB_THRE(_i) (0x18020 + ((_i) * 4))
+#define WX_TDM_RP_IDX 0x1820C
+#define WX_TDM_RP_RATE 0x18404
/***************************** RDB registers *********************************/
/* receive packet buffer */
@@ -105,6 +113,8 @@
#define WX_RDB_PL_CFG_L2HDR BIT(3)
#define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4)
#define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5)
+#define WX_RDB_RA_CTL 0x194F4
+#define WX_RDB_RA_CTL_RSS_EN BIT(2) /* RSS Enable */
/******************************* PSR Registers *******************************/
/* psr control */
@@ -150,6 +160,9 @@
#define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16))
+/* vlan tbl */
+#define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4))
+
/* mac switcher */
#define WX_PSR_MAC_SWC_AD_L 0x16200
#define WX_PSR_MAC_SWC_AD_H 0x16204
@@ -161,6 +174,15 @@
#define WX_PSR_MAC_SWC_IDX 0x16210
#define WX_CLEAR_VMDQ_ALL 0xFFFFFFFFU
+/* vlan switch */
+#define WX_PSR_VLAN_SWC 0x16220
+#define WX_PSR_VLAN_SWC_VM_L 0x16224
+#define WX_PSR_VLAN_SWC_VM_H 0x16228
+#define WX_PSR_VLAN_SWC_IDX 0x16230 /* 64 vlan entries */
+/* VLAN pool filtering masks */
+#define WX_PSR_VLAN_SWC_VIEN BIT(31) /* filter is valid */
+#define WX_PSR_VLAN_SWC_ENTRIES 64
+
/********************************* RSEC **************************************/
/* general rsec */
#define WX_RSC_CTL 0x17000
@@ -255,6 +277,7 @@
#define WX_PX_RR_RP(_i) (0x0100C + ((_i) * 0x40))
#define WX_PX_RR_CFG(_i) (0x01010 + ((_i) * 0x40))
/* PX_RR_CFG bit definitions */
+#define WX_PX_RR_CFG_VLAN BIT(31)
#define WX_PX_RR_CFG_SPLIT_MODE BIT(26)
#define WX_PX_RR_CFG_RR_THER_SHIFT 16
#define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12)
@@ -296,6 +319,7 @@
#define WX_MAX_TXD 8192
#define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */
+#define VMDQ_P(p) p
/* Supported Rx Buffer Sizes */
#define WX_RXBUFFER_256 256 /* Used for skb receive header */
@@ -315,17 +339,64 @@
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), WX_MAX_DATA_PER_TXD)
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
-/* Ether Types */
-#define WX_ETH_P_CNM 0x22E7
-
#define WX_CFG_PORT_ST 0x14404
/******************* Receive Descriptor bit definitions **********************/
#define WX_RXD_STAT_DD BIT(0) /* Done */
#define WX_RXD_STAT_EOP BIT(1) /* End of Packet */
+#define WX_RXD_STAT_VP BIT(5) /* IEEE VLAN Pkt */
+#define WX_RXD_STAT_L4CS BIT(7) /* L4 xsum calculated */
+#define WX_RXD_STAT_IPCS BIT(8) /* IP xsum calculated */
+#define WX_RXD_STAT_OUTERIPCS BIT(10) /* Cloud IP xsum calculated*/
+#define WX_RXD_ERR_OUTERIPER BIT(26) /* CRC IP Header error */
#define WX_RXD_ERR_RXE BIT(29) /* Any MAC Error */
-
+#define WX_RXD_ERR_TCPE BIT(30) /* TCP/UDP Checksum Error */
+#define WX_RXD_ERR_IPE BIT(31) /* IP Checksum Error */
+
+/* RSS Hash results */
+#define WX_RXD_RSSTYPE_MASK GENMASK(3, 0)
+#define WX_RXD_RSSTYPE_IPV4_TCP 0x00000001U
+#define WX_RXD_RSSTYPE_IPV6_TCP 0x00000003U
+#define WX_RXD_RSSTYPE_IPV4_SCTP 0x00000004U
+#define WX_RXD_RSSTYPE_IPV6_SCTP 0x00000006U
+#define WX_RXD_RSSTYPE_IPV4_UDP 0x00000007U
+#define WX_RXD_RSSTYPE_IPV6_UDP 0x00000008U
+
+#define WX_RSS_L4_TYPES_MASK \
+ ((1ul << WX_RXD_RSSTYPE_IPV4_TCP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV4_UDP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV4_SCTP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_TCP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_UDP) | \
+ (1ul << WX_RXD_RSSTYPE_IPV6_SCTP))
+/* TUN */
+#define WX_PTYPE_TUN_IPV4 0x80
+#define WX_PTYPE_TUN_IPV6 0xC0
+
+/* PKT for TUN */
+#define WX_PTYPE_PKT_IPIP 0x00 /* IP+IP */
+#define WX_PTYPE_PKT_IG 0x10 /* IP+GRE */
+#define WX_PTYPE_PKT_IGM 0x20 /* IP+GRE+MAC */
+#define WX_PTYPE_PKT_IGMV 0x30 /* IP+GRE+MAC+VLAN */
+/* PKT for !TUN */
+#define WX_PTYPE_PKT_MAC 0x10
+#define WX_PTYPE_PKT_IP 0x20
+
+/* TYP for PKT=mac */
+#define WX_PTYPE_TYP_MAC 0x01
+/* TYP for PKT=ip */
+#define WX_PTYPE_PKT_IPV6 0x08
+#define WX_PTYPE_TYP_IPFRAG 0x01
+#define WX_PTYPE_TYP_IP 0x02
+#define WX_PTYPE_TYP_UDP 0x03
+#define WX_PTYPE_TYP_TCP 0x04
+#define WX_PTYPE_TYP_SCTP 0x05
+
+#define WX_RXD_PKTTYPE(_rxd) \
+ ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF)
+#define WX_RXD_IPV6EX(_rxd) \
+ ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 6) & 0x1)
/*********************** Transmit Descriptor Config Masks ****************/
#define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */
#define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */
@@ -334,6 +405,113 @@
#define WX_TXD_IFCS BIT(25) /* Insert FCS */
#define WX_TXD_RS BIT(27) /* Report Status */
+/*********************** Adv Transmit Descriptor Config Masks ****************/
+#define WX_TXD_MAC_TSTAMP BIT(19) /* IEEE1588 time stamp */
+#define WX_TXD_DTYP_CTXT BIT(20) /* Adv Context Desc */
+#define WX_TXD_LINKSEC BIT(26) /* enable linksec */
+#define WX_TXD_VLE BIT(30) /* VLAN pkt enable */
+#define WX_TXD_TSE BIT(31) /* TCP Seg enable */
+#define WX_TXD_CC BIT(7) /* Check Context */
+#define WX_TXD_IPSEC BIT(8) /* enable ipsec esp */
+#define WX_TXD_L4CS BIT(9)
+#define WX_TXD_IIPCS BIT(10)
+#define WX_TXD_EIPCS BIT(11)
+#define WX_TXD_PAYLEN_SHIFT 13 /* Adv desc PAYLEN shift */
+#define WX_TXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
+#define WX_TXD_TAG_TPID_SEL_SHIFT 11
+
+#define WX_TXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
+#define WX_TXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
+
+#define WX_TXD_OUTER_IPLEN_SHIFT 12 /* Adv ctxt OUTERIPLEN shift */
+#define WX_TXD_TUNNEL_LEN_SHIFT 21 /* Adv ctxt TUNNELLEN shift */
+#define WX_TXD_TUNNEL_TYPE_SHIFT 11 /* Adv Tx Desc Tunnel Type shift */
+#define WX_TXD_TUNNEL_UDP FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 0)
+#define WX_TXD_TUNNEL_GRE FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 1)
+
+enum wx_tx_flags {
+ /* cmd_type flags */
+ WX_TX_FLAGS_HW_VLAN = 0x01,
+ WX_TX_FLAGS_TSO = 0x02,
+ WX_TX_FLAGS_TSTAMP = 0x04,
+
+ /* olinfo flags */
+ WX_TX_FLAGS_CC = 0x08,
+ WX_TX_FLAGS_IPV4 = 0x10,
+ WX_TX_FLAGS_CSUM = 0x20,
+ WX_TX_FLAGS_OUTER_IPV4 = 0x100,
+ WX_TX_FLAGS_LINKSEC = 0x200,
+ WX_TX_FLAGS_IPSEC = 0x400,
+};
+
+/* VLAN info */
+#define WX_TX_FLAGS_VLAN_MASK GENMASK(31, 16)
+#define WX_TX_FLAGS_VLAN_SHIFT 16
+
+/* wx_dec_ptype.mac: outer mac */
+enum wx_dec_ptype_mac {
+ WX_DEC_PTYPE_MAC_IP = 0,
+ WX_DEC_PTYPE_MAC_L2 = 2,
+ WX_DEC_PTYPE_MAC_FCOE = 3,
+};
+
+/* wx_dec_ptype.[e]ip: outer&encaped ip */
+#define WX_DEC_PTYPE_IP_FRAG 0x4
+enum wx_dec_ptype_ip {
+ WX_DEC_PTYPE_IP_NONE = 0,
+ WX_DEC_PTYPE_IP_IPV4 = 1,
+ WX_DEC_PTYPE_IP_IPV6 = 2,
+ WX_DEC_PTYPE_IP_FGV4 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV4,
+ WX_DEC_PTYPE_IP_FGV6 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV6,
+};
+
+/* wx_dec_ptype.etype: encaped type */
+enum wx_dec_ptype_etype {
+ WX_DEC_PTYPE_ETYPE_NONE = 0,
+ WX_DEC_PTYPE_ETYPE_IPIP = 1, /* IP+IP */
+ WX_DEC_PTYPE_ETYPE_IG = 2, /* IP+GRE */
+ WX_DEC_PTYPE_ETYPE_IGM = 3, /* IP+GRE+MAC */
+ WX_DEC_PTYPE_ETYPE_IGMV = 4, /* IP+GRE+MAC+VLAN */
+};
+
+/* wx_dec_ptype.proto: payload proto */
+enum wx_dec_ptype_prot {
+ WX_DEC_PTYPE_PROT_NONE = 0,
+ WX_DEC_PTYPE_PROT_UDP = 1,
+ WX_DEC_PTYPE_PROT_TCP = 2,
+ WX_DEC_PTYPE_PROT_SCTP = 3,
+ WX_DEC_PTYPE_PROT_ICMP = 4,
+ WX_DEC_PTYPE_PROT_TS = 5, /* time sync */
+};
+
+/* wx_dec_ptype.layer: payload layer */
+enum wx_dec_ptype_layer {
+ WX_DEC_PTYPE_LAYER_NONE = 0,
+ WX_DEC_PTYPE_LAYER_PAY2 = 1,
+ WX_DEC_PTYPE_LAYER_PAY3 = 2,
+ WX_DEC_PTYPE_LAYER_PAY4 = 3,
+};
+
+struct wx_dec_ptype {
+ u32 known:1;
+ u32 mac:2; /* outer mac */
+ u32 ip:3; /* outer ip*/
+ u32 etype:3; /* encaped type */
+ u32 eip:3; /* encaped ip */
+ u32 prot:4; /* payload proto */
+ u32 layer:3; /* payload layer */
+};
+
+/* macro to make the table lines short */
+#define WX_PTT(mac, ip, etype, eip, proto, layer)\
+ {1, \
+ WX_DEC_PTYPE_MAC_##mac, /* mac */\
+ WX_DEC_PTYPE_IP_##ip, /* ip */ \
+ WX_DEC_PTYPE_ETYPE_##etype, /* etype */\
+ WX_DEC_PTYPE_IP_##eip, /* eip */\
+ WX_DEC_PTYPE_PROT_##proto, /* proto */\
+ WX_DEC_PTYPE_LAYER_##layer /* layer */}
+
/* Host Interface Command Structures */
struct wx_hic_hdr {
u8 cmd;
@@ -412,6 +590,8 @@ struct wx_mac_info {
u32 mta_shadow[128];
s32 mc_filter_type;
u32 mcft_size;
+ u32 vft_shadow[128];
+ u32 vft_size;
u32 num_rar_entries;
u32 rx_pb_size;
u32 tx_pb_size;
@@ -508,10 +688,25 @@ union wx_rx_desc {
} wb; /* writeback */
};
+struct wx_tx_context_desc {
+ __le32 vlan_macip_lens;
+ __le32 seqnum_seed;
+ __le32 type_tucmd_mlhl;
+ __le32 mss_l4len_idx;
+};
+
+/* if _flag is in _input, return _result */
+#define WX_SET_FLAG(_input, _flag, _result) \
+ (((_flag) <= (_result)) ? \
+ ((u32)((_input) & (_flag)) * ((_result) / (_flag))) : \
+ ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
+
#define WX_RX_DESC(R, i) \
(&(((union wx_rx_desc *)((R)->desc))[i]))
#define WX_TX_DESC(R, i) \
(&(((union wx_tx_desc *)((R)->desc))[i]))
+#define WX_TX_CTXTDESC(R, i) \
+ (&(((struct wx_tx_context_desc *)((R)->desc))[i]))
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
@@ -523,6 +718,8 @@ struct wx_tx_buffer {
unsigned short gso_segs;
DEFINE_DMA_UNMAP_ADDR(dma);
DEFINE_DMA_UNMAP_LEN(len);
+ __be16 protocol;
+ u32 tx_flags;
};
struct wx_rx_buffer {
@@ -539,6 +736,11 @@ struct wx_queue_stats {
u64 bytes;
};
+struct wx_rx_queue_stats {
+ u64 csum_good_cnt;
+ u64 csum_err;
+};
+
/* iterator for handling rings in ring container */
#define wx_for_each_ring(posm, headm) \
for (posm = (headm).ring; posm; posm = posm->next)
@@ -550,7 +752,6 @@ struct wx_ring_container {
u8 count; /* total number of rings in vector */
u8 itr; /* current ITR setting for ring */
};
-
struct wx_ring {
struct wx_ring *next; /* pointer to next ring in q_vector */
struct wx_q_vector *q_vector; /* backpointer to host q_vector */
@@ -580,6 +781,9 @@ struct wx_ring {
struct wx_queue_stats stats;
struct u64_stats_sync syncp;
+ union {
+ struct wx_rx_queue_stats rx_stats;
+ };
} ____cacheline_internodealigned_in_smp;
struct wx_q_vector {
@@ -598,7 +802,7 @@ struct wx_q_vector {
char name[IFNAMSIZ + 17];
/* for dynamic allocation of rings associated with this q_vector */
- struct wx_ring ring[0] ____cacheline_internodealigned_in_smp;
+ struct wx_ring ring[] ____cacheline_internodealigned_in_smp;
};
enum wx_isb_idx {
@@ -610,6 +814,9 @@ enum wx_isb_idx {
};
struct wx {
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+
+ void *priv;
u8 __iomem *hw_addr;
struct pci_dev *pdev;
struct net_device *netdev;
@@ -642,6 +849,7 @@ struct wx {
bool wol_enabled;
bool ncsi_enabled;
bool gpio_ctrl;
+ raw_spinlock_t gpio_lock;
/* Tx fast path data */
int num_tx_queues;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index df6b870aa871..c99a5d3de72e 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -115,6 +115,7 @@ static int ngbe_sw_init(struct wx *wx)
wx->mac.max_rx_queues = NGBE_MAX_RX_QUEUES;
wx->mac.max_tx_queues = NGBE_MAX_TX_QUEUES;
wx->mac.mcft_size = NGBE_MC_TBL_SIZE;
+ wx->mac.vft_size = NGBE_SP_VFT_TBL_SIZE;
wx->mac.rx_pb_size = NGBE_RX_PB_SIZE;
wx->mac.tx_pb_size = NGBE_TDB_PB_SZ;
@@ -473,9 +474,12 @@ static const struct net_device_ops ngbe_netdev_ops = {
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
.ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = wx_set_mac,
.ndo_get_stats64 = wx_get_stats64,
+ .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,
};
/**
@@ -551,12 +555,18 @@ static int ngbe_probe(struct pci_dev *pdev,
ngbe_set_ethtool_ops(netdev);
netdev->netdev_ops = &ngbe_netdev_ops;
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->features = NETIF_F_SG;
-
+ netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_RXHASH | NETIF_F_RXCSUM;
+ netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_TSO_MANGLEID;
+ netdev->vlan_features |= netdev->features;
+ netdev->features |= NETIF_F_IPV6_CSUM | NETIF_F_VLAN_FEATURES;
/* copy netdev features into list of user selectable features */
- netdev->hw_features |= netdev->features |
- NETIF_F_RXALL;
+ netdev->hw_features |= netdev->features | NETIF_F_RXALL;
+ netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->hw_features |= NETIF_F_GRO;
+ netdev->features |= NETIF_F_GRO;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 373d5af628cd..b70eca397b67 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -136,6 +136,7 @@ enum NGBE_MSCA_CMD_value {
#define NGBE_RAR_ENTRIES 32
#define NGBE_RX_PB_SIZE 42
#define NGBE_MC_TBL_SIZE 128
+#define NGBE_SP_VFT_TBL_SIZE 128
#define NGBE_TDB_PB_SZ (20 * 1024) /* 160KB Packet Buffer */
/* TX/RX descriptor defines */
diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile
index 6db14a2cb2d0..7507f762edfe 100644
--- a/drivers/net/ethernet/wangxun/txgbe/Makefile
+++ b/drivers/net/ethernet/wangxun/txgbe/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o
txgbe-objs := txgbe_main.o \
txgbe_hw.o \
+ txgbe_phy.o \
txgbe_ethtool.o
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
index d914e9a05404..859da112586a 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
@@ -6,11 +6,39 @@
#include <linux/netdevice.h>
#include "../libwx/wx_ethtool.h"
+#include "../libwx/wx_type.h"
+#include "txgbe_type.h"
#include "txgbe_ethtool.h"
+static int txgbe_nway_reset(struct net_device *netdev)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_nway_reset(txgbe->phylink);
+}
+
+static int txgbe_get_link_ksettings(struct net_device *netdev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_ksettings_get(txgbe->phylink, cmd);
+}
+
+static int txgbe_set_link_ksettings(struct net_device *netdev,
+ const struct ethtool_link_ksettings *cmd)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(netdev);
+
+ return phylink_ethtool_ksettings_set(txgbe->phylink, cmd);
+}
+
static const struct ethtool_ops txgbe_ethtool_ops = {
.get_drvinfo = wx_get_drvinfo,
+ .nway_reset = txgbe_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_link_ksettings = txgbe_get_link_ksettings,
+ .set_link_ksettings = txgbe_set_link_ksettings,
};
void txgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
index ebc46f3be056..0772eb14eabf 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
@@ -160,34 +160,24 @@ int txgbe_read_pba_string(struct wx *wx, u8 *pba_num, u32 pba_num_size)
static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum)
{
u16 *eeprom_ptrs = NULL;
- u32 buffer_size = 0;
- u16 *buffer = NULL;
u16 *local_buffer;
int status;
u16 i;
wx_init_eeprom_params(wx);
- if (!buffer) {
- eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16),
- GFP_KERNEL);
- if (!eeprom_ptrs)
- return -ENOMEM;
- /* Read pointer area */
- status = wx_read_ee_hostif_buffer(wx, 0,
- TXGBE_EEPROM_LAST_WORD,
- eeprom_ptrs);
- if (status != 0) {
- wx_err(wx, "Failed to read EEPROM image\n");
- kvfree(eeprom_ptrs);
- return status;
- }
- local_buffer = eeprom_ptrs;
- } else {
- if (buffer_size < TXGBE_EEPROM_LAST_WORD)
- return -EFAULT;
- local_buffer = buffer;
+ eeprom_ptrs = kvmalloc_array(TXGBE_EEPROM_LAST_WORD, sizeof(u16),
+ GFP_KERNEL);
+ if (!eeprom_ptrs)
+ return -ENOMEM;
+ /* Read pointer area */
+ status = wx_read_ee_hostif_buffer(wx, 0, TXGBE_EEPROM_LAST_WORD, eeprom_ptrs);
+ if (status != 0) {
+ wx_err(wx, "Failed to read EEPROM image\n");
+ kvfree(eeprom_ptrs);
+ return status;
}
+ local_buffer = eeprom_ptrs;
for (i = 0; i < TXGBE_EEPROM_LAST_WORD; i++)
if (i != wx->eeprom.sw_region_offset + TXGBE_EEPROM_CHECKSUM)
@@ -196,9 +186,6 @@ static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum)
if (eeprom_ptrs)
kvfree(eeprom_ptrs);
- if (*checksum > TXGBE_EEPROM_SUM)
- return -EINVAL;
-
*checksum = TXGBE_EEPROM_SUM - *checksum;
return 0;
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 5b8a121fb496..46eba6d6188b 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
+#include <linux/phylink.h>
#include <net/ip.h>
#include <linux/if_vlan.h>
@@ -15,6 +16,7 @@
#include "../libwx/wx_hw.h"
#include "txgbe_type.h"
#include "txgbe_hw.h"
+#include "txgbe_phy.h"
#include "txgbe_ethtool.h"
char txgbe_driver_name[] = "txgbe";
@@ -81,6 +83,8 @@ static int txgbe_enumerate_functions(struct wx *wx)
**/
static void txgbe_irq_enable(struct wx *wx, bool queues)
{
+ wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
+
/* unmask interrupt */
wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
if (queues)
@@ -128,17 +132,6 @@ static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t txgbe_msix_other(int __always_unused irq, void *data)
-{
- struct wx *wx = data;
-
- /* re-enable the original interrupt state */
- if (netif_running(wx->netdev))
- txgbe_irq_enable(wx, false);
-
- return IRQ_HANDLED;
-}
-
/**
* txgbe_request_msix_irqs - Initialize MSI-X interrupts
* @wx: board private structure
@@ -170,13 +163,6 @@ static int txgbe_request_msix_irqs(struct wx *wx)
}
}
- err = request_irq(wx->msix_entries[vector].vector,
- txgbe_msix_other, 0, netdev->name, wx);
- if (err) {
- wx_err(wx, "request_irq for msix_other failed: %d\n", err);
- goto free_queue_irqs;
- }
-
return 0;
free_queue_irqs:
@@ -219,7 +205,8 @@ static int txgbe_request_irq(struct wx *wx)
static void txgbe_up_complete(struct wx *wx)
{
- u32 reg;
+ struct net_device *netdev = wx->netdev;
+ struct txgbe *txgbe;
wx_control_hw(wx, true);
wx_configure_vectors(wx);
@@ -228,24 +215,17 @@ static void txgbe_up_complete(struct wx *wx)
smp_mb__before_atomic();
wx_napi_enable_all(wx);
+ txgbe = netdev_to_txgbe(netdev);
+ phylink_start(txgbe->phylink);
+
/* clear any pending interrupts, may auto mask */
rd32(wx, WX_PX_IC(0));
rd32(wx, WX_PX_IC(1));
rd32(wx, WX_PX_MISC_IC);
txgbe_irq_enable(wx, true);
- /* Configure MAC Rx and Tx when link is up */
- reg = rd32(wx, WX_MAC_RX_CFG);
- wr32(wx, WX_MAC_RX_CFG, reg);
- wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
- reg = rd32(wx, WX_MAC_WDG_TIMEOUT);
- wr32(wx, WX_MAC_WDG_TIMEOUT, reg);
- reg = rd32(wx, WX_MAC_TX_CFG);
- wr32(wx, WX_MAC_TX_CFG, (reg & ~WX_MAC_TX_CFG_SPEED_MASK) | WX_MAC_TX_CFG_SPEED_10G);
-
/* enable transmits */
- netif_tx_start_all_queues(wx->netdev);
- netif_carrier_on(wx->netdev);
+ netif_tx_start_all_queues(netdev);
}
static void txgbe_reset(struct wx *wx)
@@ -258,6 +238,7 @@ static void txgbe_reset(struct wx *wx)
if (err != 0)
wx_err(wx, "Hardware Error: %d\n", err);
+ wx_start_hw(wx);
/* do not flush user set addresses */
memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len);
wx_flush_sw_mac_table(wx);
@@ -279,7 +260,6 @@ static void txgbe_disable_device(struct wx *wx)
wx_disable_rx_queue(wx, wx->rx_ring[i]);
netif_tx_stop_all_queues(netdev);
- netif_carrier_off(netdev);
netif_tx_disable(netdev);
wx_irq_disable(wx);
@@ -310,8 +290,11 @@ static void txgbe_disable_device(struct wx *wx)
static void txgbe_down(struct wx *wx)
{
+ struct txgbe *txgbe = netdev_to_txgbe(wx->netdev);
+
txgbe_disable_device(wx);
txgbe_reset(wx);
+ phylink_stop(txgbe->phylink);
wx_clean_all_tx_rings(wx);
wx_clean_all_rx_rings(wx);
@@ -330,6 +313,7 @@ static int txgbe_sw_init(struct wx *wx)
wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES;
wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES;
wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE;
+ wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE;
wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE;
wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ;
@@ -455,7 +439,7 @@ static int txgbe_close(struct net_device *netdev)
return 0;
}
-static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
+static void txgbe_dev_shutdown(struct pci_dev *pdev)
{
struct wx *wx = pci_get_drvdata(pdev);
struct net_device *netdev;
@@ -475,12 +459,10 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
static void txgbe_shutdown(struct pci_dev *pdev)
{
- bool wake;
-
- txgbe_dev_shutdown(pdev, &wake);
+ txgbe_dev_shutdown(pdev);
if (system_state == SYSTEM_POWER_OFF) {
- pci_wake_from_d3(pdev, wake);
+ pci_wake_from_d3(pdev, false);
pci_set_power_state(pdev, PCI_D3hot);
}
}
@@ -491,9 +473,12 @@ static const struct net_device_ops txgbe_netdev_ops = {
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
.ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = wx_set_mac,
.ndo_get_stats64 = wx_get_stats64,
+ .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid,
};
/**
@@ -513,6 +498,7 @@ static int txgbe_probe(struct pci_dev *pdev,
struct net_device *netdev;
int err, expected_gts;
struct wx *wx = NULL;
+ struct txgbe *txgbe;
u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0;
u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0;
@@ -596,11 +582,25 @@ static int txgbe_probe(struct pci_dev *pdev,
goto err_free_mac_table;
}
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->features = NETIF_F_SG;
-
+ netdev->features = NETIF_F_SG |
+ NETIF_F_TSO |
+ NETIF_F_TSO6 |
+ NETIF_F_RXHASH |
+ NETIF_F_RXCSUM |
+ NETIF_F_HW_CSUM;
+
+ netdev->gso_partial_features = NETIF_F_GSO_ENCAP_ALL;
+ netdev->features |= netdev->gso_partial_features;
+ netdev->features |= NETIF_F_SCTP_CRC;
+ netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
+ netdev->hw_enc_features |= netdev->vlan_features;
+ netdev->features |= NETIF_F_VLAN_FEATURES;
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features | NETIF_F_RXALL;
+ netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC;
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->hw_features |= NETIF_F_GRO;
+ netdev->features |= NETIF_F_GRO;
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
@@ -663,10 +663,23 @@ static int txgbe_probe(struct pci_dev *pdev,
"0x%08x", etrack_id);
}
- err = register_netdev(netdev);
+ txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL);
+ if (!txgbe) {
+ err = -ENOMEM;
+ goto err_release_hw;
+ }
+
+ txgbe->wx = wx;
+ wx->priv = txgbe;
+
+ err = txgbe_init_phy(txgbe);
if (err)
goto err_release_hw;
+ err = register_netdev(netdev);
+ if (err)
+ goto err_remove_phy;
+
pci_set_drvdata(pdev, wx);
netif_tx_stop_all_queues(netdev);
@@ -694,6 +707,8 @@ static int txgbe_probe(struct pci_dev *pdev,
return 0;
+err_remove_phy:
+ txgbe_remove_phy(txgbe);
err_release_hw:
wx_clear_interrupt_scheme(wx);
wx_control_hw(wx, false);
@@ -719,11 +734,14 @@ err_pci_disable_dev:
static void txgbe_remove(struct pci_dev *pdev)
{
struct wx *wx = pci_get_drvdata(pdev);
+ struct txgbe *txgbe = wx->priv;
struct net_device *netdev;
netdev = wx->netdev;
unregister_netdev(netdev);
+ txgbe_remove_phy(txgbe);
+
pci_release_selected_regions(pdev,
pci_select_bars(pdev, IORESOURCE_MEM));
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
new file mode 100644
index 000000000000..8779645a54be
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/gpio/machine.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/property.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/pcs/pcs-xpcs.h>
+#include <linux/phylink.h>
+
+#include "../libwx/wx_type.h"
+#include "../libwx/wx_lib.h"
+#include "../libwx/wx_hw.h"
+#include "txgbe_type.h"
+#include "txgbe_phy.h"
+
+static int txgbe_swnodes_register(struct txgbe *txgbe)
+{
+ struct txgbe_nodes *nodes = &txgbe->nodes;
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct software_node *swnodes;
+ u32 id;
+
+ id = (pdev->bus->number << 8) | pdev->devfn;
+
+ snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id);
+ snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id);
+ snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id);
+ snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id);
+
+ swnodes = nodes->swnodes;
+
+ /* GPIO 0: tx fault
+ * GPIO 1: tx disable
+ * GPIO 2: sfp module absent
+ * GPIO 3: rx signal lost
+ * GPIO 4: rate select, 1G(0) 10G(1)
+ * GPIO 5: rate select, 1G(0) 10G(1)
+ */
+ nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default");
+ swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props);
+ nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH);
+ nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH);
+ nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW);
+ nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH);
+ nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH);
+ nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH);
+
+ nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c");
+ nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model");
+ nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ);
+ swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props);
+ nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]);
+
+ nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp");
+ nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref);
+ nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref);
+ nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref);
+ nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref);
+ nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref);
+ nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref);
+ nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref);
+ swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props);
+ nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]);
+
+ nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status");
+ nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref);
+ swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props);
+
+ nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO];
+ nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C];
+ nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP];
+ nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK];
+
+ return software_node_register_node_group(nodes->group);
+}
+
+static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum)
+{
+ struct wx *wx = bus->priv;
+ u32 offset, val;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ offset = devnum << 16 | regnum;
+
+ /* Set the LAN port indicator to IDA_ADDR */
+ wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+ /* Read the data from IDA_DATA register */
+ val = rd32(wx, TXGBE_XPCS_IDA_DATA);
+
+ return (u16)val;
+}
+
+static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val)
+{
+ struct wx *wx = bus->priv;
+ u32 offset;
+
+ if (addr)
+ return -EOPNOTSUPP;
+
+ offset = devnum << 16 | regnum;
+
+ /* Set the LAN port indicator to IDA_ADDR */
+ wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+ /* Write the data to IDA_DATA register */
+ wr32(wx, TXGBE_XPCS_IDA_DATA, val);
+
+ return 0;
+}
+
+static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
+{
+ struct mii_bus *mii_bus;
+ struct dw_xpcs *xpcs;
+ struct pci_dev *pdev;
+ struct wx *wx;
+ int ret = 0;
+
+ wx = txgbe->wx;
+ pdev = wx->pdev;
+
+ mii_bus = devm_mdiobus_alloc(&pdev->dev);
+ if (!mii_bus)
+ return -ENOMEM;
+
+ mii_bus->name = "txgbe_pcs_mdio_bus";
+ mii_bus->read_c45 = &txgbe_pcs_read;
+ mii_bus->write_c45 = &txgbe_pcs_write;
+ mii_bus->parent = &pdev->dev;
+ mii_bus->phy_mask = ~0;
+ mii_bus->priv = wx;
+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x",
+ (pdev->bus->number << 8) | pdev->devfn);
+
+ ret = devm_mdiobus_register(&pdev->dev, mii_bus);
+ if (ret)
+ return ret;
+
+ xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER);
+ if (IS_ERR(xpcs))
+ return PTR_ERR(xpcs);
+
+ txgbe->xpcs = xpcs;
+
+ return 0;
+}
+
+static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config,
+ phy_interface_t interface)
+{
+ struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev));
+
+ return &txgbe->xpcs->pcs;
+}
+
+static void txgbe_mac_config(struct phylink_config *config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+}
+
+static void txgbe_mac_link_down(struct phylink_config *config,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct wx *wx = netdev_priv(to_net_dev(config->dev));
+
+ wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0);
+}
+
+static void txgbe_mac_link_up(struct phylink_config *config,
+ struct phy_device *phy,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex,
+ bool tx_pause, bool rx_pause)
+{
+ struct wx *wx = netdev_priv(to_net_dev(config->dev));
+ u32 txcfg, wdg;
+
+ txcfg = rd32(wx, WX_MAC_TX_CFG);
+ txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK;
+
+ switch (speed) {
+ case SPEED_10000:
+ txcfg |= WX_MAC_TX_CFG_SPEED_10G;
+ break;
+ case SPEED_1000:
+ case SPEED_100:
+ case SPEED_10:
+ txcfg |= WX_MAC_TX_CFG_SPEED_1G;
+ break;
+ default:
+ break;
+ }
+
+ wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE);
+
+ /* Re configure MAC Rx */
+ wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE);
+ wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
+ wdg = rd32(wx, WX_MAC_WDG_TIMEOUT);
+ wr32(wx, WX_MAC_WDG_TIMEOUT, wdg);
+}
+
+static const struct phylink_mac_ops txgbe_mac_ops = {
+ .mac_select_pcs = txgbe_phylink_mac_select,
+ .mac_config = txgbe_mac_config,
+ .mac_link_down = txgbe_mac_link_down,
+ .mac_link_up = txgbe_mac_link_up,
+};
+
+static int txgbe_phylink_init(struct txgbe *txgbe)
+{
+ struct phylink_config *config;
+ struct fwnode_handle *fwnode;
+ struct wx *wx = txgbe->wx;
+ phy_interface_t phy_mode;
+ struct phylink *phylink;
+
+ config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ config->dev = &wx->netdev->dev;
+ config->type = PHYLINK_NETDEV;
+ config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
+ phy_mode = PHY_INTERFACE_MODE_10GBASER;
+ __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
+ fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]);
+ phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops);
+ if (IS_ERR(phylink))
+ return PTR_ERR(phylink);
+
+ txgbe->phylink = phylink;
+
+ return 0;
+}
+
+static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ int val;
+
+ val = rd32m(wx, WX_GPIO_EXT, BIT(offset));
+
+ return !!(val & BIT(offset));
+}
+
+static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ u32 val;
+
+ val = rd32(wx, WX_GPIO_DDR);
+ if (BIT(offset) & val)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_DDR, BIT(offset), 0);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset,
+ int val)
+{
+ struct wx *wx = gpiochip_get_data(chip);
+ unsigned long flags;
+ u32 set;
+
+ set = val ? BIT(offset) : 0;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_DR, BIT(offset), set);
+ wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static void txgbe_gpio_irq_ack(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32(wx, WX_GPIO_EOI, BIT(hwirq));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_gpio_irq_mask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ gpiochip_disable_irq(gc, hwirq);
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq));
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_gpio_irq_unmask(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ gpiochip_enable_irq(gc, hwirq);
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+}
+
+static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset)
+{
+ struct wx *wx = gpiochip_get_data(gc);
+ u32 pol, val;
+
+ pol = rd32(wx, WX_GPIO_POLARITY);
+ val = rd32(wx, WX_GPIO_EXT);
+
+ if (val & BIT(offset))
+ pol &= ~BIT(offset);
+ else
+ pol |= BIT(offset);
+
+ wr32(wx, WX_GPIO_POLARITY, pol);
+}
+
+static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ struct wx *wx = gpiochip_get_data(gc);
+ u32 level, polarity, mask;
+ unsigned long flags;
+
+ mask = BIT(hwirq);
+
+ if (type & IRQ_TYPE_LEVEL_MASK) {
+ level = 0;
+ irq_set_handler_locked(d, handle_level_irq);
+ } else {
+ level = mask;
+ irq_set_handler_locked(d, handle_edge_irq);
+ }
+
+ if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH)
+ polarity = mask;
+ else
+ polarity = 0;
+
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+
+ wr32m(wx, WX_GPIO_INTEN, mask, mask);
+ wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level);
+ if (type == IRQ_TYPE_EDGE_BOTH)
+ txgbe_toggle_trigger(gc, hwirq);
+ else
+ wr32m(wx, WX_GPIO_POLARITY, mask, polarity);
+
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+
+ return 0;
+}
+
+static const struct irq_chip txgbe_gpio_irq_chip = {
+ .name = "txgbe_gpio_irq",
+ .irq_ack = txgbe_gpio_irq_ack,
+ .irq_mask = txgbe_gpio_irq_mask,
+ .irq_unmask = txgbe_gpio_irq_unmask,
+ .irq_set_type = txgbe_gpio_set_type,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void txgbe_irq_handler(struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct wx *wx = irq_desc_get_handler_data(desc);
+ struct txgbe *txgbe = wx->priv;
+ irq_hw_number_t hwirq;
+ unsigned long gpioirq;
+ struct gpio_chip *gc;
+ unsigned long flags;
+ u32 eicr;
+
+ eicr = wx_misc_isb(wx, WX_ISB_MISC);
+
+ chained_irq_enter(chip, desc);
+
+ gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
+
+ gc = txgbe->gpio;
+ for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
+ int gpio = irq_find_mapping(gc->irq.domain, hwirq);
+ u32 irq_type = irq_get_trigger_type(gpio);
+
+ generic_handle_domain_irq(gc->irq.domain, hwirq);
+
+ if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+ txgbe_toggle_trigger(gc, hwirq);
+ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+
+ if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) {
+ u32 reg = rd32(wx, TXGBE_CFG_PORT_ST);
+
+ phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));
+ }
+
+ /* unmask interrupt */
+ wx_intr_enable(wx, TXGBE_INTR_MISC(wx));
+}
+
+static int txgbe_gpio_init(struct txgbe *txgbe)
+{
+ struct gpio_irq_chip *girq;
+ struct gpio_chip *gc;
+ struct device *dev;
+ struct wx *wx;
+ int ret;
+
+ wx = txgbe->wx;
+ dev = &wx->pdev->dev;
+
+ raw_spin_lock_init(&wx->gpio_lock);
+
+ gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
+ if (!gc)
+ return -ENOMEM;
+
+ gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x",
+ (wx->pdev->bus->number << 8) | wx->pdev->devfn);
+ if (!gc->label)
+ return -ENOMEM;
+
+ gc->base = -1;
+ gc->ngpio = 6;
+ gc->owner = THIS_MODULE;
+ gc->parent = dev;
+ gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]);
+ gc->get = txgbe_gpio_get;
+ gc->get_direction = txgbe_gpio_get_direction;
+ gc->direction_input = txgbe_gpio_direction_in;
+ gc->direction_output = txgbe_gpio_direction_out;
+
+ girq = &gc->irq;
+ gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip);
+ girq->parent_handler = txgbe_irq_handler;
+ girq->parent_handler_data = wx;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(dev, girq->num_parents,
+ sizeof(*girq->parents), GFP_KERNEL);
+ if (!girq->parents)
+ return -ENOMEM;
+ girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+ ret = devm_gpiochip_add_data(dev, gc, wx);
+ if (ret)
+ return ret;
+
+ txgbe->gpio = gc;
+
+ return 0;
+}
+
+static int txgbe_clock_register(struct txgbe *txgbe)
+{
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct clk_lookup *clock;
+ char clk_name[32];
+ struct clk *clk;
+
+ snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
+ (pdev->bus->number << 8) | pdev->devfn);
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clock = clkdev_create(clk, NULL, clk_name);
+ if (!clock) {
+ clk_unregister(clk);
+ return -ENOMEM;
+ }
+
+ txgbe->clk = clk;
+ txgbe->clock = clock;
+
+ return 0;
+}
+
+static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct wx *wx = context;
+
+ *val = rd32(wx, reg + TXGBE_I2C_BASE);
+
+ return 0;
+}
+
+static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct wx *wx = context;
+
+ wr32(wx, reg + TXGBE_I2C_BASE, val);
+
+ return 0;
+}
+
+static const struct regmap_config i2c_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_read = txgbe_i2c_read,
+ .reg_write = txgbe_i2c_write,
+ .fast_io = true,
+};
+
+static int txgbe_i2c_register(struct txgbe *txgbe)
+{
+ struct platform_device_info info = {};
+ struct platform_device *i2c_dev;
+ struct regmap *i2c_regmap;
+ struct pci_dev *pdev;
+ struct wx *wx;
+
+ wx = txgbe->wx;
+ pdev = wx->pdev;
+ i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config);
+ if (IS_ERR(i2c_regmap)) {
+ wx_err(wx, "failed to init I2C regmap\n");
+ return PTR_ERR(i2c_regmap);
+ }
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
+ info.name = "i2c_designware";
+ info.id = (pdev->bus->number << 8) | pdev->devfn;
+
+ info.res = &DEFINE_RES_IRQ(pdev->irq);
+ info.num_res = 1;
+ i2c_dev = platform_device_register_full(&info);
+ if (IS_ERR(i2c_dev))
+ return PTR_ERR(i2c_dev);
+
+ txgbe->i2c_dev = i2c_dev;
+
+ return 0;
+}
+
+static int txgbe_sfp_register(struct txgbe *txgbe)
+{
+ struct pci_dev *pdev = txgbe->wx->pdev;
+ struct platform_device_info info = {};
+ struct platform_device *sfp_dev;
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]);
+ info.name = "sfp";
+ info.id = (pdev->bus->number << 8) | pdev->devfn;
+ sfp_dev = platform_device_register_full(&info);
+ if (IS_ERR(sfp_dev))
+ return PTR_ERR(sfp_dev);
+
+ txgbe->sfp_dev = sfp_dev;
+
+ return 0;
+}
+
+int txgbe_init_phy(struct txgbe *txgbe)
+{
+ int ret;
+
+ ret = txgbe_swnodes_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register software nodes\n");
+ return ret;
+ }
+
+ ret = txgbe_mdio_pcs_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret);
+ goto err_unregister_swnode;
+ }
+
+ ret = txgbe_phylink_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init phylink\n");
+ goto err_destroy_xpcs;
+ }
+
+ ret = txgbe_gpio_init(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init gpio\n");
+ goto err_destroy_phylink;
+ }
+
+ ret = txgbe_clock_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register clock: %d\n", ret);
+ goto err_destroy_phylink;
+ }
+
+ ret = txgbe_i2c_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret);
+ goto err_unregister_clk;
+ }
+
+ ret = txgbe_sfp_register(txgbe);
+ if (ret) {
+ wx_err(txgbe->wx, "failed to register sfp\n");
+ goto err_unregister_i2c;
+ }
+
+ return 0;
+
+err_unregister_i2c:
+ platform_device_unregister(txgbe->i2c_dev);
+err_unregister_clk:
+ clkdev_drop(txgbe->clock);
+ clk_unregister(txgbe->clk);
+err_destroy_phylink:
+ phylink_destroy(txgbe->phylink);
+err_destroy_xpcs:
+ xpcs_destroy(txgbe->xpcs);
+err_unregister_swnode:
+ software_node_unregister_node_group(txgbe->nodes.group);
+
+ return ret;
+}
+
+void txgbe_remove_phy(struct txgbe *txgbe)
+{
+ platform_device_unregister(txgbe->sfp_dev);
+ platform_device_unregister(txgbe->i2c_dev);
+ clkdev_drop(txgbe->clock);
+ clk_unregister(txgbe->clk);
+ phylink_destroy(txgbe->phylink);
+ xpcs_destroy(txgbe->xpcs);
+ software_node_unregister_node_group(txgbe->nodes.group);
+}
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
new file mode 100644
index 000000000000..1ab592124986
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
+
+#ifndef _TXGBE_PHY_H_
+#define _TXGBE_PHY_H_
+
+int txgbe_init_phy(struct txgbe *txgbe);
+void txgbe_remove_phy(struct txgbe *txgbe);
+
+#endif /* _TXGBE_NODE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 63a1c733718d..51199c355f95 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -4,6 +4,8 @@
#ifndef _TXGBE_TYPE_H_
#define _TXGBE_TYPE_H_
+#include <linux/property.h>
+
/* Device IDs */
#define TXGBE_DEV_ID_SP1000 0x1001
#define TXGBE_DEV_ID_WX1820 0x2001
@@ -53,6 +55,39 @@
#define TXGBE_TS_CTL 0x10300
#define TXGBE_TS_CTL_EVAL_MD BIT(31)
+/* GPIO register bit */
+#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */
+#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */
+#define TXGBE_GPIOBIT_2 BIT(2) /* I:sfp module absent */
+#define TXGBE_GPIOBIT_3 BIT(3) /* I:rx signal lost */
+#define TXGBE_GPIOBIT_4 BIT(4) /* O:rate select, 1G(0) 10G(1) */
+#define TXGBE_GPIOBIT_5 BIT(5) /* O:rate select, 1G(0) 10G(1) */
+
+/* Extended Interrupt Enable Set */
+#define TXGBE_PX_MISC_ETH_LKDN BIT(8)
+#define TXGBE_PX_MISC_DEV_RST BIT(10)
+#define TXGBE_PX_MISC_ETH_EVENT BIT(17)
+#define TXGBE_PX_MISC_ETH_LK BIT(18)
+#define TXGBE_PX_MISC_ETH_AN BIT(19)
+#define TXGBE_PX_MISC_INT_ERR BIT(20)
+#define TXGBE_PX_MISC_GPIO BIT(26)
+#define TXGBE_PX_MISC_IEN_MASK \
+ (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \
+ TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \
+ TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \
+ TXGBE_PX_MISC_GPIO)
+
+/* Port cfg registers */
+#define TXGBE_CFG_PORT_ST 0x14404
+#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0)
+
+/* I2C registers */
+#define TXGBE_I2C_BASE 0x14900
+
+/************************************** ETH PHY ******************************/
+#define TXGBE_XPCS_IDA_ADDR 0x13000
+#define TXGBE_XPCS_IDA_DATA 0x13004
+
/* Part Number String Length */
#define TXGBE_PBANUM_LENGTH 32
@@ -77,6 +112,7 @@
#define TXGBE_SP_MAX_RX_QUEUES 128
#define TXGBE_SP_RAR_ENTRIES 128
#define TXGBE_SP_MC_TBL_SIZE 128
+#define TXGBE_SP_VFT_TBL_SIZE 128
#define TXGBE_SP_RX_PB_SIZE 512
#define TXGBE_SP_TDB_PB_SZ (160 * 1024) /* 160KB Packet Buffer */
@@ -99,4 +135,58 @@
extern char txgbe_driver_name[];
+static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ return wx->priv;
+}
+
+#define NODE_PROP(_NAME, _PROP) \
+ (const struct software_node) { \
+ .name = _NAME, \
+ .properties = _PROP, \
+ }
+
+enum txgbe_swnodes {
+ SWNODE_GPIO = 0,
+ SWNODE_I2C,
+ SWNODE_SFP,
+ SWNODE_PHYLINK,
+ SWNODE_MAX
+};
+
+struct txgbe_nodes {
+ char gpio_name[32];
+ char i2c_name[32];
+ char sfp_name[32];
+ char phylink_name[32];
+ struct property_entry gpio_props[1];
+ struct property_entry i2c_props[3];
+ struct property_entry sfp_props[8];
+ struct property_entry phylink_props[2];
+ struct software_node_ref_args i2c_ref[1];
+ struct software_node_ref_args gpio0_ref[1];
+ struct software_node_ref_args gpio1_ref[1];
+ struct software_node_ref_args gpio2_ref[1];
+ struct software_node_ref_args gpio3_ref[1];
+ struct software_node_ref_args gpio4_ref[1];
+ struct software_node_ref_args gpio5_ref[1];
+ struct software_node_ref_args sfp_ref[1];
+ struct software_node swnodes[SWNODE_MAX];
+ const struct software_node *group[SWNODE_MAX + 1];
+};
+
+struct txgbe {
+ struct wx *wx;
+ struct txgbe_nodes nodes;
+ struct dw_xpcs *xpcs;
+ struct phylink *phylink;
+ struct platform_device *sfp_dev;
+ struct platform_device *i2c_dev;
+ struct clk_lookup *clock;
+ struct clk *clk;
+ struct gpio_chip *gpio;
+};
+
#endif /* _TXGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index e0ac1bcd9925..49f303353ecb 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1567,12 +1567,16 @@ static int temac_probe(struct platform_device *pdev)
}
/* Error handle returned DMA RX and TX interrupts */
- if (lp->rx_irq < 0)
- return dev_err_probe(&pdev->dev, lp->rx_irq,
+ if (lp->rx_irq <= 0) {
+ rc = lp->rx_irq ?: -EINVAL;
+ return dev_err_probe(&pdev->dev, rc,
"could not get DMA RX irq\n");
- if (lp->tx_irq < 0)
- return dev_err_probe(&pdev->dev, lp->tx_irq,
+ }
+ if (lp->tx_irq <= 0) {
+ rc = lp->tx_irq ?: -EINVAL;
+ return dev_err_probe(&pdev->dev, rc,
"could not get DMA TX irq\n");
+ }
if (temac_np) {
/* Retrieve the MAC address */
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 3e310b55bce2..8e32dc50a408 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1631,7 +1631,7 @@ static void axienet_pcs_an_restart(struct phylink_pcs *pcs)
phylink_mii_c22_pcs_an_restart(pcs_phy);
}
-static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
@@ -1653,7 +1653,8 @@ static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
}
}
- ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising);
+ ret = phylink_mii_c22_pcs_config(pcs_phy, interface, advertising,
+ neg_mode);
if (ret < 0)
netdev_warn(ndev, "Failed to configure PCS: %d\n", ret);
@@ -2042,6 +2043,11 @@ static int axienet_probe(struct platform_device *pdev)
goto cleanup_clk;
}
+ /* Reset core now that clocks are enabled, prior to accessing MDIO */
+ ret = __axienet_device_reset(lp);
+ if (ret)
+ goto cleanup_clk;
+
/* Autodetect the need for 64-bit DMA pointers.
* When the IP is configured for a bus width bigger than 32 bits,
* writing the MSB registers is mandatory, even if they are all 0.
@@ -2096,11 +2102,6 @@ static int axienet_probe(struct platform_device *pdev)
lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC;
- /* Reset core now that clocks are enabled, prior to accessing MDIO */
- ret = __axienet_device_reset(lp);
- if (ret)
- goto cleanup_clk;
-
ret = axienet_mdio_setup(lp);
if (ret)
dev_warn(&pdev->dev,
@@ -2129,6 +2130,7 @@ static int axienet_probe(struct platform_device *pdev)
}
of_node_put(np);
lp->pcs.ops = &axienet_pcs_ops;
+ lp->pcs.neg_mode = true;
lp->pcs.poll = true;
}
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 15c7dc82107f..acb20ad4e37e 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -631,7 +631,9 @@ static void __gtp_encap_destroy(struct sock *sk)
gtp->sk1u = NULL;
udp_sk(sk)->encap_type = 0;
rcu_assign_sk_user_data(sk, NULL);
+ release_sock(sk);
sock_put(sk);
+ return;
}
release_sock(sk);
}
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 33d51e363913..c9dd69dbe1b8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -74,6 +74,7 @@ struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */
#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40
#define ITAB_NUM 128
+#define ITAB_NUM_MAX 256
struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
struct ndis_obj_header hdr;
@@ -1034,7 +1035,9 @@ struct net_device_context {
u32 tx_table[VRSS_SEND_TAB_SIZE];
- u16 rx_table[ITAB_NUM];
+ u16 *rx_table;
+
+ u32 rx_table_sz;
/* Ethtool settings */
u8 duplex;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 0103ff914024..3ba3c8fb28a5 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1747,7 +1747,9 @@ static u32 netvsc_get_rxfh_key_size(struct net_device *dev)
static u32 netvsc_rss_indir_size(struct net_device *dev)
{
- return ITAB_NUM;
+ struct net_device_context *ndc = netdev_priv(dev);
+
+ return ndc->rx_table_sz;
}
static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
@@ -1766,7 +1768,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
rndis_dev = ndev->extension;
if (indir) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
indir[i] = ndc->rx_table[i];
}
@@ -1792,11 +1794,11 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
rndis_dev = ndev->extension;
if (indir) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
if (indir[i] >= ndev->num_chn)
return -EINVAL;
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
ndc->rx_table[i] = indir[i];
}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index eea777ec2541..af95947a87c5 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -21,6 +21,7 @@
#include <linux/rtnetlink.h>
#include <linux/ucs2_string.h>
#include <linux/string.h>
+#include <linux/slab.h>
#include "hyperv_net.h"
#include "netvsc_trace.h"
@@ -927,7 +928,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
struct rndis_set_request *set;
struct rndis_set_complete *set_complete;
u32 extlen = sizeof(struct ndis_recv_scale_param) +
- 4 * ITAB_NUM + NETVSC_HASH_KEYLEN;
+ 4 * ndc->rx_table_sz + NETVSC_HASH_KEYLEN;
struct ndis_recv_scale_param *rssp;
u32 *itab;
u8 *keyp;
@@ -953,7 +954,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
NDIS_HASH_TCP_IPV6;
- rssp->indirect_tabsize = 4*ITAB_NUM;
+ rssp->indirect_tabsize = 4 * ndc->rx_table_sz;
rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
rssp->hashkey_size = NETVSC_HASH_KEYLEN;
rssp->hashkey_offset = rssp->indirect_taboffset +
@@ -961,7 +962,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
/* Set indirection table entries */
itab = (u32 *)(rssp + 1);
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
itab[i] = ndc->rx_table[i];
/* Set hask key values */
@@ -1548,6 +1549,18 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
if (ret || rsscap.num_recv_que < 2)
goto out;
+ if (rsscap.num_indirect_tabent &&
+ rsscap.num_indirect_tabent <= ITAB_NUM_MAX)
+ ndc->rx_table_sz = rsscap.num_indirect_tabent;
+ else
+ ndc->rx_table_sz = ITAB_NUM;
+
+ ndc->rx_table = kcalloc(ndc->rx_table_sz, sizeof(u16), GFP_KERNEL);
+ if (!ndc->rx_table) {
+ ret = -ENOMEM;
+ goto err_dev_remv;
+ }
+
/* This guarantees that num_possible_rss_qs <= num_online_cpus */
num_possible_rss_qs = min_t(u32, num_online_cpus(),
rsscap.num_recv_que);
@@ -1558,7 +1571,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
if (!netif_is_rxfh_configured(net)) {
- for (i = 0; i < ITAB_NUM; i++)
+ for (i = 0; i < ndc->rx_table_sz; i++)
ndc->rx_table[i] = ethtool_rxfh_indir_default(
i, net_device->num_chn);
}
@@ -1596,11 +1609,19 @@ void rndis_filter_device_remove(struct hv_device *dev,
struct netvsc_device *net_dev)
{
struct rndis_device *rndis_dev = net_dev->extension;
+ struct net_device *net = hv_get_drvdata(dev);
+ struct net_device_context *ndc;
+
+ ndc = netdev_priv(net);
/* Halt and release the rndis device */
rndis_filter_halt_device(net_dev, rndis_dev);
netvsc_device_remove(dev);
+
+ ndc->rx_table_sz = 0;
+ kfree(ndc->rx_table);
+ ndc->rx_table = NULL;
}
int rndis_filter_open(struct netvsc_device *nvdev)
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index 0134ebac227a..f9b10e84de06 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -2855,7 +2855,6 @@ static int ca8210_interrupt_init(struct spi_device *spi)
);
if (ret) {
dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
- gpiod_unexport(gpio_to_desc(pdata->gpio_irq));
gpio_free(pdata->gpio_irq);
}
@@ -2945,7 +2944,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
ca8210_hw->phy->flags =
WPAN_PHY_FLAG_TXPOWER |
WPAN_PHY_FLAG_CCA_ED_LEVEL |
- WPAN_PHY_FLAG_CCA_MODE;
+ WPAN_PHY_FLAG_CCA_MODE |
+ WPAN_PHY_FLAG_DATAGRAMS_ONLY;
}
/**
diff --git a/drivers/net/ipa/ipa_table.c b/drivers/net/ipa/ipa_table.c
index f0529c31d0b6..7b637bb8b41c 100644
--- a/drivers/net/ipa/ipa_table.c
+++ b/drivers/net/ipa/ipa_table.c
@@ -273,16 +273,15 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
if (ret)
return ret;
- ret = ipa_filter_reset_table(ipa, true, false, modem);
- if (ret)
+ ret = ipa_filter_reset_table(ipa, false, true, modem);
+ if (ret || !ipa_table_hash_support(ipa))
return ret;
- ret = ipa_filter_reset_table(ipa, false, true, modem);
+ ret = ipa_filter_reset_table(ipa, true, false, modem);
if (ret)
return ret;
- ret = ipa_filter_reset_table(ipa, true, true, modem);
- return ret;
+ return ipa_filter_reset_table(ipa, true, true, modem);
}
/* The AP routes and modem routes are each contiguous within the
@@ -291,12 +290,13 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
* */
static int ipa_route_reset(struct ipa *ipa, bool modem)
{
+ bool hash_support = ipa_table_hash_support(ipa);
u32 modem_route_count = ipa->modem_route_count;
struct gsi_trans *trans;
u16 first;
u16 count;
- trans = ipa_cmd_trans_alloc(ipa, 4);
+ trans = ipa_cmd_trans_alloc(ipa, hash_support ? 4 : 2);
if (!trans) {
dev_err(&ipa->pdev->dev,
"no transaction for %s route reset\n",
@@ -313,10 +313,12 @@ static int ipa_route_reset(struct ipa *ipa, bool modem)
}
ipa_table_reset_add(trans, false, false, false, first, count);
- ipa_table_reset_add(trans, false, true, false, first, count);
-
ipa_table_reset_add(trans, false, false, true, first, count);
- ipa_table_reset_add(trans, false, true, true, first, count);
+
+ if (hash_support) {
+ ipa_table_reset_add(trans, false, true, false, first, count);
+ ipa_table_reset_add(trans, false, true, true, first, count);
+ }
gsi_trans_commit_wait(trans);
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index ab5133eb1d51..c0c49f181367 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -555,8 +555,7 @@ static void ipvlan_multicast_enqueue(struct ipvl_port *port,
spin_lock(&port->backlog.lock);
if (skb_queue_len(&port->backlog) < IPVLAN_QBACKLOG_LIMIT) {
- if (skb->dev)
- dev_hold(skb->dev);
+ dev_hold(skb->dev);
__skb_queue_tail(&port->backlog, skb);
spin_unlock(&port->backlog.lock);
schedule_work(&port->wq);
@@ -585,7 +584,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
consume_skb(skb);
return NET_XMIT_DROP;
}
- return ipvlan_rcv_frame(addr, &skb, true);
+ ipvlan_rcv_frame(addr, &skb, true);
+ return NET_XMIT_SUCCESS;
}
}
out:
@@ -611,7 +611,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
consume_skb(skb);
return NET_XMIT_DROP;
}
- return ipvlan_rcv_frame(addr, &skb, true);
+ ipvlan_rcv_frame(addr, &skb, true);
+ return NET_XMIT_SUCCESS;
}
}
skb = skb_share_check(skb, GFP_ATOMIC);
@@ -623,7 +624,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
* the skb for the main-dev. At the RX side we just return
* RX_PASS for it to be processed further on the stack.
*/
- return dev_forward_skb(ipvlan->phy_dev, skb);
+ dev_forward_skb(ipvlan->phy_dev, skb);
+ return NET_XMIT_SUCCESS;
} else if (is_multicast_ether_addr(eth->h_dest)) {
skb_reset_mac_header(skb);
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index b15dd9a3ad54..1b55928e89b8 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -748,7 +748,8 @@ static int ipvlan_device_event(struct notifier_block *unused,
write_pnet(&port->pnet, newnet);
- ipvlan_migrate_l3s_hook(oldnet, newnet);
+ if (port->mode == IPVLAN_MODE_L3S)
+ ipvlan_migrate_l3s_hook(oldnet, newnet);
break;
}
case NETDEV_UNREGISTER:
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 984dfa5d6c11..2d64650f4eb3 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -743,7 +743,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsLate++;
u64_stats_update_end(&rxsc_stats->syncp);
- secy->netdev->stats.rx_dropped++;
+ DEV_STATS_INC(secy->netdev, rx_dropped);
return false;
}
@@ -767,7 +767,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
rxsc_stats->stats.InPktsNotValid++;
u64_stats_update_end(&rxsc_stats->syncp);
this_cpu_inc(rx_sa->stats->InPktsNotValid);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
return false;
}
@@ -1069,7 +1069,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoTag++;
u64_stats_update_end(&secy_stats->syncp);
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
continue;
}
@@ -1179,7 +1179,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsBadTag++;
u64_stats_update_end(&secy_stats->syncp);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
goto drop_nosa;
}
@@ -1196,7 +1196,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsNotUsingSA++;
u64_stats_update_end(&rxsc_stats->syncp);
- secy->netdev->stats.rx_errors++;
+ DEV_STATS_INC(secy->netdev, rx_errors);
if (active_rx_sa)
this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
goto drop_nosa;
@@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
u64_stats_update_begin(&rxsc_stats->syncp);
rxsc_stats->stats.InPktsLate++;
u64_stats_update_end(&rxsc_stats->syncp);
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
goto drop;
}
}
@@ -1271,7 +1271,7 @@ deliver:
if (ret == NET_RX_SUCCESS)
count_rx(dev, len);
else
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
rcu_read_unlock();
@@ -1308,7 +1308,7 @@ nosci:
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoSCI++;
u64_stats_update_end(&secy_stats->syncp);
- macsec->secy.netdev->stats.rx_errors++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_errors);
continue;
}
@@ -1327,7 +1327,7 @@ nosci:
secy_stats->stats.InPktsUnknownSCI++;
u64_stats_update_end(&secy_stats->syncp);
} else {
- macsec->secy.netdev->stats.rx_dropped++;
+ DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
}
}
@@ -1341,8 +1341,7 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len)
struct crypto_aead *tfm;
int ret;
- /* Pick a sync gcm(aes) cipher to ensure order is preserved. */
- tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
if (IS_ERR(tfm))
return tfm;
@@ -3422,7 +3421,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
if (!secy->operational) {
kfree_skb(skb);
- dev->stats.tx_dropped++;
+ DEV_STATS_INC(dev, tx_dropped);
return NETDEV_TX_OK;
}
@@ -3430,7 +3429,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
skb = macsec_encrypt(skb, dev);
if (IS_ERR(skb)) {
if (PTR_ERR(skb) != -EINPROGRESS)
- dev->stats.tx_dropped++;
+ DEV_STATS_INC(dev, tx_dropped);
return NETDEV_TX_OK;
}
@@ -3667,9 +3666,9 @@ static void macsec_get_stats64(struct net_device *dev,
dev_fetch_sw_netstats(s, dev->tstats);
- s->rx_dropped = dev->stats.rx_dropped;
- s->tx_dropped = dev->stats.tx_dropped;
- s->rx_errors = dev->stats.rx_errors;
+ s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped);
+ s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped);
+ s->rx_errors = atomic_long_read(&dev->stats.__rx_errors);
}
static int macsec_get_iflink(const struct net_device *dev)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 6936823e0bcd..52cd06d60d14 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1746,6 +1746,7 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
+ [IFLA_MACVLAN_BC_CUTOFF] = { .type = NLA_S32 },
};
int macvlan_link_register(struct rtnl_link_ops *ops)
diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c
index 1d67a3ca1fd1..b37a9e4bade4 100644
--- a/drivers/net/mctp/mctp-i2c.c
+++ b/drivers/net/mctp/mctp-i2c.c
@@ -1058,7 +1058,7 @@ static struct i2c_driver mctp_i2c_driver = {
.name = "mctp-i2c-interface",
.of_match_table = mctp_i2c_of_match,
},
- .probe_new = mctp_i2c_probe,
+ .probe = mctp_i2c_probe,
.remove = mctp_i2c_remove,
.id_table = mctp_i2c_id,
};
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 9ff2e6f22f3f..4a7a303be2f7 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -185,6 +185,17 @@ config MDIO_IPQ8064
This driver supports the MDIO interface found in the network
interface units of the IPQ8064 SoC
+config MDIO_REGMAP
+ tristate
+ help
+ This driver allows using MDIO devices that are not sitting on a
+ regular MDIO bus, but still exposes the standard 802.3 register
+ layout. It's regmap-based so that it can be used on integrated,
+ memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is
+ created, and its read/write operations are mapped to the underlying
+ regmap. Users willing to use this driver must explicitly select
+ REGMAP.
+
config MDIO_THUNDER
tristate "ThunderX SOCs MDIO buses"
depends on 64BIT
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 7d4cb4c11e4e..1015f0db4531 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
+obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
diff --git a/drivers/net/mdio/mdio-bitbang.c b/drivers/net/mdio/mdio-bitbang.c
index b83932562be2..81b7748c10ce 100644
--- a/drivers/net/mdio/mdio-bitbang.c
+++ b/drivers/net/mdio/mdio-bitbang.c
@@ -186,7 +186,7 @@ int mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg)
struct mdiobb_ctrl *ctrl = bus->priv;
mdiobb_cmd_addr(ctrl, phy, devad, reg);
- mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_READ, phy, devad);
return mdiobb_read_common(bus, phy);
}
@@ -222,7 +222,7 @@ int mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, int reg, u16 val)
struct mdiobb_ctrl *ctrl = bus->priv;
mdiobb_cmd_addr(ctrl, phy, devad, reg);
- mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
+ mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, devad);
return mdiobb_write_common(bus, val);
}
diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c
index c02c9c660016..09af150ed774 100644
--- a/drivers/net/mdio/mdio-mux-mmioreg.c
+++ b/drivers/net/mdio/mdio-mux-mmioreg.c
@@ -140,14 +140,15 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
* set any bits outside of the 'mask'.
*/
for_each_available_child_of_node(np, np2) {
- iprop = of_get_property(np2, "reg", &len);
- if (!iprop || len != sizeof(uint32_t)) {
+ u64 reg;
+
+ if (of_property_read_reg(np2, 0, &reg, NULL)) {
dev_err(&pdev->dev, "mdio-mux child node %pOF is "
"missing a 'reg' property\n", np2);
of_node_put(np2);
return -ENODEV;
}
- if (be32_to_cpup(iprop) & ~s->mask) {
+ if ((u32)reg & ~s->mask) {
dev_err(&pdev->dev, "mdio-mux child node %pOF has "
"a 'reg' value with unmasked bits\n",
np2);
diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
new file mode 100644
index 000000000000..8a742a8d6387
--- /dev/null
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Driver for MMIO-Mapped MDIO devices. Some IPs expose internal PHYs or PCS
+ * within the MMIO-mapped area
+ *
+ * Copyright (C) 2023 Maxime Chevallier <maxime.chevallier@bootlin.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mdio/mdio-regmap.h>
+
+#define DRV_NAME "mdio-regmap"
+
+struct mdio_regmap_priv {
+ struct regmap *regmap;
+ u8 valid_addr;
+};
+
+static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
+{
+ struct mdio_regmap_priv *ctx = bus->priv;
+ unsigned int val;
+ int ret;
+
+ if (ctx->valid_addr != addr)
+ return -ENODEV;
+
+ ret = regmap_read(ctx->regmap, regnum, &val);
+ if (ret < 0)
+ return ret;
+
+ return val;
+}
+
+static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct mdio_regmap_priv *ctx = bus->priv;
+
+ if (ctx->valid_addr != addr)
+ return -ENODEV;
+
+ return regmap_write(ctx->regmap, regnum, val);
+}
+
+struct mii_bus *devm_mdio_regmap_register(struct device *dev,
+ const struct mdio_regmap_config *config)
+{
+ struct mdio_regmap_priv *mr;
+ struct mii_bus *mii;
+ int rc;
+
+ if (!config->parent)
+ return ERR_PTR(-EINVAL);
+
+ mii = devm_mdiobus_alloc_size(config->parent, sizeof(*mr));
+ if (!mii)
+ return ERR_PTR(-ENOMEM);
+
+ mr = mii->priv;
+ mr->regmap = config->regmap;
+ mr->valid_addr = config->valid_addr;
+
+ mii->name = DRV_NAME;
+ strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
+ mii->parent = config->parent;
+ mii->read = mdio_regmap_read_c22;
+ mii->write = mdio_regmap_write_c22;
+
+ if (config->autoscan)
+ mii->phy_mask = ~BIT(config->valid_addr);
+ else
+ mii->phy_mask = ~0;
+
+ rc = devm_mdiobus_register(dev, mii);
+ if (rc) {
+ dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc);
+ return ERR_PTR(rc);
+ }
+
+ return mii;
+}
+EXPORT_SYMBOL_GPL(devm_mdio_regmap_register);
+
+MODULE_DESCRIPTION("MDIO API over regmap");
+MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index 6045bece2654..b4d3b9cde8bd 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -184,13 +184,10 @@ static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file,
cookie_len = (count - 1) / 2;
if ((count - 1) % 2)
return -EINVAL;
- buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
- if (!buf)
- return -ENOMEM;
- ret = simple_write_to_buffer(buf, count, ppos, data, count);
- if (ret < 0)
- goto free_buf;
+ buf = memdup_user(data, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len,
GFP_KERNEL | __GFP_NOWARN);
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 85dbe7f73e31..536bd6564f8b 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -493,7 +493,7 @@ static int __init ntb_netdev_init_module(void)
return 0;
}
-module_init(ntb_netdev_init_module);
+late_initcall(ntb_netdev_init_module);
static void __exit ntb_netdev_exit_module(void)
{
diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig
index 7c34fb7cbf7b..87cf308fc6d8 100644
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -33,10 +33,4 @@ config PCS_RZN1_MIIC
on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in
pass-through mode for MII.
-config PCS_ALTERA_TSE
- tristate
- help
- This module provides helper functions for the Altera Triple Speed
- Ethernet SGMII PCS, that can be found on the Intel Socfpga family.
-
endmenu
diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile
index 9b9afd6b1c22..ea662a7989b2 100644
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -7,4 +7,3 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
-obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o
diff --git a/drivers/net/pcs/pcs-altera-tse.c b/drivers/net/pcs/pcs-altera-tse.c
deleted file mode 100644
index d616749761f4..000000000000
--- a/drivers/net/pcs/pcs-altera-tse.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2022 Bootlin
- *
- * Maxime Chevallier <maxime.chevallier@bootlin.com>
- */
-
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <linux/phylink.h>
-#include <linux/pcs-altera-tse.h>
-
-/* SGMII PCS register addresses
- */
-#define SGMII_PCS_LINK_TIMER_0 0x12
-#define SGMII_PCS_LINK_TIMER_1 0x13
-#define SGMII_PCS_IF_MODE 0x14
-#define PCS_IF_MODE_SGMII_ENA BIT(0)
-#define PCS_IF_MODE_USE_SGMII_AN BIT(1)
-#define PCS_IF_MODE_SGMI_HALF_DUPLEX BIT(4)
-#define PCS_IF_MODE_SGMI_PHY_AN BIT(5)
-#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */
-
-struct altera_tse_pcs {
- struct phylink_pcs pcs;
- void __iomem *base;
- int reg_width;
-};
-
-static struct altera_tse_pcs *phylink_pcs_to_tse_pcs(struct phylink_pcs *pcs)
-{
- return container_of(pcs, struct altera_tse_pcs, pcs);
-}
-
-static u16 tse_pcs_read(struct altera_tse_pcs *tse_pcs, int regnum)
-{
- if (tse_pcs->reg_width == 4)
- return readl(tse_pcs->base + regnum * 4);
- else
- return readw(tse_pcs->base + regnum * 2);
-}
-
-static void tse_pcs_write(struct altera_tse_pcs *tse_pcs, int regnum,
- u16 value)
-{
- if (tse_pcs->reg_width == 4)
- writel(value, tse_pcs->base + regnum * 4);
- else
- writew(value, tse_pcs->base + regnum * 2);
-}
-
-static int tse_pcs_reset(struct altera_tse_pcs *tse_pcs)
-{
- u16 bmcr;
-
- /* Reset PCS block */
- bmcr = tse_pcs_read(tse_pcs, MII_BMCR);
- bmcr |= BMCR_RESET;
- tse_pcs_write(tse_pcs, MII_BMCR, bmcr);
-
- return read_poll_timeout(tse_pcs_read, bmcr, (bmcr & BMCR_RESET),
- 10, SGMII_PCS_SW_RESET_TIMEOUT, 1,
- tse_pcs, MII_BMCR);
-}
-
-static int alt_tse_pcs_validate(struct phylink_pcs *pcs,
- unsigned long *supported,
- const struct phylink_link_state *state)
-{
- if (state->interface == PHY_INTERFACE_MODE_SGMII ||
- state->interface == PHY_INTERFACE_MODE_1000BASEX)
- return 1;
-
- return -EINVAL;
-}
-
-static int alt_tse_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- bool permit_pause_to_mac)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u32 ctrl, if_mode;
-
- ctrl = tse_pcs_read(tse_pcs, MII_BMCR);
- if_mode = tse_pcs_read(tse_pcs, SGMII_PCS_IF_MODE);
-
- /* Set link timer to 1.6ms, as per the MegaCore Function User Guide */
- tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_0, 0x0D40);
- tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_1, 0x03);
-
- if (interface == PHY_INTERFACE_MODE_SGMII) {
- if_mode |= PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA;
- } else if (interface == PHY_INTERFACE_MODE_1000BASEX) {
- if_mode &= ~(PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA);
- }
-
- ctrl |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE);
-
- tse_pcs_write(tse_pcs, MII_BMCR, ctrl);
- tse_pcs_write(tse_pcs, SGMII_PCS_IF_MODE, if_mode);
-
- return tse_pcs_reset(tse_pcs);
-}
-
-static void alt_tse_pcs_get_state(struct phylink_pcs *pcs,
- struct phylink_link_state *state)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u16 bmsr, lpa;
-
- bmsr = tse_pcs_read(tse_pcs, MII_BMSR);
- lpa = tse_pcs_read(tse_pcs, MII_LPA);
-
- phylink_mii_c22_pcs_decode_state(state, bmsr, lpa);
-}
-
-static void alt_tse_pcs_an_restart(struct phylink_pcs *pcs)
-{
- struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs);
- u16 bmcr;
-
- bmcr = tse_pcs_read(tse_pcs, MII_BMCR);
- bmcr |= BMCR_ANRESTART;
- tse_pcs_write(tse_pcs, MII_BMCR, bmcr);
-
- /* This PCS seems to require a soft reset to re-sync the AN logic */
- tse_pcs_reset(tse_pcs);
-}
-
-static const struct phylink_pcs_ops alt_tse_pcs_ops = {
- .pcs_validate = alt_tse_pcs_validate,
- .pcs_get_state = alt_tse_pcs_get_state,
- .pcs_config = alt_tse_pcs_config,
- .pcs_an_restart = alt_tse_pcs_an_restart,
-};
-
-struct phylink_pcs *alt_tse_pcs_create(struct net_device *ndev,
- void __iomem *pcs_base, int reg_width)
-{
- struct altera_tse_pcs *tse_pcs;
-
- if (reg_width != 4 && reg_width != 2)
- return ERR_PTR(-EINVAL);
-
- tse_pcs = devm_kzalloc(&ndev->dev, sizeof(*tse_pcs), GFP_KERNEL);
- if (!tse_pcs)
- return ERR_PTR(-ENOMEM);
-
- tse_pcs->pcs.ops = &alt_tse_pcs_ops;
- tse_pcs->base = pcs_base;
- tse_pcs->reg_width = reg_width;
-
- return &tse_pcs->pcs;
-}
-EXPORT_SYMBOL_GPL(alt_tse_pcs_create);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Altera TSE PCS driver");
-MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index 622c3de3f3a8..dc3962b2aa6b 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -6,6 +6,7 @@
#include <linux/mdio.h>
#include <linux/phylink.h>
#include <linux/pcs-lynx.h>
+#include <linux/property.h>
#define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */
#define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS))
@@ -34,14 +35,6 @@ enum sgmii_speed {
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
-struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs)
-{
- struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
-
- return lynx->mdio;
-}
-EXPORT_SYMBOL(lynx_get_mdio_device);
-
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
struct phylink_link_state *state)
{
@@ -119,9 +112,10 @@ static void lynx_pcs_get_state(struct phylink_pcs *pcs,
state->link, state->an_complete);
}
-static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
+static int lynx_pcs_config_giga(struct mdio_device *pcs,
phy_interface_t interface,
- const unsigned long *advertising)
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
int link_timer_ns;
u32 link_timer;
@@ -139,8 +133,9 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
if (interface == PHY_INTERFACE_MODE_1000BASEX) {
if_mode = 0;
} else {
+ /* SGMII and QSGMII */
if_mode = IF_MODE_SGMII_EN;
- if (mode == MLO_AN_INBAND)
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
if_mode |= IF_MODE_USE_SGMII_AN;
}
@@ -150,16 +145,18 @@ static int lynx_pcs_config_giga(struct mdio_device *pcs, unsigned int mode,
if (err)
return err;
- return phylink_mii_c22_pcs_config(pcs, mode, interface, advertising);
+ return phylink_mii_c22_pcs_config(pcs, interface, advertising,
+ neg_mode);
}
-static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode,
- const unsigned long *advertising)
+static int lynx_pcs_config_usxgmii(struct mdio_device *pcs,
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
struct mii_bus *bus = pcs->bus;
int addr = pcs->addr;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&pcs->dev, "USXGMII only supports in-band AN for now\n");
return -EOPNOTSUPP;
}
@@ -171,10 +168,9 @@ static int lynx_pcs_config_usxgmii(struct mdio_device *pcs, unsigned int mode,
ADVERTISE_SGMII | ADVERTISE_LPACK);
}
-static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t ifmode,
- const unsigned long *advertising,
- bool permit)
+ const unsigned long *advertising, bool permit)
{
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
@@ -182,17 +178,18 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
- return lynx_pcs_config_giga(lynx->mdio, mode, ifmode,
- advertising);
+ return lynx_pcs_config_giga(lynx->mdio, ifmode, advertising,
+ neg_mode);
case PHY_INTERFACE_MODE_2500BASEX:
- if (phylink_autoneg_inband(mode)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&lynx->mdio->dev,
"AN not supported on 3.125GHz SerDes lane\n");
return -EOPNOTSUPP;
}
break;
case PHY_INTERFACE_MODE_USXGMII:
- return lynx_pcs_config_usxgmii(lynx->mdio, mode, advertising);
+ return lynx_pcs_config_usxgmii(lynx->mdio, advertising,
+ neg_mode);
case PHY_INTERFACE_MODE_10GBASER:
/* Nothing to do here for 10GBASER */
break;
@@ -210,7 +207,8 @@ static void lynx_pcs_an_restart(struct phylink_pcs *pcs)
phylink_mii_c22_pcs_an_restart(lynx->mdio);
}
-static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
+static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs,
+ unsigned int neg_mode,
int speed, int duplex)
{
u16 if_mode = 0, sgmii_speed;
@@ -218,7 +216,7 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
/* The PCS needs to be configured manually only
* when not operating on in-band mode
*/
- if (mode == MLO_AN_INBAND)
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
if (duplex == DUPLEX_HALF)
@@ -265,12 +263,12 @@ static void lynx_pcs_link_up_sgmii(struct mdio_device *pcs, unsigned int mode,
* 2500 Mbps and we do rate adaptation through pause frames.
*/
static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs,
- unsigned int mode,
+ unsigned int neg_mode,
int speed, int duplex)
{
u16 if_mode = 0;
- if (mode == MLO_AN_INBAND) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
dev_err(&pcs->dev, "AN not supported for 2500BaseX\n");
return;
}
@@ -284,7 +282,7 @@ static void lynx_pcs_link_up_2500basex(struct mdio_device *pcs,
if_mode);
}
-static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
int speed, int duplex)
{
@@ -293,10 +291,10 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
switch (interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
- lynx_pcs_link_up_sgmii(lynx->mdio, mode, speed, duplex);
+ lynx_pcs_link_up_sgmii(lynx->mdio, neg_mode, speed, duplex);
break;
case PHY_INTERFACE_MODE_2500BASEX:
- lynx_pcs_link_up_2500basex(lynx->mdio, mode, speed, duplex);
+ lynx_pcs_link_up_2500basex(lynx->mdio, neg_mode, speed, duplex);
break;
case PHY_INTERFACE_MODE_USXGMII:
/* At the moment, only in-band AN is supported for USXGMII
@@ -315,26 +313,87 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
.pcs_link_up = lynx_pcs_link_up,
};
-struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
+static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
{
struct lynx_pcs *lynx;
lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
if (!lynx)
- return NULL;
+ return ERR_PTR(-ENOMEM);
+ mdio_device_get(mdio);
lynx->mdio = mdio;
lynx->pcs.ops = &lynx_pcs_phylink_ops;
+ lynx->pcs.neg_mode = true;
lynx->pcs.poll = true;
return lynx_to_phylink_pcs(lynx);
}
-EXPORT_SYMBOL(lynx_pcs_create);
+
+struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr)
+{
+ struct mdio_device *mdio;
+ struct phylink_pcs *pcs;
+
+ mdio = mdio_device_create(bus, addr);
+ if (IS_ERR(mdio))
+ return ERR_CAST(mdio);
+
+ pcs = lynx_pcs_create(mdio);
+
+ /* lynx_create() has taken a refcount on the mdiodev if it was
+ * successful. If lynx_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * lynx_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdio);
+
+ return pcs;
+}
+EXPORT_SYMBOL(lynx_pcs_create_mdiodev);
+
+/*
+ * lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode
+ * device indicated by node.
+ *
+ * Returns:
+ * -ENODEV if the fwnode is marked unavailable
+ * -EPROBE_DEFER if we fail to find the device
+ * -ENOMEM if we fail to allocate memory
+ * pointer to a phylink_pcs on success
+ */
+struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node)
+{
+ struct mdio_device *mdio;
+ struct phylink_pcs *pcs;
+
+ if (!fwnode_device_is_available(node))
+ return ERR_PTR(-ENODEV);
+
+ mdio = fwnode_mdio_find_device(node);
+ if (!mdio)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ pcs = lynx_pcs_create(mdio);
+
+ /* lynx_create() has taken a refcount on the mdiodev if it was
+ * successful. If lynx_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * lynx_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdio);
+
+ return pcs;
+}
+EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode);
void lynx_pcs_destroy(struct phylink_pcs *pcs)
{
struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);
+ mdio_device_put(lynx->mdio);
kfree(lynx);
}
EXPORT_SYMBOL(lynx_pcs_destroy);
diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
index 888452325edc..b0f3ede945d9 100644
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -102,13 +102,13 @@ static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
FIELD_GET(SGMII_LPA, adv));
}
-static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
- bool mode_changed = false, changed, use_an;
+ bool mode_changed = false, changed;
unsigned int rgc3, sgm_mode, bmcr;
int advertise, link_timer;
@@ -121,30 +121,21 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
* we assume that fixes it's speed at bitrate = line rate (in
* other words, 1000Mbps or 2500Mbps).
*/
- if (interface == PHY_INTERFACE_MODE_SGMII) {
+ if (interface == PHY_INTERFACE_MODE_SGMII)
sgm_mode = SGMII_IF_MODE_SGMII;
- if (phylink_autoneg_inband(mode)) {
- sgm_mode |= SGMII_REMOTE_FAULT_DIS |
- SGMII_SPEED_DUPLEX_AN;
- use_an = true;
- } else {
- use_an = false;
- }
- } else if (phylink_autoneg_inband(mode)) {
- /* 1000base-X or 2500base-X autoneg */
- sgm_mode = SGMII_REMOTE_FAULT_DIS;
- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
- } else {
- /* 1000base-X or 2500base-X without autoneg */
+ else
sgm_mode = 0;
- use_an = false;
- }
- if (use_an)
+ if (neg_mode & PHYLINK_PCS_NEG_INBAND)
+ sgm_mode |= SGMII_REMOTE_FAULT_DIS;
+
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ sgm_mode |= SGMII_SPEED_DUPLEX_AN;
bmcr = BMCR_ANENABLE;
- else
+ } else {
bmcr = 0;
+ }
if (mpcs->interface != interface) {
link_timer = phylink_get_link_timer_ns(interface);
@@ -216,14 +207,15 @@ static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs)
regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART);
}
-static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode,
+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs,
+ unsigned int neg_mode,
phy_interface_t interface, int speed,
int duplex)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
unsigned int sgm_mode;
- if (!phylink_autoneg_inband(mode)) {
+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
/* Force the speed and duplex setting */
if (speed == SPEED_10)
sgm_mode = SGMII_SPEED_10;
@@ -286,6 +278,7 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
mpcs->regmap = regmap;
mpcs->flags = flags;
mpcs->pcs.ops = &mtk_pcs_lynxi_ops;
+ mpcs->pcs.neg_mode = true;
mpcs->pcs.poll = true;
mpcs->interface = PHY_INTERFACE_MODE_NA;
diff --git a/drivers/net/pcs/pcs-rzn1-miic.c b/drivers/net/pcs/pcs-rzn1-miic.c
index 323bec5e57f8..356099169003 100644
--- a/drivers/net/pcs/pcs-rzn1-miic.c
+++ b/drivers/net/pcs/pcs-rzn1-miic.c
@@ -313,15 +313,21 @@ struct phylink_pcs *miic_create(struct device *dev, struct device_node *np)
pdev = of_find_device_by_node(pcs_np);
of_node_put(pcs_np);
- if (!pdev || !platform_get_drvdata(pdev))
+ if (!pdev || !platform_get_drvdata(pdev)) {
+ if (pdev)
+ put_device(&pdev->dev);
return ERR_PTR(-EPROBE_DEFER);
+ }
miic_port = kzalloc(sizeof(*miic_port), GFP_KERNEL);
- if (!miic_port)
+ if (!miic_port) {
+ put_device(&pdev->dev);
return ERR_PTR(-ENOMEM);
+ }
miic = platform_get_drvdata(pdev);
device_link_add(dev, miic->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ put_device(&pdev->dev);
miic_port->miic = miic;
miic_port->port = port - 1;
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 72f25e778840..44b037646865 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -64,6 +64,16 @@ static const int xpcs_xlgmii_features[] = {
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
+static const int xpcs_10gbaser_features[] = {
+ ETHTOOL_LINK_MODE_Pause_BIT,
+ ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+ __ETHTOOL_LINK_MODE_MASK_NBITS,
+};
+
static const int xpcs_sgmii_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@@ -106,6 +116,10 @@ static const phy_interface_t xpcs_xlgmii_interfaces[] = {
PHY_INTERFACE_MODE_XLGMII,
};
+static const phy_interface_t xpcs_10gbaser_interfaces[] = {
+ PHY_INTERFACE_MODE_10GBASER,
+};
+
static const phy_interface_t xpcs_sgmii_interfaces[] = {
PHY_INTERFACE_MODE_SGMII,
};
@@ -123,6 +137,7 @@ enum {
DW_XPCS_USXGMII,
DW_XPCS_10GKR,
DW_XPCS_XLGMII,
+ DW_XPCS_10GBASER,
DW_XPCS_SGMII,
DW_XPCS_1000BASEX,
DW_XPCS_2500BASEX,
@@ -246,6 +261,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
switch (compat->an_mode) {
case DW_AN_C73:
+ case DW_10GBASER:
dev = MDIO_MMD_PCS;
break;
case DW_AN_C37_SGMII:
@@ -271,15 +287,12 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
})
static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state,
+ u16 pcs_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_STAT1_FAULT) {
+ if (pcs_stat1 & MDIO_STAT1_FAULT) {
xpcs_warn(xpcs, state, "Link fault condition detected!\n");
return -EFAULT;
}
@@ -321,37 +334,6 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
return 0;
}
-static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
-{
- bool link = true;
- int ret;
-
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (!(ret & MDIO_STAT1_LSTATUS))
- link = false;
-
- return link;
-}
-
-static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
-{
- int max = SPEED_UNKNOWN;
-
- if (phylink_test(supported, 1000baseKX_Full))
- max = SPEED_1000;
- if (phylink_test(supported, 2500baseX_Full))
- max = SPEED_2500;
- if (phylink_test(supported, 10000baseKX4_Full))
- max = SPEED_10000;
- if (phylink_test(supported, 10000baseKR_Full))
- max = SPEED_10000;
-
- return max;
-}
-
static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
{
int ret, speed_sel;
@@ -478,16 +460,12 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state,
- const struct xpcs_compat *compat)
+ const struct xpcs_compat *compat, u16 an_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_AN_STAT1_COMPLETE) {
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
+ if (an_stat1 & MDIO_AN_STAT1_COMPLETE) {
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
if (ret < 0)
return ret;
@@ -504,64 +482,32 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
}
static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state, u16 an_stat1)
{
- int ret;
-
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
+ u16 lpa[3];
+ int i, ret;
- if (!(ret & MDIO_AN_STAT1_LPABLE)) {
+ if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) {
phylink_clear(state->lp_advertising, Autoneg);
return 0;
}
phylink_set(state->lp_advertising, Autoneg);
- /* Clause 73 outcome */
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_2500KX)
- phylink_set(state->lp_advertising, 2500baseX_Full);
-
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_1000KX)
- phylink_set(state->lp_advertising, 1000baseKX_Full);
- if (ret & DW_C73_10000KX4)
- phylink_set(state->lp_advertising, 10000baseKX4_Full);
- if (ret & DW_C73_10000KR)
- phylink_set(state->lp_advertising, 10000baseKR_Full);
+ /* Read Clause 73 link partner advertisement */
+ for (i = ARRAY_SIZE(lpa); --i >= 0; ) {
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i);
+ if (ret < 0)
+ return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
- if (ret < 0)
- return ret;
+ lpa[i] = ret;
+ }
- if (ret & DW_C73_PAUSE)
- phylink_set(state->lp_advertising, Pause);
- if (ret & DW_C73_ASYM_PAUSE)
- phylink_set(state->lp_advertising, Asym_Pause);
+ mii_c73_mod_linkmode(state->lp_advertising, lpa);
- linkmode_and(state->lp_advertising, state->lp_advertising,
- state->advertising);
return 0;
}
-static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
-{
- int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
-
- state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
- state->speed = max_speed;
- state->duplex = DUPLEX_FULL;
-}
-
static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
@@ -711,7 +657,8 @@ int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
}
EXPORT_SYMBOL_GPL(xpcs_config_eee);
-static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
+static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs,
+ unsigned int neg_mode)
{
int ret, mdio_ctrl;
@@ -761,7 +708,7 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
else
ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW;
@@ -770,14 +717,15 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode)
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
mdio_ctrl | AN_CL37_EN);
return ret;
}
-static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
+static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs,
+ unsigned int neg_mode,
const unsigned long *advertising)
{
phy_interface_t interface = PHY_INTERFACE_MODE_1000BASEX;
@@ -828,8 +776,7 @@ static int xpcs_config_aneg_c37_1000basex(struct dw_xpcs *xpcs, unsigned int mod
if (ret < 0)
return ret;
- if (phylink_autoneg_inband(mode) &&
- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL,
mdio_ctrl | AN_CL37_EN);
if (ret < 0)
@@ -862,7 +809,7 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs)
}
int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
- unsigned int mode, const unsigned long *advertising)
+ const unsigned long *advertising, unsigned int neg_mode)
{
const struct xpcs_compat *compat;
int ret;
@@ -872,20 +819,22 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
return -ENODEV;
switch (compat->an_mode) {
+ case DW_10GBASER:
+ break;
case DW_AN_C73:
- if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) {
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
ret = xpcs_config_aneg_c73(xpcs, compat);
if (ret)
return ret;
}
break;
case DW_AN_C37_SGMII:
- ret = xpcs_config_aneg_c37_sgmii(xpcs, mode);
+ ret = xpcs_config_aneg_c37_sgmii(xpcs, neg_mode);
if (ret)
return ret;
break;
case DW_AN_C37_1000BASEX:
- ret = xpcs_config_aneg_c37_1000basex(xpcs, mode,
+ ret = xpcs_config_aneg_c37_1000basex(xpcs, neg_mode,
advertising);
if (ret)
return ret;
@@ -909,14 +858,14 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
}
EXPORT_SYMBOL_GPL(xpcs_do_config);
-static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode,
+static int xpcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- return xpcs_do_config(xpcs, interface, mode, advertising);
+ return xpcs_do_config(xpcs, interface, advertising, neg_mode);
}
static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
@@ -924,13 +873,25 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
const struct xpcs_compat *compat)
{
bool an_enabled;
+ int pcs_stat1;
+ int an_stat1;
int ret;
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
+ if (pcs_stat1 < 0) {
+ state->link = false;
+ return pcs_stat1;
+ }
+
/* Link needs to be read first ... */
- state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0;
+ state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS);
/* ... and then we check the faults. */
- ret = xpcs_read_fault_c73(xpcs, state);
+ ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1);
if (ret) {
ret = xpcs_soft_reset(xpcs, compat);
if (ret)
@@ -938,18 +899,42 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
state->link = 0;
- return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
+ return xpcs_do_config(xpcs, state->interface, NULL,
+ PHYLINK_PCS_NEG_INBAND_ENABLED);
}
+ /* There is no point doing anything else if the link is down. */
+ if (!state->link)
+ return 0;
+
an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
state->advertising);
- if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
- state->an_complete = true;
- xpcs_read_lpa_c73(xpcs, state);
- xpcs_resolve_lpa_c73(xpcs, state);
- } else if (an_enabled) {
- state->link = 0;
- } else if (state->link) {
+ if (an_enabled) {
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
+ if (an_stat1 < 0) {
+ state->link = false;
+ return an_stat1;
+ }
+
+ state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat,
+ an_stat1);
+ if (!state->an_complete) {
+ state->link = false;
+ return 0;
+ }
+
+ ret = xpcs_read_lpa_c73(xpcs, state, an_stat1);
+ if (ret < 0) {
+ state->link = false;
+ return ret;
+ }
+
+ phylink_resolve_c73(state);
+ } else {
xpcs_resolve_pma(xpcs, state);
}
@@ -1033,6 +1018,9 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
return;
switch (compat->an_mode) {
+ case DW_10GBASER:
+ phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state);
+ break;
case DW_AN_C73:
ret = xpcs_get_state_c73(xpcs, state, compat);
if (ret) {
@@ -1060,12 +1048,12 @@ static void xpcs_get_state(struct phylink_pcs *pcs,
}
}
-static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
+static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int neg_mode,
int speed, int duplex)
{
int val, ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
val = mii_bmcr_encode_fixed(speed, duplex);
@@ -1074,12 +1062,12 @@ static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode,
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
}
-static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
+static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int neg_mode,
int speed, int duplex)
{
int val, ret;
- if (phylink_autoneg_inband(mode))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
return;
switch (speed) {
@@ -1103,7 +1091,7 @@ static void xpcs_link_up_1000basex(struct dw_xpcs *xpcs, unsigned int mode,
pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret));
}
-void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
+void xpcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
phy_interface_t interface, int speed, int duplex)
{
struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
@@ -1111,9 +1099,9 @@ void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
if (interface == PHY_INTERFACE_MODE_USXGMII)
return xpcs_config_usxgmii(xpcs, speed);
if (interface == PHY_INTERFACE_MODE_SGMII)
- return xpcs_link_up_sgmii(xpcs, mode, speed, duplex);
+ return xpcs_link_up_sgmii(xpcs, neg_mode, speed, duplex);
if (interface == PHY_INTERFACE_MODE_1000BASEX)
- return xpcs_link_up_1000basex(xpcs, mode, speed, duplex);
+ return xpcs_link_up_1000basex(xpcs, neg_mode, speed, duplex);
}
EXPORT_SYMBOL_GPL(xpcs_link_up);
@@ -1188,6 +1176,12 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = {
.num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces),
.an_mode = DW_AN_C73,
},
+ [DW_XPCS_10GBASER] = {
+ .supported = xpcs_10gbaser_features,
+ .interface = xpcs_10gbaser_interfaces,
+ .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces),
+ .an_mode = DW_10GBASER,
+ },
[DW_XPCS_SGMII] = {
.supported = xpcs_sgmii_features,
.interface = xpcs_sgmii_interfaces,
@@ -1259,8 +1253,8 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_link_up = xpcs_link_up,
};
-struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
- phy_interface_t interface)
+static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
+ phy_interface_t interface)
{
struct dw_xpcs *xpcs;
u32 xpcs_id;
@@ -1270,6 +1264,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
if (!xpcs)
return ERR_PTR(-ENOMEM);
+ mdio_device_get(mdiodev);
xpcs->mdiodev = mdiodev;
xpcs_id = xpcs_get_id(xpcs);
@@ -1290,6 +1285,10 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
}
xpcs->pcs.ops = &xpcs_phylink_ops;
+ xpcs->pcs.neg_mode = true;
+ if (compat->an_mode == DW_10GBASER)
+ return xpcs;
+
xpcs->pcs.poll = true;
ret = xpcs_soft_reset(xpcs, compat);
@@ -1302,16 +1301,42 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
ret = -ENODEV;
out:
+ mdio_device_put(mdiodev);
kfree(xpcs);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_GPL(xpcs_create);
void xpcs_destroy(struct dw_xpcs *xpcs)
{
+ if (xpcs)
+ mdio_device_put(xpcs->mdiodev);
kfree(xpcs);
}
EXPORT_SYMBOL_GPL(xpcs_destroy);
+struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr,
+ phy_interface_t interface)
+{
+ struct mdio_device *mdiodev;
+ struct dw_xpcs *xpcs;
+
+ mdiodev = mdio_device_create(bus, addr);
+ if (IS_ERR(mdiodev))
+ return ERR_CAST(mdiodev);
+
+ xpcs = xpcs_create(mdiodev, interface);
+
+ /* xpcs_create() has taken a refcount on the mdiodev if it was
+ * successful. If xpcs_create() fails, this will free the mdio
+ * device here. In any case, we don't need to hold our reference
+ * anymore, and putting it here will allow mdio_device_put() in
+ * xpcs_destroy() to automatically free the mdio device.
+ */
+ mdio_device_put(mdiodev);
+
+ return xpcs;
+}
+EXPORT_SYMBOL_GPL(xpcs_create_mdiodev);
+
MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index 770df50323a0..68c6b5a62088 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -32,9 +32,6 @@
#define DW_SR_AN_ADV1 0x10
#define DW_SR_AN_ADV2 0x11
#define DW_SR_AN_ADV3 0x12
-#define DW_SR_AN_LP_ABL1 0x13
-#define DW_SR_AN_LP_ABL2 0x14
-#define DW_SR_AN_LP_ABL3 0x15
/* Clause 73 Defines */
/* AN_LP_ABL1 */
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 93b8efc79227..78e6981650d9 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -236,6 +236,18 @@ config MEDIATEK_GE_PHY
help
Supports the MediaTek Gigabit Ethernet PHYs.
+config MEDIATEK_GE_SOC_PHY
+ tristate "MediaTek SoC Ethernet PHYs"
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
+ depends on NVMEM_MTK_EFUSE
+ help
+ Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
+
+ Include support for built-in Ethernet PHYs which are present in
+ the MT7981 and MT7988 SoCs. These PHYs need calibration data
+ present in the SoCs efuse and will dynamically calibrate VCM
+ (common-mode voltage) during startup.
+
config MICREL_PHY
tristate "Micrel PHYs"
depends on PTP_1588_CLOCK_OPTIONAL
@@ -243,9 +255,10 @@ config MICREL_PHY
Supports the KSZ9021, VSC8201, KS8001 PHYs.
config MICROCHIP_T1S_PHY
- tristate "Microchip 10BASE-T1S Ethernet PHY"
+ tristate "Microchip 10BASE-T1S Ethernet PHYs"
help
- Currently supports the LAN8670, LAN8671, LAN8672
+ Currently supports the LAN8670/1/2 Rev.B1 and LAN8650/1 Rev.B0 Internal
+ PHYs.
config MICROCHIP_PHY
tristate "Microchip PHYs"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index f289ab16a1da..2fe51ea83bab 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
+obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 656136628ffd..8a77ec33b417 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -304,7 +304,6 @@ struct at803x_priv {
bool is_1000basex;
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
- struct regulator *vddio;
u64 stats[ARRAY_SIZE(at803x_hw_stats)];
};
@@ -460,21 +459,27 @@ static int at803x_set_wol(struct phy_device *phydev,
phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
- /* Enable WOL function */
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
- 0, AT803X_WOL_EN);
- if (ret)
- return ret;
+ /* Enable WOL function for 1588 */
+ if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ 0, AT803X_WOL_EN);
+ if (ret)
+ return ret;
+ }
/* Enable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
if (ret)
return ret;
} else {
- /* Disable WoL function */
- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
- AT803X_WOL_EN, 0);
- if (ret)
- return ret;
+ /* Disable WoL function for 1588 */
+ if (phydev->drv->phy_id == ATH8031_PHY_ID) {
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+ if (ret)
+ return ret;
+ }
/* Disable WOL interrupt */
ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
if (ret)
@@ -509,11 +514,11 @@ static void at803x_get_wol(struct phy_device *phydev,
wol->supported = WAKE_MAGIC;
wol->wolopts = 0;
- value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL);
+ value = phy_read(phydev, AT803X_INTR_ENABLE);
if (value < 0)
return;
- if (value & AT803X_WOL_EN)
+ if (value & AT803X_INTR_ENABLE_WOL)
wol->wolopts |= WAKE_MAGIC;
}
@@ -824,11 +829,11 @@ static int at803x_parse_dt(struct phy_device *phydev)
if (ret < 0)
return ret;
- priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev,
- "vddio");
- if (IS_ERR(priv->vddio)) {
+ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev,
+ "vddio");
+ if (ret) {
phydev_err(phydev, "failed to get VDDIO regulator\n");
- return PTR_ERR(priv->vddio);
+ return ret;
}
/* Only AR8031/8033 support 1000Base-X for SFP modules */
@@ -856,23 +861,12 @@ static int at803x_probe(struct phy_device *phydev)
if (ret)
return ret;
- if (priv->vddio) {
- ret = regulator_enable(priv->vddio);
- if (ret < 0)
- return ret;
- }
-
if (phydev->drv->phy_id == ATH8031_PHY_ID) {
int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
int mode_cfg;
- struct ethtool_wolinfo wol = {
- .wolopts = 0,
- };
- if (ccr < 0) {
- ret = ccr;
- goto err;
- }
+ if (ccr < 0)
+ return ccr;
mode_cfg = ccr & AT803X_MODE_CFG_MASK;
switch (mode_cfg) {
@@ -886,29 +880,17 @@ static int at803x_probe(struct phy_device *phydev)
break;
}
- /* Disable WOL by default */
- ret = at803x_set_wol(phydev, &wol);
- if (ret < 0) {
- phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret);
- goto err;
- }
+ /* Disable WoL in 1588 register which is enabled
+ * by default
+ */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_PHY_MMD3_WOL_CTRL,
+ AT803X_WOL_EN, 0);
+ if (ret)
+ return ret;
}
return 0;
-
-err:
- if (priv->vddio)
- regulator_disable(priv->vddio);
-
- return ret;
-}
-
-static void at803x_remove(struct phy_device *phydev)
-{
- struct at803x_priv *priv = phydev->priv;
-
- if (priv->vddio)
- regulator_disable(priv->vddio);
}
static int at803x_get_features(struct phy_device *phydev)
@@ -2021,7 +2003,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8035",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_aneg = at803x_config_aneg,
.config_init = at803x_config_init,
.soft_reset = genphy_soft_reset,
@@ -2043,7 +2024,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8030",
.phy_id_mask = AT8030_PHY_ID_MASK,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
.set_wol = at803x_set_wol,
@@ -2059,7 +2039,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm Atheros AR8031/AR8033",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_init = at803x_config_init,
.config_aneg = at803x_config_aneg,
.soft_reset = genphy_soft_reset,
@@ -2082,12 +2061,9 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
.name = "Qualcomm Atheros AR8032",
.probe = at803x_probe,
- .remove = at803x_remove,
.flags = PHY_POLL_CABLE_TEST,
.config_init = at803x_config_init,
.link_change_notify = at803x_link_change_notify,
- .set_wol = at803x_set_wol,
- .get_wol = at803x_get_wol,
.suspend = at803x_suspend,
.resume = at803x_resume,
/* PHY_BASIC_FEATURES */
@@ -2100,7 +2076,6 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
.name = "Qualcomm Atheros AR9331 built-in PHY",
.probe = at803x_probe,
- .remove = at803x_remove,
.suspend = at803x_suspend,
.resume = at803x_resume,
.flags = PHY_POLL_CABLE_TEST,
@@ -2117,7 +2092,6 @@ static struct phy_driver at803x_driver[] = {
PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
.name = "Qualcomm Atheros QCA9561 built-in PHY",
.probe = at803x_probe,
- .remove = at803x_remove,
.suspend = at803x_suspend,
.resume = at803x_resume,
.flags = PHY_POLL_CABLE_TEST,
@@ -2183,7 +2157,6 @@ static struct phy_driver at803x_driver[] = {
.name = "Qualcomm QCA8081",
.flags = PHY_POLL_CABLE_TEST,
.probe = at803x_probe,
- .remove = at803x_remove,
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c
index b2c0baa51f39..876f28fd8256 100644
--- a/drivers/net/phy/bcm-phy-lib.c
+++ b/drivers/net/phy/bcm-phy-lib.c
@@ -6,12 +6,14 @@
#include "bcm-phy-lib.h"
#include <linux/bitfield.h>
#include <linux/brcmphy.h>
+#include <linux/etherdevice.h>
#include <linux/export.h>
#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/ethtool.h>
#include <linux/ethtool_netlink.h>
+#include <linux/netdevice.h>
#define MII_BCM_CHANNEL_WIDTH 0x2000
#define BCM_CL45VEN_EEE_ADV 0x3c
@@ -494,18 +496,20 @@ EXPORT_SYMBOL_GPL(bcm_phy_downshift_set);
struct bcm_phy_hw_stat {
const char *string;
- u8 reg;
+ int devad;
+ u16 reg;
u8 shift;
u8 bits;
};
/* Counters freeze at either 0xffff or 0xff, better than nothing */
static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
- { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
- { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
- { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
- { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
- { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
+ { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12, 0, 16 },
+ { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13, 8, 8 },
+ { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13, 0, 8 },
+ { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14, 8, 8 },
+ { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14, 0, 8 },
+ { "phy_lpi_count", MDIO_MMD_AN, BRCM_CL45VEN_EEE_LPI_CNT, 0, 16 },
};
int bcm_phy_get_sset_count(struct phy_device *phydev)
@@ -534,7 +538,10 @@ static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
int val;
u64 ret;
- val = phy_read(phydev, stat.reg);
+ if (stat.devad < 0)
+ val = phy_read(phydev, stat.reg);
+ else
+ val = phy_read_mmd(phydev, stat.devad, stat.reg);
if (val < 0) {
ret = U64_MAX;
} else {
@@ -816,6 +823,249 @@ int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev,
}
EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb);
+#define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \
+ WAKE_MCAST | \
+ WAKE_BCAST | \
+ WAKE_MAGIC | \
+ WAKE_MAGICSECURE)
+
+int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ struct net_device *ndev = phydev->attached_dev;
+ u8 da[ETH_ALEN], mask[ETH_ALEN];
+ unsigned int i;
+ u16 ctl;
+ int ret;
+
+ /* Allow a MAC driver to play through its own Wake-on-LAN
+ * implementation
+ */
+ if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK)
+ return -EOPNOTSUPP;
+
+ /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's
+ * ethtool only supports 6, for now.
+ */
+ BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN);
+
+ /* Clear previous interrupts */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL);
+ if (ret < 0)
+ return ret;
+
+ ctl = ret;
+
+ if (!wol->wolopts) {
+ if (phy_interrupt_is_valid(phydev))
+ disable_irq_wake(phydev->irq);
+
+ /* Leave all interrupts disabled */
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK,
+ BCM54XX_WOL_ALL_INTRS);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the global Wake-on-LAN enable bit */
+ ctl &= ~BCM54XX_WOL_EN;
+
+ return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl);
+ }
+
+ /* Clear the previously configured mode and mask mode for Wake-on-LAN */
+ ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT);
+ ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT);
+ ctl &= ~BCM54XX_WOL_DIR_PKT_EN;
+ ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT);
+
+ /* When using WAKE_MAGIC, we program the magic pattern filter to match
+ * the device's MAC address and we accept any MAC DA in the Ethernet
+ * frame.
+ *
+ * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the
+ * following:
+ * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match
+ * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care
+ * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match
+ *
+ * Note that the Broadcast MAC DA is inherently going to match the
+ * multicast pattern being matched.
+ */
+ memset(mask, 0, sizeof(mask));
+
+ if (wol->wolopts & WAKE_MCAST) {
+ memset(da, 0, sizeof(da));
+ memset(mask, 0xff, sizeof(mask));
+ da[0] = 0x01;
+ mask[0] = ~da[0];
+ } else {
+ if (wol->wolopts & WAKE_UCAST) {
+ ether_addr_copy(da, ndev->dev_addr);
+ } else if (wol->wolopts & WAKE_BCAST) {
+ eth_broadcast_addr(da);
+ } else if (wol->wolopts & WAKE_MAGICSECURE) {
+ ether_addr_copy(da, wol->sopass);
+ } else if (wol->wolopts & WAKE_MAGIC) {
+ memset(da, 0, sizeof(da));
+ memset(mask, 0xff, sizeof(mask));
+ }
+ }
+
+ for (i = 0; i < ETH_ALEN / 2; i++) {
+ if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
+ ret = bcm_phy_write_exp(phydev,
+ BCM54XX_WOL_MPD_DATA1(2 - i),
+ ndev->dev_addr[i * 2] << 8 |
+ ndev->dev_addr[i * 2 + 1]);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i),
+ da[i * 2] << 8 | da[i * 2 + 1]);
+ if (ret < 0)
+ return ret;
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i),
+ mask[i * 2] << 8 | mask[i * 2 + 1]);
+ if (ret)
+ return ret;
+ }
+
+ if (wol->wolopts & WAKE_MAGICSECURE) {
+ ctl |= BCM54XX_WOL_SECKEY_OPT_6B <<
+ BCM54XX_WOL_SECKEY_OPT_SHIFT;
+ ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT;
+ ctl |= BCM54XX_WOL_MASK_MODE_DA_FF <<
+ BCM54XX_WOL_MASK_MODE_SHIFT;
+ } else {
+ if (wol->wolopts & WAKE_MAGIC)
+ ctl |= BCM54XX_WOL_MODE_SINGLE_MPD;
+ else
+ ctl |= BCM54XX_WOL_DIR_PKT_EN;
+ ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY <<
+ BCM54XX_WOL_MASK_MODE_SHIFT;
+ }
+
+ /* Globally enable Wake-on-LAN */
+ ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK;
+
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl);
+ if (ret < 0)
+ return ret;
+
+ /* Enable WOL interrupt on LED4 */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL);
+ if (ret < 0)
+ return ret;
+
+ ret |= BCM54XX_LED4_SEL_INTR;
+ ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret);
+ if (ret < 0)
+ return ret;
+
+ /* Enable all Wake-on-LAN interrupt sources */
+ ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0);
+ if (ret < 0)
+ return ret;
+
+ if (phy_interrupt_is_valid(phydev))
+ enable_irq_wake(phydev->irq);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_set_wol);
+
+void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
+{
+ struct net_device *ndev = phydev->attached_dev;
+ u8 da[ETH_ALEN];
+ unsigned int i;
+ int ret;
+ u16 ctl;
+
+ wol->supported = BCM54XX_WOL_SUPPORTED_MASK;
+ wol->wolopts = 0;
+
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL);
+ if (ret < 0)
+ return;
+
+ ctl = ret;
+
+ if (!(ctl & BCM54XX_WOL_EN))
+ return;
+
+ for (i = 0; i < sizeof(da) / 2; i++) {
+ ret = bcm_phy_read_exp(phydev,
+ BCM54XX_WOL_MPD_DATA2(2 - i));
+ if (ret < 0)
+ return;
+
+ da[i * 2] = ret >> 8;
+ da[i * 2 + 1] = ret & 0xff;
+ }
+
+ if (ctl & BCM54XX_WOL_DIR_PKT_EN) {
+ if (is_broadcast_ether_addr(da))
+ wol->wolopts |= WAKE_BCAST;
+ else if (is_multicast_ether_addr(da))
+ wol->wolopts |= WAKE_MCAST;
+ else if (ether_addr_equal(da, ndev->dev_addr))
+ wol->wolopts |= WAKE_UCAST;
+ } else {
+ ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK;
+ switch (ctl) {
+ case BCM54XX_WOL_MODE_SINGLE_MPD:
+ wol->wolopts |= WAKE_MAGIC;
+ break;
+ case BCM54XX_WOL_MODE_SINGLE_MPDSEC:
+ wol->wolopts |= WAKE_MAGICSECURE;
+ memcpy(wol->sopass, da, sizeof(da));
+ break;
+ default:
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(bcm_phy_get_wol);
+
+irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_wol_isr);
+
+int bcm_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value)
+{
+ u8 led_num;
+ int ret;
+ u16 reg;
+
+ if (index >= 4)
+ return -EINVAL;
+
+ /* Two LEDS per register */
+ led_num = index % 2;
+ reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1;
+
+ ret = bcm_phy_read_shadow(phydev, reg);
+ if (ret < 0)
+ return ret;
+
+ ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num));
+ if (value == LED_OFF)
+ ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num);
+ else
+ ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num);
+ return bcm_phy_write_shadow(phydev, reg, ret);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set);
+
MODULE_DESCRIPTION("Broadcom PHY Library");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Broadcom Corporation");
diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h
index 729db441797a..b52189e45a84 100644
--- a/drivers/net/phy/bcm-phy-lib.h
+++ b/drivers/net/phy/bcm-phy-lib.h
@@ -8,6 +8,9 @@
#include <linux/brcmphy.h>
#include <linux/phy.h>
+#include <linux/interrupt.h>
+
+struct ethtool_wolinfo;
/* 28nm only register definitions */
#define MISC_ADDR(base, channel) base, channel
@@ -111,4 +114,11 @@ static inline void bcm_ptp_stop(struct bcm_ptp_private *priv)
}
#endif
+int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol);
+irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id);
+
+int bcm_phy_led_brightness_set(struct phy_device *phydev,
+ u8 index, enum led_brightness value);
+
#endif /* _LINUX_BCM_PHY_LIB_H */
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index ad71c88c87e7..04b2e6eeb195 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -14,8 +14,12 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/phy.h>
+#include <linux/pm_wakeup.h>
#include <linux/brcmphy.h>
#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio/consumer.h>
#define BRCM_PHY_MODEL(phydev) \
((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -30,8 +34,17 @@ MODULE_LICENSE("GPL");
struct bcm54xx_phy_priv {
u64 *stats;
struct bcm_ptp_private *ptp;
+ int wake_irq;
+ bool wake_irq_enabled;
};
+static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev)
+{
+ struct bcm54xx_phy_priv *priv = phydev->priv;
+
+ return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0;
+}
+
static int bcm54xx_config_clock_delay(struct phy_device *phydev)
{
int rc, val;
@@ -401,18 +414,28 @@ static int bcm54xx_config_init(struct phy_device *phydev)
* these settings will cause LOS to malfunction.
*/
if (!phy_on_sfp(phydev)) {
- val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
- BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
- bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val);
+ val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |
+ BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);
+ bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val);
val = BCM_LED_MULTICOLOR_IN_PHASE |
- BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
- BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
+ BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |
+ BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);
bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);
}
bcm54xx_ptp_config_init(phydev);
+ /* Acknowledge any left over interrupt and charge the device for
+ * wake-up.
+ */
+ err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (err < 0)
+ return err;
+
+ if (err)
+ pm_wakeup_event(&phydev->mdio.dev, 0);
+
return 0;
}
@@ -437,12 +460,39 @@ out:
return ret;
}
+static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state)
+{
+ struct bcm54xx_phy_priv *priv = phydev->priv;
+ int ret = 0;
+
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return ret;
+
+ if (priv->wake_irq_enabled != state) {
+ if (state)
+ ret = enable_irq_wake(priv->wake_irq);
+ else
+ ret = disable_irq_wake(priv->wake_irq);
+ priv->wake_irq_enabled = state;
+ }
+
+ return ret;
+}
+
static int bcm54xx_suspend(struct phy_device *phydev)
{
- int ret;
+ int ret = 0;
bcm54xx_ptp_stop(phydev);
+ /* Acknowledge any Wake-on-LAN interrupt prior to suspend */
+ ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ if (phydev->wol_enabled)
+ return bcm54xx_set_wakeup_irq(phydev, true);
+
/* We cannot use a read/modify/write here otherwise the PHY gets into
* a bad state where its LEDs keep flashing, thus defeating the purpose
* of low power mode.
@@ -456,7 +506,13 @@ static int bcm54xx_suspend(struct phy_device *phydev)
static int bcm54xx_resume(struct phy_device *phydev)
{
- int ret;
+ int ret = 0;
+
+ if (phydev->wol_enabled) {
+ ret = bcm54xx_set_wakeup_irq(phydev, false);
+ if (ret)
+ return ret;
+ }
ret = bcm54xx_iddq_set(phydev, false);
if (ret < 0)
@@ -486,6 +542,17 @@ static int bcm54xx_resume(struct phy_device *phydev)
return bcm54xx_config_init(phydev);
}
+static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
+{
+ return -EOPNOTSUPP;
+}
+
+static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
+ u16 val)
+{
+ return -EOPNOTSUPP;
+}
+
static int bcm54811_config_init(struct phy_device *phydev)
{
int err, reg;
@@ -608,17 +675,6 @@ static int bcm54616s_read_status(struct phy_device *phydev)
return err;
}
-static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
-{
- int val;
-
- val = phy_read(phydev, reg);
- if (val < 0)
- return val;
-
- return phy_write(phydev, reg, val | set);
-}
-
static int brcm_fet_config_init(struct phy_device *phydev)
{
int reg, err, err2, brcmtest;
@@ -689,15 +745,15 @@ static int brcm_fet_config_init(struct phy_device *phydev)
goto done;
/* Enable auto MDIX */
- err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
- MII_BRCM_FET_SHDW_MC_FAME);
+ err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
+ MII_BRCM_FET_SHDW_MC_FAME);
if (err < 0)
goto done;
if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
/* Enable auto power down */
- err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
- MII_BRCM_FET_SHDW_AS2_APDE);
+ err = phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
+ MII_BRCM_FET_SHDW_AS2_APDE);
}
done:
@@ -801,14 +857,54 @@ static int brcm_fet_suspend(struct phy_device *phydev)
return err;
}
+static void bcm54xx_phy_get_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ /* We cannot wake-up if we do not have a dedicated PHY interrupt line
+ * or an out of band GPIO descriptor for wake-up. Zeroing
+ * wol->supported allows the caller (MAC driver) to play through and
+ * offer its own Wake-on-LAN scheme if available.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev)) {
+ wol->supported = 0;
+ return;
+ }
+
+ bcm_phy_get_wol(phydev, wol);
+}
+
+static int bcm54xx_phy_set_wol(struct phy_device *phydev,
+ struct ethtool_wolinfo *wol)
+{
+ int ret;
+
+ /* We cannot wake-up if we do not have a dedicated PHY interrupt line
+ * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP
+ * allows the caller (MAC driver) to play through and offer its own
+ * Wake-on-LAN scheme if available.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return -EOPNOTSUPP;
+
+ ret = bcm_phy_set_wol(phydev, wol);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int bcm54xx_phy_probe(struct phy_device *phydev)
{
struct bcm54xx_phy_priv *priv;
+ struct gpio_desc *wakeup_gpio;
+ int ret = 0;
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->wake_irq = -ENXIO;
+
phydev->priv = priv;
priv->stats = devm_kcalloc(&phydev->mdio.dev,
@@ -821,7 +917,35 @@ static int bcm54xx_phy_probe(struct phy_device *phydev)
if (IS_ERR(priv->ptp))
return PTR_ERR(priv->ptp);
- return 0;
+ /* We cannot utilize the _optional variant here since we want to know
+ * whether the GPIO descriptor exists or not to advertise Wake-on-LAN
+ * support or not.
+ */
+ wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN);
+ if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER)
+ return PTR_ERR(wakeup_gpio);
+
+ if (!IS_ERR(wakeup_gpio)) {
+ priv->wake_irq = gpiod_to_irq(wakeup_gpio);
+
+ /* Dummy interrupt handler which is not enabled but is provided
+ * in order for the interrupt descriptor to be fully set-up.
+ */
+ ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq,
+ bcm_phy_wol_isr,
+ IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
+ dev_name(&phydev->mdio.dev), phydev);
+ if (ret)
+ return ret;
+ }
+
+ /* If we do not have a main interrupt or a side-band wake-up interrupt,
+ * then the device cannot be marked as wake-up capable.
+ */
+ if (!bcm54xx_phy_can_wakeup(phydev))
+ return 0;
+
+ return device_init_wakeup(&phydev->mdio.dev, true);
}
static void bcm54xx_get_stats(struct phy_device *phydev,
@@ -894,6 +1018,7 @@ static struct phy_driver broadcom_drivers[] = {
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM54210E",
/* PHY_GBIT_FEATURES */
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
.get_sset_count = bcm_phy_get_sset_count,
.get_strings = bcm_phy_get_strings,
.get_stats = bcm54xx_get_stats,
@@ -904,6 +1029,9 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .get_wol = bcm54xx_phy_get_wol,
+ .set_wol = bcm54xx_phy_set_wol,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5461,
.phy_id_mask = 0xfffffff0,
@@ -917,6 +1045,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54612E,
.phy_id_mask = 0xfffffff0,
@@ -930,6 +1059,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54616S,
.phy_id_mask = 0xfffffff0,
@@ -943,6 +1073,7 @@ static struct phy_driver broadcom_drivers[] = {
.read_status = bcm54616s_read_status,
.probe = bcm54616s_probe,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5464,
.phy_id_mask = 0xfffffff0,
@@ -958,6 +1089,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = genphy_suspend,
.resume = genphy_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5481,
.phy_id_mask = 0xfffffff0,
@@ -972,6 +1104,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54810,
.phy_id_mask = 0xfffffff0,
@@ -981,6 +1114,8 @@ static struct phy_driver broadcom_drivers[] = {
.get_strings = bcm_phy_get_strings,
.get_stats = bcm54xx_get_stats,
.probe = bcm54xx_phy_probe,
+ .read_mmd = bcm54810_read_mmd,
+ .write_mmd = bcm54810_write_mmd,
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
.config_intr = bcm_phy_config_intr,
@@ -988,6 +1123,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM54811,
.phy_id_mask = 0xfffffff0,
@@ -1004,6 +1140,7 @@ static struct phy_driver broadcom_drivers[] = {
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM5482,
.phy_id_mask = 0xfffffff0,
@@ -1017,6 +1154,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM50610,
.phy_id_mask = 0xfffffff0,
@@ -1032,6 +1170,7 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM50610M,
.phy_id_mask = 0xfffffff0,
@@ -1047,6 +1186,7 @@ static struct phy_driver broadcom_drivers[] = {
.link_change_notify = bcm54xx_link_change_notify,
.suspend = bcm54xx_suspend,
.resume = bcm54xx_resume,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM57780,
.phy_id_mask = 0xfffffff0,
@@ -1060,6 +1200,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCMAC131,
.phy_id_mask = 0xfffffff0,
@@ -1091,6 +1232,7 @@ static struct phy_driver broadcom_drivers[] = {
.get_stats = bcm54xx_get_stats,
.probe = bcm54xx_phy_probe,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM53125,
.phy_id_mask = 0xfffffff0,
@@ -1105,6 +1247,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM53128,
.phy_id_mask = 0xfffffff0,
@@ -1119,6 +1262,7 @@ static struct phy_driver broadcom_drivers[] = {
.config_intr = bcm_phy_config_intr,
.handle_interrupt = bcm_phy_handle_interrupt,
.link_change_notify = bcm54xx_link_change_notify,
+ .led_brightness_set = bcm_phy_led_brightness_set,
}, {
.phy_id = PHY_ID_BCM89610,
.phy_id_mask = 0xfffffff0,
diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
index 9ab5eff502b7..fa8c6fdcf301 100644
--- a/drivers/net/phy/dp83869.c
+++ b/drivers/net/phy/dp83869.c
@@ -692,8 +692,19 @@ static int dp83869_configure_mode(struct phy_device *phydev,
/* Below init sequence for each operational mode is defined in
* section 9.4.8 of the datasheet.
*/
+ phy_ctrl_val = dp83869->mode;
+ if (phydev->interface == PHY_INTERFACE_MODE_MII) {
+ if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
+ dp83869->mode == DP83869_RGMII_100_BASE) {
+ phy_ctrl_val |= DP83869_OP_MODE_MII;
+ } else {
+ phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
+ return -EINVAL;
+ }
+ }
+
ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE,
- dp83869->mode);
+ phy_ctrl_val);
if (ret)
return ret;
diff --git a/drivers/net/phy/dp83td510.c b/drivers/net/phy/dp83td510.c
index 3cd9a77f9532..d7616b13c594 100644
--- a/drivers/net/phy/dp83td510.c
+++ b/drivers/net/phy/dp83td510.c
@@ -12,6 +12,11 @@
/* MDIO_MMD_VEND2 registers */
#define DP83TD510E_PHY_STS 0x10
+/* Bit 7 - mii_interrupt, active high. Clears on read.
+ * Note: Clearing does not necessarily deactivate IRQ pin if interrupts pending.
+ * This differs from the DP83TD510E datasheet (2020) which states this bit
+ * clears on write 0.
+ */
#define DP83TD510E_STS_MII_INT BIT(7)
#define DP83TD510E_LINK_STATUS BIT(0)
@@ -53,12 +58,6 @@ static int dp83td510_config_intr(struct phy_device *phydev)
int ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
- /* Clear any pending interrupts */
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS,
- 0x0);
- if (ret)
- return ret;
-
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
DP83TD510E_INTERRUPT_REG_1,
DP83TD510E_INT1_LINK_EN);
@@ -81,10 +80,6 @@ static int dp83td510_config_intr(struct phy_device *phydev)
DP83TD510E_GENCFG_INT_EN);
if (ret)
return ret;
-
- /* Clear any pending interrupts */
- ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS,
- 0x0);
}
return ret;
@@ -94,14 +89,6 @@ static irqreturn_t dp83td510_handle_interrupt(struct phy_device *phydev)
{
int ret;
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_PHY_STS);
- if (ret < 0) {
- phy_error(phydev);
- return IRQ_NONE;
- } else if (!(ret & DP83TD510E_STS_MII_INT)) {
- return IRQ_NONE;
- }
-
/* Read the current enabled interrupts */
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TD510E_INTERRUPT_REG_1);
if (ret < 0) {
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 55d9d7acc32e..d4bb90d76881 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -328,6 +328,13 @@ static int mv3310_power_up(struct phy_device *phydev)
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
MV_V2_PORT_CTRL_PWRDOWN);
+ /* Sometimes, the power down bit doesn't clear immediately, and
+ * a read of this register causes the bit not to clear. Delay
+ * 100us to allow the PHY to come out of power down mode before
+ * the next access.
+ */
+ udelay(100);
+
if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
priv->firmware_ver < 0x00030000)
return ret;
diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c
new file mode 100644
index 000000000000..95369171a7ba
--- /dev/null
+++ b/drivers/net/phy/mediatek-ge-soc.c
@@ -0,0 +1,1116 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/phy.h>
+
+#define MTK_GPHY_ID_MT7981 0x03a29461
+#define MTK_GPHY_ID_MT7988 0x03a29481
+
+#define MTK_EXT_PAGE_ACCESS 0x1f
+#define MTK_PHY_PAGE_STANDARD 0x0000
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
+
+#define MTK_PHY_LPI_REG_14 0x14
+#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0)
+
+#define MTK_PHY_LPI_REG_1c 0x1c
+#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
+
+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
+
+#define ANALOG_INTERNAL_OPERATION_MAX_US 20
+#define TXRESERVE_MIN 0
+#define TXRESERVE_MAX 7
+
+#define MTK_PHY_ANARG_RG 0x10
+#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8)
+
+/* Registers on MDIO_MMD_VEND1 */
+#define MTK_PHY_TXVLD_DA_RG 0x12
+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16
+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10)
+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17
+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18
+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19
+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20
+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21
+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0)
+
+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22
+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8)
+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0)
+
+#define MTK_PHY_RXADC_CTRL_RG7 0xc6
+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
+
+#define MTK_PHY_RXADC_CTRL_RG9 0xc8
+#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12)
+#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8)
+#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4)
+#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0)
+
+#define MTK_PHY_LDO_OUTPUT_V 0xd7
+
+#define MTK_PHY_RG_ANA_CAL_RG0 0xdb
+#define MTK_PHY_RG_CAL_CKINV BIT(12)
+#define MTK_PHY_RG_ANA_CALEN BIT(8)
+#define MTK_PHY_RG_ZCALEN_A BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG1 0xdc
+#define MTK_PHY_RG_ZCALEN_B BIT(12)
+#define MTK_PHY_RG_ZCALEN_C BIT(8)
+#define MTK_PHY_RG_ZCALEN_D BIT(4)
+#define MTK_PHY_RG_TXVOS_CALEN BIT(0)
+
+#define MTK_PHY_RG_ANA_CAL_RG5 0xe0
+#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8)
+
+#define MTK_PHY_RG_TX_FILTER 0xfe
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120
+#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8)
+#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122
+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0)
+
+#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144
+#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172
+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173
+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8)
+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0)
+
+#define MTK_PHY_RG_AD_CAL_COMP 0x17a
+#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8)
+
+#define MTK_PHY_RG_AD_CAL_CLK 0x17b
+#define MTK_PHY_DA_CAL_CLK BIT(0)
+
+#define MTK_PHY_RG_AD_CALIN 0x17c
+#define MTK_PHY_DA_CALIN_FLAG BIT(0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d
+#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e
+#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f
+#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180
+#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181
+#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182
+#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183
+#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184
+#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0)
+
+#define MTK_PHY_RG_DEV1E_REG19b 0x19b
+#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8)
+
+#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a
+#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b
+#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c
+#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d
+#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e
+#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f
+#define MTK_PHY_RG_LP_IIR2_K4_L 0x230
+#define MTK_PHY_RG_LP_IIR2_K4_U 0x231
+#define MTK_PHY_RG_LP_IIR2_K5_L 0x232
+#define MTK_PHY_RG_LP_IIR2_K5_U 0x233
+
+#define MTK_PHY_RG_DEV1E_REG234 0x234
+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0)
+#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4)
+#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12)
+
+#define MTK_PHY_RG_LPF_CNT_VAL 0x235
+
+#define MTK_PHY_RG_DEV1E_REG238 0x238
+#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG239 0x239
+#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0)
+#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12)
+
+#define MTK_PHY_RG_DEV1E_REG27C 0x27c
+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8)
+#define MTK_PHY_RG_DEV1E_REG27D 0x27d
+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0)
+
+#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7
+#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
+#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
+
+#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1
+#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0)
+#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8)
+#define MTK_PHY_LPI_TR_READY BIT(9)
+#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10)
+
+#define MTK_PHY_RG_DEV1E_REG323 0x323
+#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0)
+#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4)
+
+#define MTK_PHY_RG_DEV1E_REG324 0x324
+#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0)
+#define MTK_PHY_SMI_DET_MAX_EN BIT(8)
+
+#define MTK_PHY_RG_DEV1E_REG326 0x326
+#define MTK_PHY_LPI_MODE_SD_ON BIT(0)
+#define MTK_PHY_RESET_RANDUPD_CNT BIT(1)
+#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2)
+#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4)
+#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5)
+
+#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502
+#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503
+
+#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d
+#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e
+#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f
+#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
+
+#define MTK_PHY_RG_BG_RASEL 0x115
+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
+
+/* These macro privides efuse parsing for internal phy. */
+#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0))
+#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0))
+
+#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0))
+#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0))
+
+#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0))
+#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0))
+
+enum {
+ NO_PAIR,
+ PAIR_A,
+ PAIR_B,
+ PAIR_C,
+ PAIR_D,
+};
+
+enum {
+ GPHY_PORT0,
+ GPHY_PORT1,
+ GPHY_PORT2,
+ GPHY_PORT3,
+};
+
+enum calibration_mode {
+ EFUSE_K,
+ SW_K
+};
+
+enum CAL_ITEM {
+ REXT,
+ TX_OFFSET,
+ TX_AMP,
+ TX_R50,
+ TX_VCM
+};
+
+enum CAL_MODE {
+ EFUSE_M,
+ SW_M
+};
+
+static int mtk_socphy_read_page(struct phy_device *phydev)
+{
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+}
+
+static int mtk_socphy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
+}
+
+/* One calibration cycle consists of:
+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
+ * until AD_CAL_COMP is ready to output calibration result.
+ * 2.Wait until DA_CAL_CLK is available.
+ * 3.Fetch AD_CAL_COMP_OUT.
+ */
+static int cal_cycle(struct phy_device *phydev, int devad,
+ u32 regnum, u16 mask, u16 cal_val)
+{
+ int reg_val;
+ int ret;
+
+ phy_modify_mmd(phydev, devad, regnum,
+ mask, cal_val);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+
+ ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_AD_CAL_CLK, reg_val,
+ reg_val & MTK_PHY_DA_CAL_CLK, 500,
+ ANALOG_INTERNAL_OPERATION_MAX_US, false);
+ if (ret) {
+ phydev_err(phydev, "Calibration cycle timeout\n");
+ return ret;
+ }
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
+ MTK_PHY_DA_CALIN_FLAG);
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
+ phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
+
+ return ret;
+}
+
+static int rext_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5,
+ MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL,
+ MTK_PHY_RG_BG_RASEL_MASK, buf[1]);
+
+ return 0;
+}
+
+static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 rext_cal_val[2];
+
+ rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]);
+ rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]);
+ rext_fill_result(phydev, rext_cal_val);
+
+ return 0;
+}
+
+static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B,
+ MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D,
+ MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]);
+
+ return 0;
+}
+
+static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_offset_cal_val[4];
+
+ tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]);
+ tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]);
+ tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]);
+ tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]);
+
+ tx_offset_fill_result(phydev, tx_offset_cal_val);
+
+ return 0;
+}
+
+static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
+{
+ int i;
+ int bias[16] = {};
+ const int vals_9461[16] = { 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7,
+ 7, 1, 4, 7 };
+ const int vals_9481[16] = { 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10,
+ 10, 6, 6, 10 };
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ /* We add some calibration to efuse values
+ * due to board level influence.
+ * GBE: +7, TBT: +1, HBT: +4, TST: +7
+ */
+ memcpy(bias, (const void *)vals_9461, sizeof(bias));
+ break;
+ case MTK_GPHY_ID_MT7988:
+ memcpy(bias, (const void *)vals_9481, sizeof(bias));
+ break;
+ }
+
+ /* Prevent overflow */
+ for (i = 0; i < 12; i++) {
+ if (buf[i >> 2] + bias[i] > 63) {
+ buf[i >> 2] = 63;
+ bias[i] = 0;
+ }
+ }
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
+
+ return 0;
+}
+
+static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
+{
+ u16 tx_amp_cal_val[4];
+
+ tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]);
+ tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]);
+ tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]);
+ tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]);
+ tx_amp_fill_result(phydev, tx_amp_cal_val);
+
+ return 0;
+}
+
+static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
+ u8 txg_calen_x)
+{
+ int bias = 0;
+ u16 reg, val;
+
+ if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988)
+ bias = -2;
+
+ val = clamp_val(bias + tx_r50_cal_val, 0, 63);
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ reg = MTK_PHY_DA_TX_R50_PAIR_A;
+ break;
+ case PAIR_B:
+ reg = MTK_PHY_DA_TX_R50_PAIR_B;
+ break;
+ case PAIR_C:
+ reg = MTK_PHY_DA_TX_R50_PAIR_C;
+ break;
+ case PAIR_D:
+ reg = MTK_PHY_DA_TX_R50_PAIR_D;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8);
+
+ return 0;
+}
+
+static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
+ u8 txg_calen_x)
+{
+ u16 tx_r50_cal_val;
+
+ switch (txg_calen_x) {
+ case PAIR_A:
+ tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]);
+ break;
+ case PAIR_B:
+ tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]);
+ break;
+ case PAIR_C:
+ tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]);
+ break;
+ case PAIR_D:
+ tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x);
+
+ return 0;
+}
+
+static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
+{
+ u8 lower_idx, upper_idx, txreserve_val;
+ u8 lower_ret, upper_ret;
+ int ret;
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_CAL_CKINV);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+
+ switch (rg_txreserve_x) {
+ case PAIR_A:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_A,
+ MTK_PHY_DASN_DAC_IN0_A_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_A,
+ MTK_PHY_DASN_DAC_IN1_A_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ break;
+ case PAIR_B:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_B,
+ MTK_PHY_DASN_DAC_IN0_B_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_B,
+ MTK_PHY_DASN_DAC_IN1_B_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B);
+ break;
+ case PAIR_C:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_C,
+ MTK_PHY_DASN_DAC_IN0_C_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_C,
+ MTK_PHY_DASN_DAC_IN1_C_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_C);
+ break;
+ case PAIR_D:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN0_D,
+ MTK_PHY_DASN_DAC_IN0_D_MASK);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DASN_DAC_IN1_D,
+ MTK_PHY_DASN_DAC_IN1_D_MASK);
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_D);
+ break;
+ default:
+ ret = -EINVAL;
+ goto restore;
+ }
+
+ lower_idx = TXRESERVE_MIN;
+ upper_idx = TXRESERVE_MAX;
+
+ phydev_dbg(phydev, "Start TX-VCM SW cal.\n");
+ while ((upper_idx - lower_idx) > 1) {
+ txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2);
+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ txreserve_val << 12 | txreserve_val << 8 |
+ txreserve_val << 4 | txreserve_val);
+ if (ret == 1) {
+ upper_idx = txreserve_val;
+ upper_ret = ret;
+ } else if (ret == 0) {
+ lower_idx = txreserve_val;
+ lower_ret = ret;
+ } else {
+ goto restore;
+ }
+ }
+
+ if (lower_idx == TXRESERVE_MIN) {
+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ ret = lower_ret;
+ } else if (upper_idx == TXRESERVE_MAX) {
+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ ret = upper_ret;
+ }
+ if (ret < 0)
+ goto restore;
+
+ /* We calibrate TX-VCM in different logic. Check upper index and then
+ * lower index. If this calibration is valid, apply lower index's result.
+ */
+ ret = upper_ret - lower_ret;
+ if (ret == 1) {
+ ret = 0;
+ /* Make sure we use upper_idx in our calibration system */
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ upper_idx << 12 | upper_idx << 8 |
+ upper_idx << 4 | upper_idx);
+ phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx);
+ } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 &&
+ lower_ret == 1) {
+ ret = 0;
+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9,
+ MTK_PHY_DA_RX_PSBN_TBT_MASK |
+ MTK_PHY_DA_RX_PSBN_HBT_MASK |
+ MTK_PHY_DA_RX_PSBN_GBE_MASK |
+ MTK_PHY_DA_RX_PSBN_LP_MASK,
+ lower_idx << 12 | lower_idx << 8 |
+ lower_idx << 4 | lower_idx);
+ phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n",
+ lower_idx);
+ } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
+ lower_ret == 0) {
+ ret = 0;
+ phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
+ upper_idx);
+ } else {
+ ret = -EINVAL;
+ }
+
+restore:
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ANA_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_TXVOS_CALEN);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0,
+ MTK_PHY_RG_ZCALEN_A);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1,
+ MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C |
+ MTK_PHY_RG_ZCALEN_D);
+
+ return ret;
+}
+
+static void mt798x_phy_common_finetune(struct phy_device *phydev)
+{
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* EnabRandUpdTrig = 1 */
+ __phy_write(phydev, 0x11, 0x2f00);
+ __phy_write(phydev, 0x12, 0xe);
+ __phy_write(phydev, 0x10, 0x8fb0);
+
+ /* NormMseLoThresh = 85 */
+ __phy_write(phydev, 0x11, 0x55a0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x83aa);
+
+ /* TrFreeze = 0 */
+ __phy_write(phydev, 0x11, 0x0);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9686);
+
+ /* SSTrKp1000Slv = 5 */
+ __phy_write(phydev, 0x11, 0xbaef);
+ __phy_write(phydev, 0x12, 0x2e);
+ __phy_write(phydev, 0x10, 0x968c);
+
+ /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
+ * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
+ */
+ __phy_write(phydev, 0x11, 0xd10a);
+ __phy_write(phydev, 0x12, 0x34);
+ __phy_write(phydev, 0x10, 0x8f82);
+
+ /* VcoSlicerThreshBitsHigh */
+ __phy_write(phydev, 0x11, 0x5555);
+ __phy_write(phydev, 0x12, 0x55);
+ __phy_write(phydev, 0x10, 0x8ec0);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
+
+ /* rg_tr_lpf_cnt_val = 512 */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200);
+
+ /* IIR2 related */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe);
+
+ /* FFE peaking */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C,
+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8);
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D,
+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e);
+
+ /* Disable LDO pump */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0);
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0);
+ /* Adjust LDO output voltage */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222);
+}
+
+static void mt7981_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[8] = { 0x01ce, 0x01c1,
+ 0x020f, 0x0202,
+ 0x03d0, 0x03c0,
+ 0x0013, 0x0005 };
+ int i, k;
+
+ /* 100M eye finetune:
+ * Keep middle level of TX MLT3 shapper as default.
+ * Only change TX MLT3 overshoot level here.
+ */
+ for (k = 0, i = 1; i < 12; i++) {
+ if (i % 3 == 0)
+ continue;
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]);
+ }
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
+ __phy_write(phydev, 0x11, 0xc71);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 6 */
+ __phy_write(phydev, 0x11, 0x600);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate = 1 */
+ __phy_write(phydev, 0x11, 0x4c2a);
+ __phy_write(phydev, 0x12, 0x3e);
+ __phy_write(phydev, 0x10, 0x8fa4);
+
+ /* FfeUpdGainForce = 4 */
+ __phy_write(phydev, 0x11, 0x240);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9680);
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt7988_phy_finetune(struct phy_device *phydev)
+{
+ u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182,
+ 0x020d, 0x0206, 0x0384, 0x03d0,
+ 0x03c6, 0x030a, 0x0011, 0x0005 };
+ int i;
+
+ /* Set default MLT3 shaper first */
+ for (i = 0; i < 12; i++)
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
+
+ /* TCT finetune */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
+
+ /* Disable TX power saving */
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+
+ /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */
+ __phy_write(phydev, 0x11, 0x671);
+ __phy_write(phydev, 0x12, 0xc);
+ __phy_write(phydev, 0x10, 0x8fae);
+
+ /* ResetSyncOffset = 5 */
+ __phy_write(phydev, 0x11, 0x500);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8fc0);
+
+ /* VgaDecRate is 1 at default on mt7988 */
+
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30);
+ /* TxClkOffset = 2 */
+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK,
+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+}
+
+static void mt798x_phy_eee(struct phy_device *phydev)
+{
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120,
+ MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK |
+ MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) |
+ FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ 0xff));
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_TESTMUX_ADC_CTRL,
+ MTK_PHY_RG_TXEN_DIG_MASK);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY);
+
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238,
+ MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK |
+ MTK_PHY_LPI_SLV_SEND_TX_EN,
+ FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239,
+ MTK_PHY_LPI_SEND_LOC_TIMER_MASK |
+ MTK_PHY_LPI_TXPCS_LOC_RCV,
+ FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
+ MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK,
+ FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
+ FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1,
+ MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK,
+ 0x33) |
+ MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY |
+ MTK_PHY_LPI_VCO_EEE_STG0_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323,
+ MTK_PHY_EEE_WAKE_MAS_INT_DC |
+ MTK_PHY_EEE_WAKE_SLV_INT_DC);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324,
+ MTK_PHY_SMI_DETCNT_MAX_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) |
+ MTK_PHY_SMI_DET_MAX_EN);
+
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326,
+ MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT |
+ MTK_PHY_TREC_UPDATE_ENAB_CLR |
+ MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF |
+ MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
+ /* Regsigdet_sel_1000 = 0 */
+ __phy_write(phydev, 0x11, 0xb);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x9690);
+
+ /* REG_EEE_st2TrKf1000 = 3 */
+ __phy_write(phydev, 0x11, 0x114f);
+ __phy_write(phydev, 0x12, 0x2);
+ __phy_write(phydev, 0x10, 0x969a);
+
+ /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
+ __phy_write(phydev, 0x11, 0x3028);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x969e);
+
+ /* RegEEE_slv_wake_int_timer_tar = 8 */
+ __phy_write(phydev, 0x11, 0x5010);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a0);
+
+ /* RegEEE_trfreeze_timer2 = 586 */
+ __phy_write(phydev, 0x11, 0x24a);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96a8);
+
+ /* RegEEE100Stg1_tar = 16 */
+ __phy_write(phydev, 0x11, 0x3210);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96b8);
+
+ /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */
+ __phy_write(phydev, 0x11, 0x1463);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x96ca);
+
+ /* DfeTailEnableVgaThresh1000 = 27 */
+ __phy_write(phydev, 0x11, 0x36);
+ __phy_write(phydev, 0x12, 0x0);
+ __phy_write(phydev, 0x10, 0x8f80);
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
+
+ __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
+ FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc));
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
+
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
+}
+
+static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_OFFSET & TX_AMP have no SW calibration. */
+ switch (cal_item) {
+ case TX_VCM:
+ ret = tx_vcm_cal_sw(phydev, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ u8 start_pair, u8 end_pair, u32 *buf)
+{
+ u8 pair_n;
+ int ret;
+
+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) {
+ /* TX_VCM has no efuse calibration. */
+ switch (cal_item) {
+ case REXT:
+ ret = rext_cal_efuse(phydev, buf);
+ break;
+ case TX_OFFSET:
+ ret = tx_offset_cal_efuse(phydev, buf);
+ break;
+ case TX_AMP:
+ ret = tx_amp_cal_efuse(phydev, buf);
+ break;
+ case TX_R50:
+ ret = tx_r50_cal_efuse(phydev, buf, pair_n);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
+ enum CAL_MODE cal_mode, u8 start_pair,
+ u8 end_pair, u32 *buf)
+{
+ int ret;
+
+ switch (cal_mode) {
+ case EFUSE_M:
+ ret = cal_efuse(phydev, cal_item, start_pair,
+ end_pair, buf);
+ break;
+ case SW_M:
+ ret = cal_sw(phydev, cal_item, start_pair, end_pair);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret) {
+ phydev_err(phydev, "cal %d failed\n", cal_item);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mt798x_phy_calibration(struct phy_device *phydev)
+{
+ int ret = 0;
+ u32 *buf;
+ size_t len;
+ struct nvmem_cell *cell;
+
+ cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
+ if (IS_ERR(cell)) {
+ if (PTR_ERR(cell) == -EPROBE_DEFER)
+ return PTR_ERR(cell);
+ return 0;
+ }
+
+ buf = (u32 *)nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ nvmem_cell_put(cell);
+
+ if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
+ phydev_err(phydev, "invalid efuse data\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf);
+ if (ret)
+ goto out;
+ ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf);
+ if (ret)
+ goto out;
+
+out:
+ kfree(buf);
+ return ret;
+}
+
+static int mt798x_phy_config_init(struct phy_device *phydev)
+{
+ switch (phydev->drv->phy_id) {
+ case MTK_GPHY_ID_MT7981:
+ mt7981_phy_finetune(phydev);
+ break;
+ case MTK_GPHY_ID_MT7988:
+ mt7988_phy_finetune(phydev);
+ break;
+ }
+
+ mt798x_phy_common_finetune(phydev);
+ mt798x_phy_eee(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static struct phy_driver mtk_socphy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+ .name = "MediaTek MT7981 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+ .probe = mt798x_phy_calibration,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
+ .name = "MediaTek MT7988 PHY",
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+ .probe = mt798x_phy_calibration,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,
+ .write_page = mtk_socphy_write_page,
+ },
+};
+
+module_phy_driver(mtk_socphy_driver);
+
+static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
+ { }
+};
+
+MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);
diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek-ge.c
index 68ee434f9dea..a493ae01b267 100644
--- a/drivers/net/phy/mediatek-ge.c
+++ b/drivers/net/phy/mediatek-ge.c
@@ -102,7 +102,8 @@ static struct phy_driver mtk_gephy_driver[] = {
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
- { PHY_ID_MATCH_VENDOR(0x03a29400) },
+ { PHY_ID_MATCH_EXACT(0x03a29441) },
+ { PHY_ID_MATCH_EXACT(0x03a29412) },
{ }
};
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 3f81bb8dac44..927d3d54658e 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -252,6 +252,9 @@
#define PS_TO_REG 200
#define FIFO_SIZE 8
+/* Delay used to get the second part from the LTC */
+#define LAN8841_GET_SEC_LTC_DELAY (500 * NSEC_PER_MSEC)
+
struct kszphy_hw_stat {
const char *string;
u8 reg;
@@ -319,6 +322,10 @@ struct kszphy_ptp_priv {
/* Lock for ptp_clock */
struct mutex ptp_lock;
struct ptp_pin_desc *pin_config;
+
+ s64 seconds;
+ /* Lock for accessing seconds */
+ spinlock_t seconds_lock;
};
struct kszphy_priv {
@@ -637,7 +644,7 @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
{
int ret;
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051)
+ if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK))
return 0;
ret = phy_read(phydev, MII_BMSR);
@@ -1566,7 +1573,7 @@ static int ksz9x31_cable_test_fault_length(struct phy_device *phydev, u16 stat)
*
* distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity
*/
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131)
+ if (phydev_id_compare(phydev, PHY_ID_KSZ9131))
dt = clamp(dt - 22, 0, 255);
return (dt * 400) / 10;
@@ -1774,6 +1781,82 @@ static int ksz886x_read_status(struct phy_device *phydev)
return genphy_read_status(phydev);
}
+struct ksz9477_errata_write {
+ u8 dev_addr;
+ u8 reg_addr;
+ u16 val;
+};
+
+static const struct ksz9477_errata_write ksz9477_errata_writes[] = {
+ /* Register settings are needed to improve PHY receive performance */
+ {0x01, 0x6f, 0xdd0b},
+ {0x01, 0x8f, 0x6032},
+ {0x01, 0x9d, 0x248c},
+ {0x01, 0x75, 0x0060},
+ {0x01, 0xd3, 0x7777},
+ {0x1c, 0x06, 0x3008},
+ {0x1c, 0x08, 0x2000},
+
+ /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
+ {0x1c, 0x04, 0x00d0},
+
+ /* Register settings are required to meet data sheet supply current specifications */
+ {0x1c, 0x13, 0x6eff},
+ {0x1c, 0x14, 0xe6ff},
+ {0x1c, 0x15, 0x6eff},
+ {0x1c, 0x16, 0xe6ff},
+ {0x1c, 0x17, 0x00ff},
+ {0x1c, 0x18, 0x43ff},
+ {0x1c, 0x19, 0xc3ff},
+ {0x1c, 0x1a, 0x6fff},
+ {0x1c, 0x1b, 0x07ff},
+ {0x1c, 0x1c, 0x0fff},
+ {0x1c, 0x1d, 0xe7ff},
+ {0x1c, 0x1e, 0xefff},
+ {0x1c, 0x20, 0xeeee},
+};
+
+static int ksz9477_config_init(struct phy_device *phydev)
+{
+ int err;
+ int i;
+
+ /* Apply PHY settings to address errata listed in
+ * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
+ * Silicon Errata and Data Sheet Clarification documents.
+ *
+ * Document notes: Before configuring the PHY MMD registers, it is
+ * necessary to set the PHY to 100 Mbps speed with auto-negotiation
+ * disabled by writing to register 0xN100-0xN101. After writing the
+ * MMD registers, and after all errata workarounds that involve PHY
+ * register settings, write register 0xN100-0xN101 again to enable
+ * and restart auto-negotiation.
+ */
+ err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) {
+ const struct ksz9477_errata_write *errata = &ksz9477_errata_writes[i];
+
+ err = phy_write_mmd(phydev, errata->dev_addr, errata->reg_addr, errata->val);
+ if (err)
+ return err;
+ }
+
+ /* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes
+ * in this switch shall be regarded as broken.
+ */
+ if (phydev->dev_flags & MICREL_NO_EEE)
+ phydev->eee_broken_modes = -1;
+
+ err = genphy_restart_aneg(phydev);
+ if (err)
+ return err;
+
+ return kszphy_config_init(phydev);
+}
+
static int kszphy_get_sset_count(struct phy_device *phydev)
{
return ARRAY_SIZE(kszphy_hw_stats);
@@ -1998,7 +2081,7 @@ static __always_inline int ksz886x_cable_test_fault_length(struct phy_device *ph
*/
dt = FIELD_GET(data_mask, status);
- if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814)
+ if (phydev_id_compare(phydev, PHY_ID_LAN8814))
return ((dt - 22) * 800) / 10;
else
return (dt * 400) / 10;
@@ -3238,6 +3321,9 @@ static int lan8814_probe(struct phy_device *phydev)
#define LAN8841_PTP_CMD_CTL_PTP_RESET BIT(0)
#define LAN8841_PTP_RX_PARSE_CONFIG 368
#define LAN8841_PTP_TX_PARSE_CONFIG 432
+#define LAN8841_PTP_RX_MODE 381
+#define LAN8841_PTP_INSERT_TS_EN BIT(0)
+#define LAN8841_PTP_INSERT_TS_32BIT BIT(1)
static int lan8841_config_init(struct phy_device *phydev)
{
@@ -3386,68 +3472,18 @@ static void lan8841_ptp_process_tx_ts(struct kszphy_ptp_priv *ptp_priv)
lan8814_match_tx_skb(ptp_priv, sec, nsec, seq);
}
-#define LAN8841_PTP_RX_INGRESS_SEC_LO 389
-#define LAN8841_PTP_RX_INGRESS_SEC_HI 388
-#define LAN8841_PTP_RX_INGRESS_NS_LO 387
-#define LAN8841_PTP_RX_INGRESS_NS_HI 386
-#define LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID BIT(15)
-#define LAN8841_PTP_RX_MSG_HEADER2 391
-
-static struct lan8814_ptp_rx_ts *lan8841_ptp_get_rx_ts(struct kszphy_ptp_priv *ptp_priv)
-{
- struct phy_device *phydev = ptp_priv->phydev;
- struct lan8814_ptp_rx_ts *rx_ts;
- u32 sec, nsec;
- u16 seq;
-
- nsec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_HI);
- if (!(nsec & LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID))
- return NULL;
-
- nsec = ((nsec & 0x3fff) << 16);
- nsec = nsec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_LO);
-
- sec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_HI);
- sec = sec << 16;
- sec = sec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_LO);
-
- seq = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_MSG_HEADER2);
-
- rx_ts = kzalloc(sizeof(*rx_ts), GFP_KERNEL);
- if (!rx_ts)
- return NULL;
-
- rx_ts->seconds = sec;
- rx_ts->nsec = nsec;
- rx_ts->seq_id = seq;
-
- return rx_ts;
-}
-
-static void lan8841_ptp_process_rx_ts(struct kszphy_ptp_priv *ptp_priv)
-{
- struct lan8814_ptp_rx_ts *rx_ts;
-
- while ((rx_ts = lan8841_ptp_get_rx_ts(ptp_priv)) != NULL)
- lan8814_match_rx_ts(ptp_priv, rx_ts);
-}
-
#define LAN8841_PTP_INT_STS 259
#define LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT BIT(13)
#define LAN8841_PTP_INT_STS_PTP_TX_TS_INT BIT(12)
-#define LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT BIT(9)
-#define LAN8841_PTP_INT_STS_PTP_RX_TS_INT BIT(8)
#define LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT BIT(2)
-static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv, bool egress)
+static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv)
{
struct phy_device *phydev = ptp_priv->phydev;
int i;
for (i = 0; i < FIFO_SIZE; ++i)
- phy_read_mmd(phydev, 2,
- egress ? LAN8841_PTP_TX_MSG_HEADER2 :
- LAN8841_PTP_RX_MSG_HEADER2);
+ phy_read_mmd(phydev, 2, LAN8841_PTP_TX_MSG_HEADER2);
phy_read_mmd(phydev, 2, LAN8841_PTP_INT_STS);
}
@@ -3525,23 +3561,17 @@ static void lan8841_handle_ptp_interrupt(struct phy_device *phydev)
if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_INT)
lan8841_ptp_process_tx_ts(ptp_priv);
- if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_INT)
- lan8841_ptp_process_rx_ts(ptp_priv);
-
if (status & LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT)
lan8841_gpio_process_cap(ptp_priv);
if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT) {
- lan8841_ptp_flush_fifo(ptp_priv, true);
+ lan8841_ptp_flush_fifo(ptp_priv);
skb_queue_purge(&ptp_priv->tx_queue);
}
- if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT) {
- lan8841_ptp_flush_fifo(ptp_priv, false);
- skb_queue_purge(&ptp_priv->rx_queue);
- }
-
- } while (status);
+ } while (status & (LAN8841_PTP_INT_STS_PTP_TX_TS_INT |
+ LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT |
+ LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT));
}
#define LAN8841_INTS_PTP BIT(9)
@@ -3605,32 +3635,46 @@ static int lan8841_ts_info(struct mii_timestamper *mii_ts,
#define LAN8841_PTP_INT_EN 260
#define LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN BIT(13)
#define LAN8841_PTP_INT_EN_PTP_TX_TS_EN BIT(12)
-#define LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN BIT(9)
-#define LAN8841_PTP_INT_EN_PTP_RX_TS_EN BIT(8)
-static void lan8841_ptp_enable_int(struct kszphy_ptp_priv *ptp_priv,
- bool enable)
+static void lan8841_ptp_enable_processing(struct kszphy_ptp_priv *ptp_priv,
+ bool enable)
{
struct phy_device *phydev = ptp_priv->phydev;
- if (enable)
- /* Enable interrupts */
+ if (enable) {
+ /* Enable interrupts on the TX side */
phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN,
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN);
- else
- /* Disable interrupts */
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN);
+
+ /* Enable the modification of the frame on RX side,
+ * this will add the ns and 2 bits of sec in the reserved field
+ * of the PTP header
+ */
+ phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ LAN8841_PTP_RX_MODE,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT);
+
+ ptp_schedule_worker(ptp_priv->ptp_clock, 0);
+ } else {
+ /* Disable interrupts on the TX side */
phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN,
LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN |
- LAN8841_PTP_INT_EN_PTP_TX_TS_EN |
- LAN8841_PTP_INT_EN_PTP_RX_TS_EN, 0);
+ LAN8841_PTP_INT_EN_PTP_TX_TS_EN, 0);
+
+ /* Disable modification of the RX frames */
+ phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG,
+ LAN8841_PTP_RX_MODE,
+ LAN8841_PTP_INSERT_TS_EN |
+ LAN8841_PTP_INSERT_TS_32BIT, 0);
+
+ ptp_cancel_worker_sync(ptp_priv->ptp_clock);
+ }
}
#define LAN8841_PTP_RX_TIMESTAMP_EN 379
@@ -3641,7 +3685,6 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
{
struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts);
struct phy_device *phydev = ptp_priv->phydev;
- struct lan8814_ptp_rx_ts *rx_ts, *tmp;
struct hwtstamp_config config;
int txcfg = 0, rxcfg = 0;
int pkt_ts_enable;
@@ -3705,24 +3748,61 @@ static int lan8841_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ : 0);
/* Now enable/disable the timestamping */
- lan8841_ptp_enable_int(ptp_priv,
- config.rx_filter != HWTSTAMP_FILTER_NONE);
+ lan8841_ptp_enable_processing(ptp_priv,
+ config.rx_filter != HWTSTAMP_FILTER_NONE);
- /* In case of multiple starts and stops, these needs to be cleared */
- list_for_each_entry_safe(rx_ts, tmp, &ptp_priv->rx_ts_list, list) {
- list_del(&rx_ts->list);
- kfree(rx_ts);
- }
-
- skb_queue_purge(&ptp_priv->rx_queue);
skb_queue_purge(&ptp_priv->tx_queue);
- lan8841_ptp_flush_fifo(ptp_priv, false);
- lan8841_ptp_flush_fifo(ptp_priv, true);
+ lan8841_ptp_flush_fifo(ptp_priv);
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
}
+static bool lan8841_rxtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct kszphy_ptp_priv *ptp_priv =
+ container_of(mii_ts, struct kszphy_ptp_priv, mii_ts);
+ struct ptp_header *header = ptp_parse_header(skb, type);
+ struct skb_shared_hwtstamps *shhwtstamps;
+ struct timespec64 ts;
+ unsigned long flags;
+ u32 ts_header;
+
+ if (!header)
+ return false;
+
+ if (ptp_priv->rx_filter == HWTSTAMP_FILTER_NONE ||
+ type == PTP_CLASS_NONE)
+ return false;
+
+ if ((type & ptp_priv->version) == 0 || (type & ptp_priv->layer) == 0)
+ return false;
+
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ts.tv_sec = ptp_priv->seconds;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+ ts_header = __be32_to_cpu(header->reserved2);
+
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+ /* Check for any wrap arounds for the second part */
+ if ((ts.tv_sec & GENMASK(1, 0)) == 0 && (ts_header >> 30) == 3)
+ ts.tv_sec -= GENMASK(1, 0) + 1;
+ else if ((ts.tv_sec & GENMASK(1, 0)) == 3 && (ts_header >> 30) == 0)
+ ts.tv_sec += 1;
+
+ shhwtstamps->hwtstamp =
+ ktime_set((ts.tv_sec & ~(GENMASK(1, 0))) | ts_header >> 30,
+ ts_header & GENMASK(29, 0));
+ header->reserved2 = 0;
+
+ netif_rx(skb);
+
+ return true;
+}
+
#define LAN8841_EVENT_A 0
#define LAN8841_EVENT_B 1
#define LAN8841_PTP_LTC_TARGET_SEC_HI(event) ((event) == LAN8841_EVENT_A ? 278 : 288)
@@ -3807,6 +3887,7 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp,
struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
ptp_clock_info);
struct phy_device *phydev = ptp_priv->phydev;
+ unsigned long flags;
int ret;
/* Set the value to be stored */
@@ -3823,6 +3904,10 @@ static int lan8841_ptp_settime64(struct ptp_clock_info *ptp,
ret = lan8841_ptp_update_target(ptp_priv, ts);
mutex_unlock(&ptp_priv->ptp_lock);
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ptp_priv->seconds = ts->tv_sec;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+
return ret;
}
@@ -3863,6 +3948,30 @@ static int lan8841_ptp_gettime64(struct ptp_clock_info *ptp,
return 0;
}
+static void lan8841_ptp_getseconds(struct ptp_clock_info *ptp,
+ struct timespec64 *ts)
+{
+ struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
+ ptp_clock_info);
+ struct phy_device *phydev = ptp_priv->phydev;
+ time64_t s;
+
+ mutex_lock(&ptp_priv->ptp_lock);
+ /* Issue the command to read the LTC */
+ phy_write_mmd(phydev, 2, LAN8841_PTP_CMD_CTL,
+ LAN8841_PTP_CMD_CTL_PTP_LTC_READ);
+
+ /* Read the LTC */
+ s = phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_HI);
+ s <<= 16;
+ s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_MID);
+ s <<= 16;
+ s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_LO);
+ mutex_unlock(&ptp_priv->ptp_lock);
+
+ set_normalized_timespec64(ts, s, 0);
+}
+
#define LAN8841_PTP_LTC_STEP_ADJ_LO 276
#define LAN8841_PTP_LTC_STEP_ADJ_HI 275
#define LAN8841_PTP_LTC_STEP_ADJ_DIR BIT(15)
@@ -4365,6 +4474,22 @@ static int lan8841_ptp_enable(struct ptp_clock_info *ptp,
return 0;
}
+static long lan8841_ptp_do_aux_work(struct ptp_clock_info *ptp)
+{
+ struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv,
+ ptp_clock_info);
+ struct timespec64 ts;
+ unsigned long flags;
+
+ lan8841_ptp_getseconds(&ptp_priv->ptp_clock_info, &ts);
+
+ spin_lock_irqsave(&ptp_priv->seconds_lock, flags);
+ ptp_priv->seconds = ts.tv_sec;
+ spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags);
+
+ return nsecs_to_jiffies(LAN8841_GET_SEC_LTC_DELAY);
+}
+
static struct ptp_clock_info lan8841_ptp_clock_info = {
.owner = THIS_MODULE,
.name = "lan8841 ptp",
@@ -4375,6 +4500,7 @@ static struct ptp_clock_info lan8841_ptp_clock_info = {
.adjfine = lan8841_ptp_adjfine,
.verify = lan8841_ptp_verify,
.enable = lan8841_ptp_enable,
+ .do_aux_work = lan8841_ptp_do_aux_work,
.n_per_out = LAN8841_PTP_GPIO_NUM,
.n_ext_ts = LAN8841_PTP_GPIO_NUM,
.n_pins = LAN8841_PTP_GPIO_NUM,
@@ -4435,13 +4561,11 @@ static int lan8841_probe(struct phy_device *phydev)
/* Initialize the SW */
skb_queue_head_init(&ptp_priv->tx_queue);
- skb_queue_head_init(&ptp_priv->rx_queue);
- INIT_LIST_HEAD(&ptp_priv->rx_ts_list);
- spin_lock_init(&ptp_priv->rx_ts_lock);
ptp_priv->phydev = phydev;
mutex_init(&ptp_priv->ptp_lock);
+ spin_lock_init(&ptp_priv->seconds_lock);
- ptp_priv->mii_ts.rxtstamp = lan8814_rxtstamp;
+ ptp_priv->mii_ts.rxtstamp = lan8841_rxtstamp;
ptp_priv->mii_ts.txtstamp = lan8814_txtstamp;
ptp_priv->mii_ts.hwtstamp = lan8841_hwtstamp;
ptp_priv->mii_ts.ts_info = lan8841_ts_info;
@@ -4451,6 +4575,16 @@ static int lan8841_probe(struct phy_device *phydev)
return 0;
}
+static int lan8841_suspend(struct phy_device *phydev)
+{
+ struct kszphy_priv *priv = phydev->priv;
+ struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv;
+
+ ptp_cancel_worker_sync(ptp_priv->ptp_clock);
+
+ return genphy_suspend(phydev);
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -4674,7 +4808,7 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
- .suspend = genphy_suspend,
+ .suspend = lan8841_suspend,
.resume = genphy_resume,
.cable_test_start = lan8814_cable_test_start,
.cable_test_get_status = ksz886x_cable_test_get_status,
@@ -4735,7 +4869,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip KSZ9477",
/* PHY_GBIT_FEATURES */
- .config_init = kszphy_config_init,
+ .config_init = ksz9477_config_init,
.config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt,
.suspend = genphy_suspend,
diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c
index 094967b3c111..534ca7d1b061 100644
--- a/drivers/net/phy/microchip_t1s.c
+++ b/drivers/net/phy/microchip_t1s.c
@@ -1,19 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Driver for Microchip 10BASE-T1S LAN867X PHY
+ * Driver for Microchip 10BASE-T1S PHYs
*
* Support: Microchip Phys:
- * lan8670, lan8671, lan8672
+ * lan8670/1/2 Rev.B1
+ * lan8650/1 Rev.B0 Internal PHYs
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy.h>
-#define PHY_ID_LAN867X 0x0007C160
+#define PHY_ID_LAN867X_REVB1 0x0007C162
+#define PHY_ID_LAN865X_REVB0 0x0007C1B3
-#define LAN867X_REG_IRQ_1_CTL 0x001C
-#define LAN867X_REG_IRQ_2_CTL 0x001D
+#define LAN867X_REG_STS2 0x0019
+
+#define LAN867x_RESET_COMPLETE_STS BIT(11)
+
+#define LAN865X_REG_CFGPARAM_ADDR 0x00D8
+#define LAN865X_REG_CFGPARAM_DATA 0x00D9
+#define LAN865X_REG_CFGPARAM_CTRL 0x00DA
+#define LAN865X_REG_STS2 0x0019
+
+#define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
/* The arrays below are pulled from the following table from AN1699
* Access MMD Address Value Mask
@@ -31,72 +41,219 @@
* W 0x1F 0x0099 0x7F80 ------
*/
-static const int lan867x_fixup_registers[12] = {
+static const u32 lan867x_revb1_fixup_registers[12] = {
0x00D0, 0x00D1, 0x0084, 0x0085,
0x008A, 0x0087, 0x0088, 0x008B,
0x0080, 0x00F1, 0x0096, 0x0099,
};
-static const int lan867x_fixup_values[12] = {
+static const u16 lan867x_revb1_fixup_values[12] = {
0x0002, 0x0000, 0x3380, 0x0006,
0xC000, 0x801C, 0x033F, 0x0404,
0x0600, 0x2400, 0x2000, 0x7F80,
};
-static const int lan867x_fixup_masks[12] = {
+static const u16 lan867x_revb1_fixup_masks[12] = {
0x0E03, 0x0300, 0xFFC0, 0x000F,
0xF800, 0x801C, 0x1FFF, 0xFFFF,
0x0600, 0x7F00, 0x2000, 0xFFFF,
};
-static int lan867x_config_init(struct phy_device *phydev)
+/* LAN865x Rev.B0 configuration parameters from AN1760 */
+static const u32 lan865x_revb0_fixup_registers[28] = {
+ 0x0091, 0x0081, 0x0043, 0x0044,
+ 0x0045, 0x0053, 0x0054, 0x0055,
+ 0x0040, 0x0050, 0x00D0, 0x00E9,
+ 0x00F5, 0x00F4, 0x00F8, 0x00F9,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3,
+ 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB,
+};
+
+static const u16 lan865x_revb0_fixup_values[28] = {
+ 0x9660, 0x00C0, 0x00FF, 0xFFFF,
+ 0x0000, 0x00FF, 0xFFFF, 0x0000,
+ 0x0002, 0x0002, 0x5F21, 0x9E50,
+ 0x1CF8, 0xC020, 0x9B00, 0x4E53,
+ 0x0103, 0x0910, 0x1D26, 0x002A,
+ 0x0103, 0x070D, 0x1720, 0x0027,
+ 0x0509, 0x0E13, 0x1C25, 0x002B,
+};
+
+static const u16 lan865x_revb0_fixup_cfg_regs[5] = {
+ 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF
+};
+
+/* Pulled from AN1760 describing 'indirect read'
+ *
+ * write_register(0x4, 0x00D8, addr)
+ * write_register(0x4, 0x00DA, 0x2)
+ * return (int8)(read_register(0x4, 0x00D9))
+ *
+ * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2
+ */
+static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr)
+{
+ int ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR,
+ addr);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL,
+ LAN865X_CFGPARAM_READ_ENABLE);
+ if (ret)
+ return ret;
+
+ return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA);
+}
+
+/* This is pulled straight from AN1760 from 'calculation of offset 1' &
+ * 'calculation of offset 2'
+ */
+static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2])
+{
+ const u16 fixup_regs[2] = {0x0004, 0x0008};
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) {
+ ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]);
+ if (ret < 0)
+ return ret;
+ if (ret & BIT(4))
+ offsets[i] = ret | 0xE0;
+ else
+ offsets[i] = ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[])
+{
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i]);
+ if (ret < 0)
+ return ret;
+ cfg_params[i] = (u16)ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[])
{
- /* HW quirk: Microchip states in the application note (AN1699) for the phy
- * that a set of read-modify-write (rmw) operations has to be performed
- * on a set of seemingly magic registers.
- * The result of these operations is just described as 'optimal performance'
- * Microchip gives no explanation as to what these mmd regs do,
- * in fact they are marked as reserved in the datasheet.
- * It is unclear if phy_modify_mmd would be safe to use or if a write
- * really has to happen to each register.
- * In order to exactly conform to what is stated in the AN phy_write_mmd is
- * used, which might then write the same value back as read + modified.
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i],
+ cfg_params[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_setup_cfgparam(struct phy_device *phydev)
+{
+ u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)];
+ u16 cfg_results[5];
+ s8 offsets[2];
+ int ret;
+
+ ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ if (ret)
+ return ret;
+
+ ret = lan865x_read_cfg_params(phydev, cfg_params);
+ if (ret)
+ return ret;
+
+ cfg_results[0] = (cfg_params[0] & 0x000F) |
+ FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
+ FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]);
+ cfg_results[1] = (cfg_params[1] & 0x03FF) |
+ FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
+ cfg_results[2] = (cfg_params[2] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) |
+ (9 + offsets[0]);
+ cfg_results[3] = (cfg_params[3] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) |
+ (14 + offsets[0]);
+ cfg_results[4] = (cfg_params[4] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) |
+ (22 + offsets[0]);
+
+ return lan865x_write_cfg_params(phydev, cfg_results);
+}
+
+static int lan865x_revb0_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Reference to AN1760
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf
+ */
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_registers[i],
+ lan865x_revb0_fixup_values[i]);
+ if (ret)
+ return ret;
+ }
+ /* Function to calculate and write the configuration parameters in the
+ * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760)
*/
+ return lan865x_setup_cfgparam(phydev);
+}
- int reg_value;
+static int lan867x_revb1_config_init(struct phy_device *phydev)
+{
int err;
- int reg;
- /* Read-Modified Write Pseudocode (from AN1699)
- * current_val = read_register(mmd, addr) // Read current register value
- * new_val = current_val AND (NOT mask) // Clear bit fields to be written
- * new_val = new_val OR value // Set bits
- * write_register(mmd, addr, new_val) // Write back updated register value
+ /* The chip completes a reset in 3us, we might get here earlier than
+ * that, as an added margin we'll conditionally sleep 5us.
*/
- for (int i = 0; i < ARRAY_SIZE(lan867x_fixup_registers); i++) {
- reg = lan867x_fixup_registers[i];
- reg_value = phy_read_mmd(phydev, MDIO_MMD_VEND2, reg);
- reg_value &= ~lan867x_fixup_masks[i];
- reg_value |= lan867x_fixup_values[i];
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, reg_value);
- if (err != 0)
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
+ return err;
+
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ udelay(5);
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
return err;
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ phydev_err(phydev, "PHY reset failed\n");
+ return -ENODEV;
+ }
}
- /* None of the interrupts in the lan867x phy seem relevant.
- * Other phys inspect the link status and call phy_trigger_machine
- * in the interrupt handler.
- * This phy does not support link status, and thus has no interrupt
- * for it either.
- * So we'll just disable all interrupts on the chip.
+ /* Reference to AN1699
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
+ * AN1699 says Read, Modify, Write, but the Write is not required if the
+ * register already has the required value. So it is safe to use
+ * phy_modify_mmd here.
*/
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_1_CTL, 0xFFFF);
- if (err != 0)
- return err;
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_2_CTL, 0xFFFF);
+ for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) {
+ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+ lan867x_revb1_fixup_registers[i],
+ lan867x_revb1_fixup_masks[i],
+ lan867x_revb1_fixup_values[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
-static int lan867x_read_status(struct phy_device *phydev)
+static int lan86xx_read_status(struct phy_device *phydev)
{
/* The phy has some limitations, namely:
* - always reports link up
@@ -111,28 +268,39 @@ static int lan867x_read_status(struct phy_device *phydev)
return 0;
}
-static struct phy_driver lan867x_driver[] = {
+static struct phy_driver microchip_t1s_driver[] = {
{
- PHY_ID_MATCH_MODEL(PHY_ID_LAN867X),
- .name = "LAN867X",
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1),
+ .name = "LAN867X Rev.B1",
.features = PHY_BASIC_T1S_P2MP_FEATURES,
- .config_init = lan867x_config_init,
- .read_status = lan867x_read_status,
+ .config_init = lan867x_revb1_config_init,
+ .read_status = lan86xx_read_status,
.get_plca_cfg = genphy_c45_plca_get_cfg,
.set_plca_cfg = genphy_c45_plca_set_cfg,
.get_plca_status = genphy_c45_plca_get_status,
- }
+ },
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0),
+ .name = "LAN865X Rev.B0 Internal Phy",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = lan865x_revb0_config_init,
+ .read_status = lan86xx_read_status,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = genphy_c45_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ },
};
-module_phy_driver(lan867x_driver);
+module_phy_driver(microchip_t1s_driver);
static struct mdio_device_id __maybe_unused tbl[] = {
- { PHY_ID_MATCH_MODEL(PHY_ID_LAN867X) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) },
{ }
};
MODULE_DEVICE_TABLE(mdio, tbl);
-MODULE_DESCRIPTION("Microchip 10BASE-T1S lan867x Phy driver");
+MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver");
MODULE_AUTHOR("Ramón Nordin Rodriguez");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
index defe5cc6d4fc..7a962050a4d4 100644
--- a/drivers/net/phy/mscc/mscc.h
+++ b/drivers/net/phy/mscc/mscc.h
@@ -292,6 +292,7 @@ enum rgmii_clock_delay {
#define PHY_ID_VSC8575 0x000707d0
#define PHY_ID_VSC8582 0x000707b0
#define PHY_ID_VSC8584 0x000707c0
+#define PHY_VENDOR_MSCC 0x00070400
#define MSCC_VDDMAC_1500 1500
#define MSCC_VDDMAC_1800 1800
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
index 28df8a2e4230..4171f01d34e5 100644
--- a/drivers/net/phy/mscc/mscc_main.c
+++ b/drivers/net/phy/mscc/mscc_main.c
@@ -107,6 +107,9 @@ static const struct vsc8531_edge_rate_table edge_table[] = {
};
#endif
+static const int vsc85xx_internal_delay[] = {200, 800, 1100, 1700, 2000, 2300,
+ 2600, 3400};
+
static int vsc85xx_phy_read_page(struct phy_device *phydev)
{
return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
@@ -525,8 +528,12 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
{
u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
+ int delay_size = ARRAY_SIZE(vsc85xx_internal_delay);
+ struct device *dev = &phydev->mdio.dev;
u16 reg_val = 0;
u16 mask = 0;
+ s32 rx_delay;
+ s32 tx_delay;
int rc = 0;
/* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
@@ -541,12 +548,28 @@ static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
if (phy_interface_is_rgmii(phydev))
mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_rx_delay_pos;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
- reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
+ rx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay,
+ delay_size, true);
+ if (rx_delay < 0) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ rx_delay = RGMII_CLK_DELAY_2_0_NS;
+ else
+ rx_delay = RGMII_CLK_DELAY_0_2_NS;
+ }
+
+ tx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay,
+ delay_size, false);
+ if (tx_delay < 0) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+ tx_delay = RGMII_CLK_DELAY_2_0_NS;
+ else
+ tx_delay = RGMII_CLK_DELAY_0_2_NS;
+ }
+
+ reg_val |= rx_delay << rgmii_rx_delay_pos;
+ reg_val |= tx_delay << rgmii_tx_delay_pos;
if (mask)
rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
@@ -2678,21 +2701,7 @@ static struct phy_driver vsc85xx_driver[] = {
module_phy_driver(vsc85xx_driver);
static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
- { PHY_ID_VSC8501, 0xfffffff0, },
- { PHY_ID_VSC8502, 0xfffffff0, },
- { PHY_ID_VSC8504, 0xfffffff0, },
- { PHY_ID_VSC8514, 0xfffffff0, },
- { PHY_ID_VSC8530, 0xfffffff0, },
- { PHY_ID_VSC8531, 0xfffffff0, },
- { PHY_ID_VSC8540, 0xfffffff0, },
- { PHY_ID_VSC8541, 0xfffffff0, },
- { PHY_ID_VSC8552, 0xfffffff0, },
- { PHY_ID_VSC856X, 0xfffffff0, },
- { PHY_ID_VSC8572, 0xfffffff0, },
- { PHY_ID_VSC8574, 0xfffffff0, },
- { PHY_ID_VSC8575, 0xfffffff0, },
- { PHY_ID_VSC8582, 0xfffffff0, },
- { PHY_ID_VSC8584, 0xfffffff0, },
+ { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) },
{ }
};
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index fee514b96ab1..93ed07223377 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1425,12 +1425,15 @@ int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
EXPORT_SYMBOL(genphy_c45_ethtool_get_eee);
/**
- * genphy_c45_ethtool_set_eee - get EEE supported and status
+ * genphy_c45_ethtool_set_eee - set EEE supported and status
* @phydev: target phy_device struct
* @data: ethtool_eee data
*
- * Description: it reportes the Supported/Advertisement/LP Advertisement
- * capabilities.
+ * Description: sets the Supported/Advertisement/LP Advertisement
+ * capabilities. If eee_enabled is false, no links modes are
+ * advertised, but the previously advertised link modes are
+ * retained. This allows EEE to be enabled/disabled in a
+ * non-destructive way.
*/
int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
struct ethtool_eee *data)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 0c0df38cd1ab..a9ecfdd19624 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -52,6 +52,7 @@ static const char *phy_state_to_str(enum phy_state st)
PHY_STATE_STR(NOLINK)
PHY_STATE_STR(CABLETEST)
PHY_STATE_STR(HALTED)
+ PHY_STATE_STR(ERROR)
}
return NULL;
@@ -1183,9 +1184,11 @@ void phy_stop_machine(struct phy_device *phydev)
static void phy_process_error(struct phy_device *phydev)
{
- mutex_lock(&phydev->lock);
- phydev->state = PHY_HALTED;
- mutex_unlock(&phydev->lock);
+ /* phydev->lock must be held for the state change to be safe */
+ if (!mutex_is_locked(&phydev->lock))
+ phydev_err(phydev, "PHY-device data unsafe context\n");
+
+ phydev->state = PHY_ERROR;
phy_trigger_machine(phydev);
}
@@ -1194,17 +1197,18 @@ static void phy_error_precise(struct phy_device *phydev,
const void *func, int err)
{
WARN(1, "%pS: returned: %d\n", func, err);
+ mutex_lock(&phydev->lock);
phy_process_error(phydev);
+ mutex_unlock(&phydev->lock);
}
/**
- * phy_error - enter HALTED state for this PHY device
+ * phy_error - enter ERROR state for this PHY device
* @phydev: target phy_device struct
*
- * Moves the PHY to the HALTED state in response to a read
+ * Moves the PHY to the ERROR state in response to a read
* or write error, and tells the controller the link is down.
- * Must not be called from interrupt context, or while the
- * phydev->lock is held.
+ * Must be called with phydev->lock held.
*/
void phy_error(struct phy_device *phydev)
{
@@ -1326,7 +1330,8 @@ void phy_stop(struct phy_device *phydev)
struct net_device *dev = phydev->attached_dev;
enum phy_state old_state;
- if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
+ if (!phy_is_started(phydev) && phydev->state != PHY_DOWN &&
+ phydev->state != PHY_ERROR) {
WARN(1, "called from state %s\n",
phy_state_to_str(phydev->state));
return;
@@ -1443,6 +1448,7 @@ void phy_state_machine(struct work_struct *work)
}
break;
case PHY_HALTED:
+ case PHY_ERROR:
if (phydev->link) {
phydev->link = 0;
phy_link_down(phydev);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 53598210be6c..c7cf61fe41cf 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -454,8 +454,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask)
fixup = list_entry(pos, struct phy_fixup, list);
if ((!strcmp(fixup->bus_id, bus_id)) &&
- ((fixup->phy_uid & phy_uid_mask) ==
- (phy_uid & phy_uid_mask))) {
+ phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) {
list_del(&fixup->list);
kfree(fixup);
ret = 0;
@@ -491,8 +490,8 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
return 0;
- if ((fixup->phy_uid & fixup->phy_uid_mask) !=
- (phydev->phy_id & fixup->phy_uid_mask))
+ if (!phy_id_compare(phydev->phy_id, fixup->phy_uid,
+ fixup->phy_uid_mask))
if (fixup->phy_uid != PHY_ANY_UID)
return 0;
@@ -539,15 +538,14 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv)
if (phydev->c45_ids.device_ids[i] == 0xffffffff)
continue;
- if ((phydrv->phy_id & phydrv->phy_id_mask) ==
- (phydev->c45_ids.device_ids[i] &
- phydrv->phy_id_mask))
+ if (phy_id_compare(phydev->c45_ids.device_ids[i],
+ phydrv->phy_id, phydrv->phy_id_mask))
return 1;
}
return 0;
} else {
- return (phydrv->phy_id & phydrv->phy_id_mask) ==
- (phydev->phy_id & phydrv->phy_id_mask);
+ return phy_id_compare(phydev->phy_id, phydrv->phy_id,
+ phydrv->phy_id_mask);
}
}
@@ -1860,9 +1858,10 @@ int phy_suspend(struct phy_device *phydev)
if (phydev->suspended)
return 0;
- /* If the device has WOL enabled, we cannot suspend the PHY */
phy_ethtool_get_wol(phydev, &wol);
- if (wol.wolopts || (netdev && netdev->wol_enabled))
+ phydev->wol_enabled = wol.wolopts || (netdev && netdev->wol_enabled);
+ /* If the device has WOL enabled, we cannot suspend the PHY */
+ if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND))
return -EBUSY;
if (!phydrv || !phydrv->suspend)
@@ -3217,6 +3216,8 @@ static int phy_probe(struct device *dev)
goto out;
}
+ phy_disable_interrupts(phydev);
+
/* Start out supporting everything. Eventually,
* a controller will attach, and may modify one
* or both of these values
@@ -3334,16 +3335,6 @@ static int phy_remove(struct device *dev)
return 0;
}
-static void phy_shutdown(struct device *dev)
-{
- struct phy_device *phydev = to_phy_device(dev);
-
- if (phydev->state == PHY_READY || !phydev->attached_dev)
- return;
-
- phy_disable_interrupts(phydev);
-}
-
/**
* phy_driver_register - register a phy_driver with the PHY layer
* @new_driver: new phy_driver to register
@@ -3377,7 +3368,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
new_driver->mdiodrv.driver.bus = &mdio_bus_type;
new_driver->mdiodrv.driver.probe = phy_probe;
new_driver->mdiodrv.driver.remove = phy_remove;
- new_driver->mdiodrv.driver.shutdown = phy_shutdown;
new_driver->mdiodrv.driver.owner = owner;
new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
@@ -3452,23 +3442,30 @@ static int __init phy_init(void)
{
int rc;
+ ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+
rc = mdio_bus_init();
if (rc)
- return rc;
+ goto err_ethtool_phy_ops;
- ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
features_init();
rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
if (rc)
- goto err_c45;
+ goto err_mdio_bus;
rc = phy_driver_register(&genphy_driver, THIS_MODULE);
- if (rc) {
- phy_driver_unregister(&genphy_c45_driver);
+ if (rc)
+ goto err_c45;
+
+ return 0;
+
err_c45:
- mdio_bus_exit();
- }
+ phy_driver_unregister(&genphy_c45_driver);
+err_mdio_bus:
+ mdio_bus_exit();
+err_ethtool_phy_ops:
+ ethtool_set_ethtool_phy_ops(NULL);
return rc;
}
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 5efdeb59f4b2..d0aaa5cad853 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -71,6 +71,7 @@ struct phylink {
struct mutex state_mutex;
struct phylink_link_state phy_state;
struct work_struct resolve;
+ unsigned int pcs_neg_mode;
bool mac_link_dropped;
bool using_mac_select_pcs;
@@ -156,6 +157,23 @@ static const char *phylink_an_mode_str(unsigned int mode)
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
}
+static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX: /* 1.25Mbd */
+ return 1250;
+ case PHY_INTERFACE_MODE_2500BASEX: /* 3.125Mbd */
+ return 3125;
+ case PHY_INTERFACE_MODE_5GBASER: /* 5.15625Mbd */
+ return 5156;
+ case PHY_INTERFACE_MODE_10GBASER: /* 10.3125Mbd */
+ return 10313;
+ default:
+ return 0;
+ }
+}
+
/**
* phylink_interface_max_speed() - get the maximum speed of a phy interface
* @interface: phy interface mode defined by &typedef phy_interface_t
@@ -695,20 +713,17 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported,
{
const unsigned long *interfaces = pl->config->supported_interfaces;
- if (!phy_interface_empty(interfaces)) {
- if (state->interface == PHY_INTERFACE_MODE_NA)
- return phylink_validate_mask(pl, supported, state,
- interfaces);
+ if (state->interface == PHY_INTERFACE_MODE_NA)
+ return phylink_validate_mask(pl, supported, state, interfaces);
- if (!test_bit(state->interface, interfaces))
- return -EINVAL;
- }
+ if (!test_bit(state->interface, interfaces))
+ return -EINVAL;
return phylink_validate_mac_and_pcs(pl, supported, state);
}
static int phylink_parse_fixedlink(struct phylink *pl,
- struct fwnode_handle *fwnode)
+ const struct fwnode_handle *fwnode)
{
struct fwnode_handle *fixed_node;
bool pause, asym_pause, autoneg;
@@ -819,7 +834,8 @@ static int phylink_parse_fixedlink(struct phylink *pl,
return 0;
}
-static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
+static int phylink_parse_mode(struct phylink *pl,
+ const struct fwnode_handle *fwnode)
{
struct fwnode_handle *dn;
const char *managed;
@@ -962,11 +978,10 @@ static void phylink_apply_manual_flow(struct phylink *pl,
state->pause = pl->link_config.pause;
}
-static void phylink_resolve_flow(struct phylink_link_state *state)
+static void phylink_resolve_an_pause(struct phylink_link_state *state)
{
bool tx_pause, rx_pause;
- state->pause = MLO_PAUSE_NONE;
if (state->duplex == DUPLEX_FULL) {
linkmode_resolve_pause(state->advertising,
state->lp_advertising,
@@ -978,6 +993,25 @@ static void phylink_resolve_flow(struct phylink_link_state *state)
}
}
+static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
+ const struct phylink_link_state *state,
+ bool permit_pause_to_mac)
+{
+ if (!pcs)
+ return 0;
+
+ return pcs->ops->pcs_config(pcs, neg_mode, state->interface,
+ state->advertising, permit_pause_to_mac);
+}
+
+static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
+ phy_interface_t interface, int speed,
+ int duplex)
+{
+ if (pcs && pcs->ops->pcs_link_up)
+ pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
+}
+
static void phylink_pcs_poll_stop(struct phylink *pl)
{
if (pl->cfg_link_an_mode == MLO_AN_INBAND)
@@ -1024,10 +1058,16 @@ static void phylink_major_config(struct phylink *pl, bool restart,
{
struct phylink_pcs *pcs = NULL;
bool pcs_changed = false;
+ unsigned int rate_kbd;
+ unsigned int neg_mode;
int err;
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
+ state->interface,
+ state->advertising);
+
if (pl->using_mac_select_pcs) {
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
if (IS_ERR(pcs)) {
@@ -1060,18 +1100,18 @@ static void phylink_major_config(struct phylink *pl, bool restart,
phylink_mac_config(pl, state);
- if (pl->pcs) {
- err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
- state->interface,
- state->advertising,
- !!(pl->link_config.pause &
- MLO_PAUSE_AN));
- if (err < 0)
- phylink_err(pl, "pcs_config failed: %pe\n",
- ERR_PTR(err));
- if (err > 0)
- restart = true;
- }
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs && pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
+ err = phylink_pcs_config(pl->pcs, neg_mode, state,
+ !!(pl->link_config.pause & MLO_PAUSE_AN));
+ if (err < 0)
+ phylink_err(pl, "pcs_config failed: %pe\n",
+ ERR_PTR(err));
+ else if (err > 0)
+ restart = true;
+
if (restart)
phylink_mac_pcs_an_restart(pl);
@@ -1083,6 +1123,12 @@ static void phylink_major_config(struct phylink *pl, bool restart,
ERR_PTR(err));
}
+ if (pl->sfp_bus) {
+ rate_kbd = phylink_interface_signal_rate(state->interface);
+ if (rate_kbd)
+ sfp_upstream_set_signal_rate(pl->sfp_bus, rate_kbd);
+ }
+
phylink_pcs_poll_start(pl);
}
@@ -1094,6 +1140,7 @@ static void phylink_major_config(struct phylink *pl, bool restart,
*/
static int phylink_change_inband_advert(struct phylink *pl)
{
+ unsigned int neg_mode;
int ret;
if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
@@ -1112,15 +1159,21 @@ static int phylink_change_inband_advert(struct phylink *pl)
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
pl->link_config.pause);
+ /* Recompute the PCS neg mode */
+ pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
+ pl->link_config.interface,
+ pl->link_config.advertising);
+
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
/* Modern PCS-based method; update the advert at the PCS, and
* restart negotiation if the pcs_config() helper indicates that
* the programmed advertisement has changed.
*/
- ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
- pl->link_config.interface,
- pl->link_config.advertising,
- !!(pl->link_config.pause &
- MLO_PAUSE_AN));
+ ret = phylink_pcs_config(pl->pcs, neg_mode, &pl->link_config,
+ !!(pl->link_config.pause & MLO_PAUSE_AN));
if (ret < 0)
return ret;
@@ -1171,7 +1224,8 @@ static void phylink_get_fixed_state(struct phylink *pl,
else if (pl->link_gpio)
state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
- phylink_resolve_flow(state);
+ state->pause = MLO_PAUSE_NONE;
+ phylink_resolve_an_pause(state);
}
static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
@@ -1221,6 +1275,7 @@ static void phylink_link_up(struct phylink *pl,
struct phylink_link_state link_state)
{
struct net_device *ndev = pl->netdev;
+ unsigned int neg_mode;
int speed, duplex;
bool rx_pause;
@@ -1251,9 +1306,12 @@ static void phylink_link_up(struct phylink *pl,
pl->cur_interface = link_state.interface;
- if (pl->pcs && pl->pcs->ops->pcs_link_up)
- pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode,
- pl->cur_interface, speed, duplex);
+ neg_mode = pl->cur_link_an_mode;
+ if (pl->pcs && pl->pcs->neg_mode)
+ neg_mode = pl->pcs_neg_mode;
+
+ phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
+ duplex);
pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
pl->cur_interface, speed, duplex,
@@ -1441,7 +1499,7 @@ static void phylink_fixed_poll(struct timer_list *t)
static const struct sfp_upstream_ops sfp_phylink_ops;
static int phylink_register_sfp(struct phylink *pl,
- struct fwnode_handle *fwnode)
+ const struct fwnode_handle *fwnode)
{
struct sfp_bus *bus;
int ret;
@@ -1480,7 +1538,7 @@ static int phylink_register_sfp(struct phylink *pl,
* must use IS_ERR() to check for errors from this function.
*/
struct phylink *phylink_create(struct phylink_config *config,
- struct fwnode_handle *fwnode,
+ const struct fwnode_handle *fwnode,
phy_interface_t iface,
const struct phylink_mac_ops *mac_ops)
{
@@ -1488,19 +1546,18 @@ struct phylink *phylink_create(struct phylink_config *config,
struct phylink *pl;
int ret;
- if (mac_ops->mac_select_pcs &&
- mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) !=
- ERR_PTR(-EOPNOTSUPP))
- using_mac_select_pcs = true;
-
/* Validate the supplied configuration */
- if (using_mac_select_pcs &&
- phy_interface_empty(config->supported_interfaces)) {
+ if (phy_interface_empty(config->supported_interfaces)) {
dev_err(config->dev,
- "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n");
+ "phylink: error: empty supported_interfaces\n");
return ERR_PTR(-EINVAL);
}
+ if (mac_ops->mac_select_pcs &&
+ mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) !=
+ ERR_PTR(-EOPNOTSUPP))
+ using_mac_select_pcs = true;
+
pl = kzalloc(sizeof(*pl), GFP_KERNEL);
if (!pl)
return ERR_PTR(-ENOMEM);
@@ -1809,7 +1866,7 @@ EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
* Returns 0 on success or a negative errno.
*/
int phylink_fwnode_phy_connect(struct phylink *pl,
- struct fwnode_handle *fwnode,
+ const struct fwnode_handle *fwnode,
u32 flags)
{
struct fwnode_handle *phy_fwnode;
@@ -3131,8 +3188,8 @@ static void phylink_sfp_link_up(void *upstream)
*/
static bool phylink_phy_no_inband(struct phy_device *phy)
{
- return phy->is_c45 &&
- (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150;
+ return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
+ 0xae025150, 0xfffffff0);
}
static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
@@ -3196,10 +3253,48 @@ static const struct sfp_upstream_ops sfp_phylink_ops = {
/* Helpers for MAC drivers */
+static struct {
+ int bit;
+ int speed;
+} phylink_c73_priority_resolution[] = {
+ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 },
+ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 },
+ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */
+ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 },
+ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 },
+ /* 5GBASE-KR not supported */
+ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 },
+ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 },
+};
+
+void phylink_resolve_c73(struct phylink_link_state *state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) {
+ int bit = phylink_c73_priority_resolution[i].bit;
+ if (linkmode_test_bit(bit, state->advertising) &&
+ linkmode_test_bit(bit, state->lp_advertising))
+ break;
+ }
+
+ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) {
+ state->speed = phylink_c73_priority_resolution[i].speed;
+ state->duplex = DUPLEX_FULL;
+ } else {
+ /* negotiation failure */
+ state->link = false;
+ }
+
+ phylink_resolve_an_pause(state);
+}
+EXPORT_SYMBOL_GPL(phylink_resolve_c73);
+
static void phylink_decode_c37_word(struct phylink_link_state *state,
uint16_t config_reg, int speed)
{
- bool tx_pause, rx_pause;
int fd_bit;
if (speed == SPEED_2500)
@@ -3218,13 +3313,7 @@ static void phylink_decode_c37_word(struct phylink_link_state *state,
state->link = false;
}
- linkmode_resolve_pause(state->advertising, state->lp_advertising,
- &tx_pause, &rx_pause);
-
- if (tx_pause)
- state->pause |= MLO_PAUSE_TX;
- if (rx_pause)
- state->pause |= MLO_PAUSE_RX;
+ phylink_resolve_an_pause(state);
}
static void phylink_decode_sgmii_word(struct phylink_link_state *state,
@@ -3456,18 +3545,19 @@ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement);
/**
* phylink_mii_c22_pcs_config() - configure clause 22 PCS
* @pcs: a pointer to a &struct mdio_device.
- * @mode: link autonegotiation mode
* @interface: the PHY interface mode being configured
* @advertising: the ethtool advertisement mask
+ * @neg_mode: PCS negotiation mode
*
* Configure a Clause 22 PCS PHY with the appropriate negotiation
* parameters for the @mode, @interface and @advertising parameters.
* Returns negative error number on failure, zero if the advertisement
* has not changed, or positive if there is a change.
*/
-int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
+int phylink_mii_c22_pcs_config(struct mdio_device *pcs,
phy_interface_t interface,
- const unsigned long *advertising)
+ const unsigned long *advertising,
+ unsigned int neg_mode)
{
bool changed = 0;
u16 bmcr;
@@ -3482,15 +3572,12 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
changed = ret;
}
- /* Ensure ISOLATE bit is disabled */
- if (mode == MLO_AN_INBAND &&
- (interface == PHY_INTERFACE_MODE_SGMII ||
- interface == PHY_INTERFACE_MODE_QSGMII ||
- linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)))
+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
bmcr = BMCR_ANENABLE;
else
bmcr = 0;
+ /* Configure the inband state. Ensure ISOLATE bit is disabled */
ret = mdiodev_modify(pcs, MII_BMCR, BMCR_ANENABLE | BMCR_ISOLATE, bmcr);
if (ret < 0)
return ret;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 3d99fd6664d7..894172a3e15f 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,7 @@
#include <linux/phy.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
@@ -80,6 +81,7 @@ struct rtl821x_priv {
u16 phycr1;
u16 phycr2;
bool has_phycr2;
+ struct clk *clk;
};
static int rtl821x_read_page(struct phy_device *phydev)
@@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev)
if (!priv)
return -ENOMEM;
+ priv->clk = devm_clk_get_optional_enabled(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return dev_err_probe(dev, PTR_ERR(priv->clk),
+ "failed to get phy clock\n");
+
ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1);
if (ret < 0)
return ret;
@@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev)
return genphy_soft_reset(phydev);
}
+static int rtl821x_suspend(struct phy_device *phydev)
+{
+ struct rtl821x_priv *priv = phydev->priv;
+ int ret = 0;
+
+ if (!phydev->wol_enabled) {
+ ret = genphy_suspend(phydev);
+
+ if (ret)
+ return ret;
+
+ clk_disable_unprepare(priv->clk);
+ }
+
+ return ret;
+}
+
static int rtl821x_resume(struct phy_device *phydev)
{
+ struct rtl821x_priv *priv = phydev->priv;
int ret;
+ if (!phydev->wol_enabled)
+ clk_prepare_enable(priv->clk);
+
ret = genphy_resume(phydev);
if (ret < 0)
return ret;
@@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt,
- .suspend = genphy_suspend,
+ .suspend = rtl821x_suspend,
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
}, {
PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID),
.name = "RTL8211F-VD Gigabit Ethernet",
@@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtlgen_read_status,
.config_intr = &rtl8211f_config_intr,
.handle_interrupt = rtl8211f_handle_interrupt,
- .suspend = genphy_suspend,
+ .suspend = rtl821x_suspend,
.resume = rtl821x_resume,
.read_page = rtl821x_read_page,
.write_page = rtl821x_write_page,
+ .flags = PHY_ALWAYS_CALL_SUSPEND,
}, {
.name = "Generic FE-GE Realtek PHY",
.match_phy_device = rtlgen_match_phy_device,
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 9372e5a4cadc..208a9393c2df 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -258,6 +258,16 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
switch (id->base.extended_cc) {
case SFF8024_ECC_UNSPEC:
break;
+ case SFF8024_ECC_100G_25GAUI_C2M_AOC:
+ if (br_min <= 28000 && br_max >= 25000) {
+ /* 25GBASE-R, possibly with FEC */
+ __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces);
+ /* There is currently no link mode for 25000base
+ * with unspecified range, reuse SR.
+ */
+ phylink_set(modes, 25000baseSR_Full);
+ }
+ break;
case SFF8024_ECC_100GBASE_SR4_25GBASE_SR:
phylink_set(modes, 100000baseSR4_Full);
phylink_set(modes, 25000baseSR_Full);
@@ -576,6 +586,26 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
}
/**
+ * sfp_upstream_set_signal_rate() - set data signalling rate
+ * @bus: a pointer to the &struct sfp_bus structure for the sfp module
+ * @rate_kbd: signalling rate in units of 1000 baud
+ *
+ * Configure the rate select settings on the SFP module for the signalling
+ * rate (not the same as the data rate).
+ *
+ * Locks that may be held:
+ * Phylink's state_mutex
+ * rtnl lock
+ * SFP's sm_mutex
+ */
+void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd)
+{
+ if (bus->registered)
+ bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd);
+}
+EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate);
+
+/**
* sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
* @fwnode: firmware node for the parent device (MAC or PHY)
*
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 89636dc71e48..d855a18308d7 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -24,14 +24,18 @@ enum {
GPIO_LOS,
GPIO_TX_FAULT,
GPIO_TX_DISABLE,
- GPIO_RATE_SELECT,
+ GPIO_RS0,
+ GPIO_RS1,
GPIO_MAX,
SFP_F_PRESENT = BIT(GPIO_MODDEF0),
SFP_F_LOS = BIT(GPIO_LOS),
SFP_F_TX_FAULT = BIT(GPIO_TX_FAULT),
SFP_F_TX_DISABLE = BIT(GPIO_TX_DISABLE),
- SFP_F_RATE_SELECT = BIT(GPIO_RATE_SELECT),
+ SFP_F_RS0 = BIT(GPIO_RS0),
+ SFP_F_RS1 = BIT(GPIO_RS1),
+
+ SFP_F_OUTPUTS = SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
SFP_E_INSERT = 0,
SFP_E_REMOVE,
@@ -148,6 +152,7 @@ static const char *gpio_names[] = {
"tx-fault",
"tx-disable",
"rate-select0",
+ "rate-select1",
};
static const enum gpiod_flags gpio_flags[] = {
@@ -156,6 +161,7 @@ static const enum gpiod_flags gpio_flags[] = {
GPIOD_IN,
GPIOD_ASIS,
GPIOD_ASIS,
+ GPIOD_ASIS,
};
/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a
@@ -164,7 +170,6 @@ static const enum gpiod_flags gpio_flags[] = {
* on board (for a copper SFP) time to initialise.
*/
#define T_WAIT msecs_to_jiffies(50)
-#define T_WAIT_ROLLBALL msecs_to_jiffies(25000)
#define T_START_UP msecs_to_jiffies(300)
#define T_START_UP_BAD_GPON msecs_to_jiffies(60000)
@@ -242,10 +247,18 @@ struct sfp {
bool need_poll;
+ /* Access rules:
+ * state_hw_drive: st_mutex held
+ * state_hw_mask: st_mutex held
+ * state_soft_mask: st_mutex held
+ * state: st_mutex held unless reading input bits
+ */
struct mutex st_mutex; /* Protects state */
+ unsigned int state_hw_drive;
unsigned int state_hw_mask;
unsigned int state_soft_mask;
unsigned int state;
+
struct delayed_work poll;
struct delayed_work timeout;
struct mutex sm_mutex; /* Protects state machine */
@@ -262,6 +275,10 @@ struct sfp {
unsigned int module_t_start_up;
unsigned int module_t_wait;
+ unsigned int rate_kbd;
+ unsigned int rs_threshold_kbd;
+ unsigned int rs_state_mask;
+
bool have_a2;
bool tx_fault_ignore;
@@ -312,7 +329,7 @@ static bool sfp_module_supported(const struct sfp_eeprom_id *id)
static const struct sff_data sfp_data = {
.gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT |
- SFP_F_TX_DISABLE | SFP_F_RATE_SELECT,
+ SFP_F_TX_DISABLE | SFP_F_RS0 | SFP_F_RS1,
.module_supported = sfp_module_supported,
};
@@ -333,6 +350,27 @@ static void sfp_fixup_ignore_tx_fault(struct sfp *sfp)
sfp->tx_fault_ignore = true;
}
+// For 10GBASE-T short-reach modules
+static void sfp_fixup_10gbaset_30m(struct sfp *sfp)
+{
+ sfp->id.base.connector = SFF8024_CONNECTOR_RJ45;
+ sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SR;
+}
+
+static void sfp_fixup_rollball_proto(struct sfp *sfp, unsigned int secs)
+{
+ sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
+ sfp->module_t_wait = msecs_to_jiffies(secs * 1000);
+}
+
+static void sfp_fixup_fs_10gt(struct sfp *sfp)
+{
+ sfp_fixup_10gbaset_30m(sfp);
+
+ // These SFPs need 4 seconds before the PHY can be accessed
+ sfp_fixup_rollball_proto(sfp, 4);
+}
+
static void sfp_fixup_halny_gsfp(struct sfp *sfp)
{
/* Ignore the TX_FAULT and LOS signals on this module.
@@ -344,8 +382,8 @@ static void sfp_fixup_halny_gsfp(struct sfp *sfp)
static void sfp_fixup_rollball(struct sfp *sfp)
{
- sfp->mdio_protocol = MDIO_I2C_ROLLBALL;
- sfp->module_t_wait = T_WAIT_ROLLBALL;
+ // Rollball SFPs need 25 seconds before the PHY can be accessed
+ sfp_fixup_rollball_proto(sfp, 25);
}
static void sfp_fixup_rollball_cc(struct sfp *sfp)
@@ -410,6 +448,10 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex,
sfp_fixup_long_startup),
+ // Fiberstore SFP-10G-T doesn't identify as copper, and uses the
+ // Rollball protocol to talk to the PHY.
+ SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt),
+
SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
// HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
@@ -427,6 +469,11 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
+ // Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the
+ // Rollball protocol to talk to the PHY.
+ SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt),
+ SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt),
+
SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
@@ -500,20 +547,37 @@ static unsigned int sff_gpio_get_state(struct sfp *sfp)
static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state)
{
- if (state & SFP_F_PRESENT) {
- /* If the module is present, drive the signals */
- if (sfp->gpio[GPIO_TX_DISABLE])
+ unsigned int drive;
+
+ if (state & SFP_F_PRESENT)
+ /* If the module is present, drive the requested signals */
+ drive = sfp->state_hw_drive;
+ else
+ /* Otherwise, let them float to the pull-ups */
+ drive = 0;
+
+ if (sfp->gpio[GPIO_TX_DISABLE]) {
+ if (drive & SFP_F_TX_DISABLE)
gpiod_direction_output(sfp->gpio[GPIO_TX_DISABLE],
state & SFP_F_TX_DISABLE);
- if (state & SFP_F_RATE_SELECT)
- gpiod_direction_output(sfp->gpio[GPIO_RATE_SELECT],
- state & SFP_F_RATE_SELECT);
- } else {
- /* Otherwise, let them float to the pull-ups */
- if (sfp->gpio[GPIO_TX_DISABLE])
+ else
gpiod_direction_input(sfp->gpio[GPIO_TX_DISABLE]);
- if (state & SFP_F_RATE_SELECT)
- gpiod_direction_input(sfp->gpio[GPIO_RATE_SELECT]);
+ }
+
+ if (sfp->gpio[GPIO_RS0]) {
+ if (drive & SFP_F_RS0)
+ gpiod_direction_output(sfp->gpio[GPIO_RS0],
+ state & SFP_F_RS0);
+ else
+ gpiod_direction_input(sfp->gpio[GPIO_RS0]);
+ }
+
+ if (sfp->gpio[GPIO_RS1]) {
+ if (drive & SFP_F_RS1)
+ gpiod_direction_output(sfp->gpio[GPIO_RS1],
+ state & SFP_F_RS1);
+ else
+ gpiod_direction_input(sfp->gpio[GPIO_RS1]);
}
}
@@ -675,16 +739,33 @@ static unsigned int sfp_soft_get_state(struct sfp *sfp)
return state & sfp->state_soft_mask;
}
-static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
+static void sfp_soft_set_state(struct sfp *sfp, unsigned int state,
+ unsigned int soft)
{
- u8 mask = SFP_STATUS_TX_DISABLE_FORCE;
+ u8 mask = 0;
u8 val = 0;
+ if (soft & SFP_F_TX_DISABLE)
+ mask |= SFP_STATUS_TX_DISABLE_FORCE;
if (state & SFP_F_TX_DISABLE)
val |= SFP_STATUS_TX_DISABLE_FORCE;
+ if (soft & SFP_F_RS0)
+ mask |= SFP_STATUS_RS0_SELECT;
+ if (state & SFP_F_RS0)
+ val |= SFP_STATUS_RS0_SELECT;
+
+ if (mask)
+ sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
- sfp_modify_u8(sfp, true, SFP_STATUS, mask, val);
+ val = mask = 0;
+ if (soft & SFP_F_RS1)
+ mask |= SFP_EXT_STATUS_RS1_SELECT;
+ if (state & SFP_F_RS1)
+ val |= SFP_EXT_STATUS_RS1_SELECT;
+
+ if (mask)
+ sfp_modify_u8(sfp, true, SFP_EXT_STATUS, mask, val);
}
static void sfp_soft_start_poll(struct sfp *sfp)
@@ -692,27 +773,35 @@ static void sfp_soft_start_poll(struct sfp *sfp)
const struct sfp_eeprom_id *id = &sfp->id;
unsigned int mask = 0;
- sfp->state_soft_mask = 0;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE)
mask |= SFP_F_TX_DISABLE;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT)
mask |= SFP_F_TX_FAULT;
if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS)
mask |= SFP_F_LOS;
+ if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RATE_SELECT)
+ mask |= sfp->rs_state_mask;
+ mutex_lock(&sfp->st_mutex);
// Poll the soft state for hardware pins we want to ignore
sfp->state_soft_mask = ~sfp->state_hw_mask & mask;
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
!sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
+ mutex_unlock(&sfp->st_mutex);
}
static void sfp_soft_stop_poll(struct sfp *sfp)
{
+ mutex_lock(&sfp->st_mutex);
sfp->state_soft_mask = 0;
+ mutex_unlock(&sfp->st_mutex);
}
+/* sfp_get_state() - must be called with st_mutex held, or in the
+ * initialisation path.
+ */
static unsigned int sfp_get_state(struct sfp *sfp)
{
unsigned int soft = sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT);
@@ -725,13 +814,26 @@ static unsigned int sfp_get_state(struct sfp *sfp)
return state;
}
+/* sfp_set_state() - must be called with st_mutex held, or in the
+ * initialisation path.
+ */
static void sfp_set_state(struct sfp *sfp, unsigned int state)
{
+ unsigned int soft;
+
sfp->set_state(sfp, state);
- if (state & SFP_F_PRESENT &&
- sfp->state_soft_mask & SFP_F_TX_DISABLE)
- sfp_soft_set_state(sfp, state);
+ soft = sfp->state_soft_mask & SFP_F_OUTPUTS;
+ if (state & SFP_F_PRESENT && soft)
+ sfp_soft_set_state(sfp, state, soft);
+}
+
+static void sfp_mod_state(struct sfp *sfp, unsigned int mask, unsigned int set)
+{
+ mutex_lock(&sfp->st_mutex);
+ sfp->state = (sfp->state & ~mask) | set;
+ sfp_set_state(sfp, sfp->state);
+ mutex_unlock(&sfp->st_mutex);
}
static unsigned int sfp_check(void *buf, size_t len)
@@ -1537,16 +1639,14 @@ static void sfp_module_tx_disable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 1);
- sfp->state |= SFP_F_TX_DISABLE;
- sfp_set_state(sfp, sfp->state);
+ sfp_mod_state(sfp, SFP_F_TX_DISABLE, SFP_F_TX_DISABLE);
}
static void sfp_module_tx_enable(struct sfp *sfp)
{
dev_dbg(sfp->dev, "tx disable %u -> %u\n",
sfp->state & SFP_F_TX_DISABLE ? 1 : 0, 0);
- sfp->state &= ~SFP_F_TX_DISABLE;
- sfp_set_state(sfp, sfp->state);
+ sfp_mod_state(sfp, SFP_F_TX_DISABLE, 0);
}
#if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -1567,10 +1667,15 @@ static int sfp_debug_state_show(struct seq_file *s, void *data)
sfp->sm_fault_retries);
seq_printf(s, "PHY probe remaining retries: %d\n",
sfp->sm_phy_retries);
+ seq_printf(s, "Signalling rate: %u kBd\n", sfp->rate_kbd);
+ seq_printf(s, "Rate select threshold: %u kBd\n",
+ sfp->rs_threshold_kbd);
seq_printf(s, "moddef0: %d\n", !!(sfp->state & SFP_F_PRESENT));
seq_printf(s, "rx_los: %d\n", !!(sfp->state & SFP_F_LOS));
seq_printf(s, "tx_fault: %d\n", !!(sfp->state & SFP_F_TX_FAULT));
seq_printf(s, "tx_disable: %d\n", !!(sfp->state & SFP_F_TX_DISABLE));
+ seq_printf(s, "rs0: %d\n", !!(sfp->state & SFP_F_RS0));
+ seq_printf(s, "rs1: %d\n", !!(sfp->state & SFP_F_RS1));
return 0;
}
DEFINE_SHOW_ATTRIBUTE(sfp_debug_state);
@@ -1599,16 +1704,18 @@ static void sfp_debugfs_exit(struct sfp *sfp)
static void sfp_module_tx_fault_reset(struct sfp *sfp)
{
- unsigned int state = sfp->state;
-
- if (state & SFP_F_TX_DISABLE)
- return;
+ unsigned int state;
- sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
+ mutex_lock(&sfp->st_mutex);
+ state = sfp->state;
+ if (!(state & SFP_F_TX_DISABLE)) {
+ sfp_set_state(sfp, state | SFP_F_TX_DISABLE);
- udelay(T_RESET_US);
+ udelay(T_RESET_US);
- sfp_set_state(sfp, state);
+ sfp_set_state(sfp, state);
+ }
+ mutex_unlock(&sfp->st_mutex);
}
/* SFP state machine */
@@ -1874,6 +1981,95 @@ static int sfp_sm_mod_hpower(struct sfp *sfp, bool enable)
return 0;
}
+static void sfp_module_parse_rate_select(struct sfp *sfp)
+{
+ u8 rate_id;
+
+ sfp->rs_threshold_kbd = 0;
+ sfp->rs_state_mask = 0;
+
+ if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_RATE_SELECT)))
+ /* No support for RateSelect */
+ return;
+
+ /* Default to INF-8074 RateSelect operation. The signalling threshold
+ * rate is not well specified, so always select "Full Bandwidth", but
+ * SFF-8079 reveals that it is understood that RS0 will be low for
+ * 1.0625Gb/s and high for 2.125Gb/s. Choose a value half-way between.
+ * This method exists prior to SFF-8472.
+ */
+ sfp->rs_state_mask = SFP_F_RS0;
+ sfp->rs_threshold_kbd = 1594;
+
+ /* Parse the rate identifier, which is complicated due to history:
+ * SFF-8472 rev 9.5 marks this field as reserved.
+ * SFF-8079 references SFF-8472 rev 9.5 and defines bit 0. SFF-8472
+ * compliance is not required.
+ * SFF-8472 rev 10.2 defines this field using values 0..4
+ * SFF-8472 rev 11.0 redefines this field with bit 0 for SFF-8079
+ * and even values.
+ */
+ rate_id = sfp->id.base.rate_id;
+ if (rate_id == 0)
+ /* Unspecified */
+ return;
+
+ /* SFF-8472 rev 10.0..10.4 did not account for SFF-8079 using bit 0,
+ * and allocated value 3 to SFF-8431 independent tx/rx rate select.
+ * Convert this to a SFF-8472 rev 11.0 rate identifier.
+ */
+ if (sfp->id.ext.sff8472_compliance >= SFP_SFF8472_COMPLIANCE_REV10_2 &&
+ sfp->id.ext.sff8472_compliance < SFP_SFF8472_COMPLIANCE_REV11_0 &&
+ rate_id == 3)
+ rate_id = SFF_RID_8431;
+
+ if (rate_id & SFF_RID_8079) {
+ /* SFF-8079 RateSelect / Application Select in conjunction with
+ * SFF-8472 rev 9.5. SFF-8079 defines rate_id as a bitfield
+ * with only bit 0 used, which takes precedence over SFF-8472.
+ */
+ if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_APP_SELECT_SFF8079)) {
+ /* SFF-8079 Part 1 - rate selection between Fibre
+ * Channel 1.0625/2.125/4.25 Gbd modes. Note that RS0
+ * is high for 2125, so we have to subtract 1 to
+ * include it.
+ */
+ sfp->rs_threshold_kbd = 2125 - 1;
+ sfp->rs_state_mask = SFP_F_RS0;
+ }
+ return;
+ }
+
+ /* SFF-8472 rev 9.5 does not define the rate identifier */
+ if (sfp->id.ext.sff8472_compliance <= SFP_SFF8472_COMPLIANCE_REV9_5)
+ return;
+
+ /* SFF-8472 rev 11.0 defines rate_id as a numerical value which will
+ * always have bit 0 clear due to SFF-8079's bitfield usage of rate_id.
+ */
+ switch (rate_id) {
+ case SFF_RID_8431_RX_ONLY:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS0;
+ break;
+
+ case SFF_RID_8431_TX_ONLY:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS1;
+ break;
+
+ case SFF_RID_8431:
+ sfp->rs_threshold_kbd = 4250;
+ sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
+ break;
+
+ case SFF_RID_10G8G:
+ sfp->rs_threshold_kbd = 9000;
+ sfp->rs_state_mask = SFP_F_RS0 | SFP_F_RS1;
+ break;
+ }
+}
+
/* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL
* V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do
* not support multibyte reads from the EEPROM. Each multi-byte read
@@ -1953,6 +2149,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
bool cotsworks_sfbg;
+ unsigned int mask;
bool cotsworks;
u8 check;
int ret;
@@ -2092,14 +2289,19 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
if (ret < 0)
return ret;
- /* Initialise state bits to use from hardware */
- sfp->state_hw_mask = SFP_F_PRESENT;
+ sfp_module_parse_rate_select(sfp);
+
+ mask = SFP_F_PRESENT;
if (sfp->gpio[GPIO_TX_DISABLE])
- sfp->state_hw_mask |= SFP_F_TX_DISABLE;
+ mask |= SFP_F_TX_DISABLE;
if (sfp->gpio[GPIO_TX_FAULT])
- sfp->state_hw_mask |= SFP_F_TX_FAULT;
+ mask |= SFP_F_TX_FAULT;
if (sfp->gpio[GPIO_LOS])
- sfp->state_hw_mask |= SFP_F_LOS;
+ mask |= SFP_F_LOS;
+ if (sfp->gpio[GPIO_RS0])
+ mask |= SFP_F_RS0;
+ if (sfp->gpio[GPIO_RS1])
+ mask |= SFP_F_RS1;
sfp->module_t_start_up = T_START_UP;
sfp->module_t_wait = T_WAIT;
@@ -2117,8 +2319,17 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
sfp->mdio_protocol = MDIO_I2C_NONE;
sfp->quirk = sfp_lookup_quirk(&id);
+
+ mutex_lock(&sfp->st_mutex);
+ /* Initialise state bits to use from hardware */
+ sfp->state_hw_mask = mask;
+
+ /* We want to drive the rate select pins that the module is using */
+ sfp->state_hw_drive |= sfp->rs_state_mask;
+
if (sfp->quirk && sfp->quirk->fixup)
sfp->quirk->fixup(sfp);
+ mutex_unlock(&sfp->st_mutex);
return 0;
}
@@ -2132,6 +2343,7 @@ static void sfp_sm_mod_remove(struct sfp *sfp)
memset(&sfp->id, 0, sizeof(sfp->id));
sfp->module_power_mW = 0;
+ sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->have_a2 = false;
dev_info(sfp->dev, "module removed\n");
@@ -2452,10 +2664,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
}
}
-static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+static void __sfp_sm_event(struct sfp *sfp, unsigned int event)
{
- mutex_lock(&sfp->sm_mutex);
-
dev_dbg(sfp->dev, "SM: enter %s:%s:%s event %s\n",
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
@@ -2470,7 +2680,12 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
mod_state_to_str(sfp->sm_mod_state),
dev_state_to_str(sfp->sm_dev_state),
sm_state_to_str(sfp->sm_state));
+}
+static void sfp_sm_event(struct sfp *sfp, unsigned int event)
+{
+ mutex_lock(&sfp->sm_mutex);
+ __sfp_sm_event(sfp, event);
mutex_unlock(&sfp->sm_mutex);
}
@@ -2494,6 +2709,20 @@ static void sfp_stop(struct sfp *sfp)
sfp_sm_event(sfp, SFP_E_DEV_DOWN);
}
+static void sfp_set_signal_rate(struct sfp *sfp, unsigned int rate_kbd)
+{
+ unsigned int set;
+
+ sfp->rate_kbd = rate_kbd;
+
+ if (rate_kbd > sfp->rs_threshold_kbd)
+ set = sfp->rs_state_mask;
+ else
+ set = 0;
+
+ sfp_mod_state(sfp, SFP_F_RS0 | SFP_F_RS1, set);
+}
+
static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo)
{
/* locking... and check module is present */
@@ -2578,6 +2807,7 @@ static const struct sfp_socket_ops sfp_module_ops = {
.detach = sfp_detach,
.start = sfp_start,
.stop = sfp_stop,
+ .set_signal_rate = sfp_set_signal_rate,
.module_info = sfp_module_info,
.module_eeprom = sfp_module_eeprom,
.module_eeprom_by_page = sfp_module_eeprom_by_page,
@@ -2596,6 +2826,7 @@ static void sfp_check_state(struct sfp *sfp)
{
unsigned int state, i, changed;
+ rtnl_lock();
mutex_lock(&sfp->st_mutex);
state = sfp_get_state(sfp);
changed = state ^ sfp->state;
@@ -2609,23 +2840,24 @@ static void sfp_check_state(struct sfp *sfp)
dev_dbg(sfp->dev, "%s %u -> %u\n", gpio_names[i],
!!(sfp->state & BIT(i)), !!(state & BIT(i)));
- state |= sfp->state & (SFP_F_TX_DISABLE | SFP_F_RATE_SELECT);
+ state |= sfp->state & SFP_F_OUTPUTS;
sfp->state = state;
+ mutex_unlock(&sfp->st_mutex);
- rtnl_lock();
+ mutex_lock(&sfp->sm_mutex);
if (changed & SFP_F_PRESENT)
- sfp_sm_event(sfp, state & SFP_F_PRESENT ?
- SFP_E_INSERT : SFP_E_REMOVE);
+ __sfp_sm_event(sfp, state & SFP_F_PRESENT ?
+ SFP_E_INSERT : SFP_E_REMOVE);
if (changed & SFP_F_TX_FAULT)
- sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
- SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
+ __sfp_sm_event(sfp, state & SFP_F_TX_FAULT ?
+ SFP_E_TX_FAULT : SFP_E_TX_CLEAR);
if (changed & SFP_F_LOS)
- sfp_sm_event(sfp, state & SFP_F_LOS ?
- SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
+ __sfp_sm_event(sfp, state & SFP_F_LOS ?
+ SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
+ mutex_unlock(&sfp->sm_mutex);
rtnl_unlock();
- mutex_unlock(&sfp->st_mutex);
}
static irqreturn_t sfp_irq(int irq, void *data)
@@ -2643,6 +2875,8 @@ static void sfp_poll(struct work_struct *work)
sfp_check_state(sfp);
+ // st_mutex doesn't need to be held here for state_soft_mask,
+ // it's unimportant if we race while reading this.
if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) ||
sfp->need_poll)
mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
@@ -2748,6 +2982,7 @@ static int sfp_probe(struct platform_device *pdev)
}
sfp->state_hw_mask = SFP_F_PRESENT;
+ sfp->state_hw_drive = SFP_F_TX_DISABLE;
sfp->get_state = sfp_gpio_get_state;
sfp->set_state = sfp_gpio_set_state;
@@ -2773,9 +3008,9 @@ static int sfp_probe(struct platform_device *pdev)
*/
sfp->state = sfp_get_state(sfp) | SFP_F_TX_DISABLE;
- if (sfp->gpio[GPIO_RATE_SELECT] &&
- gpiod_get_value_cansleep(sfp->gpio[GPIO_RATE_SELECT]))
- sfp->state |= SFP_F_RATE_SELECT;
+ if (sfp->gpio[GPIO_RS0] &&
+ gpiod_get_value_cansleep(sfp->gpio[GPIO_RS0]))
+ sfp->state |= SFP_F_RS0;
sfp_set_state(sfp, sfp->state);
sfp_module_tx_disable(sfp);
if (sfp->state & SFP_F_PRESENT) {
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 6cf1643214d3..c7cb50d10099 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -19,6 +19,7 @@ struct sfp_socket_ops {
void (*detach)(struct sfp *sfp);
void (*start)(struct sfp *sfp);
void (*stop)(struct sfp *sfp);
+ void (*set_signal_rate)(struct sfp *sfp, unsigned int rate_kbd);
int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee,
u8 *data);
diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig
index ac4d162d9455..8c9ed1889d1a 100644
--- a/drivers/net/ppp/Kconfig
+++ b/drivers/net/ppp/Kconfig
@@ -129,6 +129,40 @@ config PPPOE
which contains instruction on how to use this driver (under
the heading "Kernel mode PPPoE").
+choice
+ prompt "Number of PPPoE hash bits"
+ default PPPOE_HASH_BITS_4
+ depends on PPPOE
+ help
+ Select the number of bits used for hashing PPPoE interfaces.
+
+ Larger sizes reduces the risk of hash collisions at the cost
+ of slightly increased memory usage.
+
+ This hash table is on a per outer ethernet interface.
+
+config PPPOE_HASH_BITS_1
+ bool "1 bit (2 buckets)"
+
+config PPPOE_HASH_BITS_2
+ bool "2 bits (4 buckets)"
+
+config PPPOE_HASH_BITS_4
+ bool "4 bits (16 buckets)"
+
+config PPPOE_HASH_BITS_8
+ bool "8 bits (256 buckets)"
+
+endchoice
+
+config PPPOE_HASH_BITS
+ int
+ default 1 if PPPOE_HASH_BITS_1
+ default 2 if PPPOE_HASH_BITS_2
+ default 4 if PPPOE_HASH_BITS_4
+ default 8 if PPPOE_HASH_BITS_8
+ default 4
+
config PPTP
tristate "PPP over IPv4 (PPTP)"
depends on PPP && NET_IPGRE_DEMUX
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index ce2cbb5903d7..3b79c603b936 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -80,7 +80,7 @@
#include <linux/uaccess.h>
-#define PPPOE_HASH_BITS 4
+#define PPPOE_HASH_BITS CONFIG_PPPOE_HASH_BITS
#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
#define PPPOE_HASH_MASK (PPPOE_HASH_SIZE - 1)
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 0fe78826c8fa..32183f24e63f 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -24,6 +24,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/rcupdate.h>
+#include <linux/security.h>
#include <linux/spinlock.h>
#include <net/sock.h>
@@ -128,6 +129,23 @@ static void del_chan(struct pppox_sock *sock)
spin_unlock(&chan_lock);
}
+static struct rtable *pptp_route_output(struct pppox_sock *po,
+ struct flowi4 *fl4)
+{
+ struct sock *sk = &po->sk;
+ struct net *net;
+
+ net = sock_net(sk);
+ flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 0,
+ RT_SCOPE_UNIVERSE, IPPROTO_GRE, 0,
+ po->proto.pptp.dst_addr.sin_addr.s_addr,
+ po->proto.pptp.src_addr.sin_addr.s_addr,
+ 0, 0, sock_net_uid(net, sk));
+ security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
+
+ return ip_route_output_flow(net, fl4, sk);
+}
+
static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
{
struct sock *sk = (struct sock *) chan->private;
@@ -151,11 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
goto tx_error;
- rt = ip_route_output_ports(net, &fl4, NULL,
- opt->dst_addr.sin_addr.s_addr,
- opt->src_addr.sin_addr.s_addr,
- 0, 0, IPPROTO_GRE,
- RT_TOS(0), sk->sk_bound_dev_if);
+ rt = pptp_route_output(po, &fl4);
if (IS_ERR(rt))
goto tx_error;
@@ -438,12 +452,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.private = sk;
po->chan.ops = &pptp_chan_ops;
- rt = ip_route_output_ports(sock_net(sk), &fl4, sk,
- opt->dst_addr.sin_addr.s_addr,
- opt->src_addr.sin_addr.s_addr,
- 0, 0,
- IPPROTO_GRE, RT_CONN_FLAGS(sk),
- sk->sk_bound_dev_if);
+ rt = pptp_route_output(po, &fl4);
if (IS_ERR(rt)) {
error = -EHOSTUNREACH;
goto end;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index d30d730ed5a7..49d1d6acf95e 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/uio.h>
+#include <net/gso.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
#include <net/sock.h>
@@ -533,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file)
q->sock.state = SS_CONNECTED;
q->sock.file = file;
q->sock.ops = &tap_socket_ops;
- sock_init_data_uid(&q->sock, &q->sk, inode->i_uid);
+ sock_init_data_uid(&q->sock, &q->sk, current_fsuid());
q->sk.sk_write_space = tap_sock_write_space;
q->sk.sk_destruct = tap_sock_destruct;
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 555b0b1e9a78..382756c3fb83 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2135,6 +2135,15 @@ static void team_setup_by_port(struct net_device *dev,
dev->mtu = port_dev->mtu;
memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
eth_hw_addr_inherit(dev, port_dev);
+
+ if (port_dev->flags & IFF_POINTOPOINT) {
+ dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+ dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+ } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) ==
+ (IFF_BROADCAST | IFF_MULTICAST)) {
+ dev->flags |= (IFF_BROADCAST | IFF_MULTICAST);
+ dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP);
+ }
}
static int team_dev_type_check_change(struct net_device *dev,
@@ -2191,7 +2200,9 @@ static void team_setup(struct net_device *dev)
dev->hw_features = TEAM_VLAN_FEATURES |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_FILTER;
+ NETIF_F_HW_VLAN_CTAG_FILTER |
+ NETIF_F_HW_VLAN_STAG_RX |
+ NETIF_F_HW_VLAN_STAG_FILTER;
dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
dev->features |= dev->hw_features;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d75456adc62a..100339bc8b04 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1594,7 +1594,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
if (zerocopy)
return false;
- if (SKB_DATA_ALIGN(len + TUN_RX_PAD) +
+ if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE)
return false;
@@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tfile->socket.file = file;
tfile->socket.ops = &tun_socket_ops;
- sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid);
+ sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid());
tfile->sk.sk_write_space = tun_sock_write_space;
tfile->sk.sk_sndbuf = INT_MAX;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 4402eedb3d1a..3fd7dccf0f9c 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -583,12 +583,10 @@ config USB_IPHETH
default n
help
Module used to share Internet connection (tethering) from your
- iPhone (Original, 3G and 3GS) to your system.
- Note that you need userspace libraries and programs that are needed
- to pair your device with your system and that understand the iPhone
- protocol.
-
- For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver
+ iPhone to your system.
+ Note that you need a corresponding userspace library/program
+ to pair your device with your system, for example usbmuxd
+ <https://github.com/libimobiledevice/usbmuxd>.
config USB_SIERRA_NET
tristate "USB-to-WWAN Driver for Sierra Wireless modems"
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 80849d115e5d..6d61052353f0 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -618,6 +618,13 @@ static const struct usb_device_id products[] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8006, /* B-500/SL-5600 */
ZAURUS_MASTER_INTERFACE,
.driver_info = 0,
@@ -625,11 +632,25 @@ static const struct usb_device_id products[] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8007, /* C-700 */
ZAURUS_MASTER_INTERFACE,
.driver_info = 0,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = 0,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9031, /* C-750 C-760 */
@@ -876,6 +897,12 @@ static const struct usb_device_id products[] = {
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_info,
}, {
+ /* U-blox LARA-R6 01B */
+ USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1313, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&wwan_info,
+}, {
/* U-blox LARA-L6 */
USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1343, USB_CLASS_COMM,
USB_CDC_SUBCLASS_ETHERNET,
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 6a769df0b421..687d70cfc556 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -52,6 +52,7 @@
#include <linux/ethtool.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
+#include <linux/usb/cdc.h>
#define USB_VENDOR_APPLE 0x05ac
@@ -59,8 +60,12 @@
#define IPHETH_USBINTF_SUBCLASS 253
#define IPHETH_USBINTF_PROTO 1
-#define IPHETH_BUF_SIZE 1514
#define IPHETH_IP_ALIGN 2 /* padding at front of URB */
+#define IPHETH_NCM_HEADER_SIZE (12 + 96) /* NCMH + NCM0 */
+#define IPHETH_TX_BUF_SIZE ETH_FRAME_LEN
+#define IPHETH_RX_BUF_SIZE_LEGACY (IPHETH_IP_ALIGN + ETH_FRAME_LEN)
+#define IPHETH_RX_BUF_SIZE_NCM 65536
+
#define IPHETH_TX_TIMEOUT (5 * HZ)
#define IPHETH_INTFNUM 2
@@ -71,6 +76,7 @@
#define IPHETH_CTRL_TIMEOUT (5 * HZ)
#define IPHETH_CMD_GET_MACADDR 0x00
+#define IPHETH_CMD_ENABLE_NCM 0x04
#define IPHETH_CMD_CARRIER_CHECK 0x45
#define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ)
@@ -97,6 +103,8 @@ struct ipheth_device {
u8 bulk_out;
struct delayed_work carrier_work;
bool confirmed_pairing;
+ int (*rcvbulk_callback)(struct urb *urb);
+ size_t rx_buf_len;
};
static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags);
@@ -116,12 +124,12 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
if (rx_urb == NULL)
goto free_tx_urb;
- tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
+ tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_TX_BUF_SIZE,
GFP_KERNEL, &tx_urb->transfer_dma);
if (tx_buf == NULL)
goto free_rx_urb;
- rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
+ rx_buf = usb_alloc_coherent(iphone->udev, iphone->rx_buf_len,
GFP_KERNEL, &rx_urb->transfer_dma);
if (rx_buf == NULL)
goto free_tx_buf;
@@ -134,7 +142,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone)
return 0;
free_tx_buf:
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf,
+ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, tx_buf,
tx_urb->transfer_dma);
free_rx_urb:
usb_free_urb(rx_urb);
@@ -146,9 +154,9 @@ error_nomem:
static void ipheth_free_urbs(struct ipheth_device *iphone)
{
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf,
+ usb_free_coherent(iphone->udev, iphone->rx_buf_len, iphone->rx_buf,
iphone->rx_urb->transfer_dma);
- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
+ usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, iphone->tx_buf,
iphone->tx_urb->transfer_dma);
usb_free_urb(iphone->rx_urb);
usb_free_urb(iphone->tx_urb);
@@ -160,15 +168,106 @@ static void ipheth_kill_urbs(struct ipheth_device *dev)
usb_kill_urb(dev->rx_urb);
}
-static void ipheth_rcvbulk_callback(struct urb *urb)
+static int ipheth_consume_skb(char *buf, int len, struct ipheth_device *dev)
{
- struct ipheth_device *dev;
struct sk_buff *skb;
- int status;
+
+ skb = dev_alloc_skb(len);
+ if (!skb) {
+ dev->net->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put_data(skb, buf, len);
+ skb->dev = dev->net;
+ skb->protocol = eth_type_trans(skb, dev->net);
+
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += len;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ipheth_rcvbulk_callback_legacy(struct urb *urb)
+{
+ struct ipheth_device *dev;
char *buf;
int len;
dev = urb->context;
+
+ if (urb->actual_length <= IPHETH_IP_ALIGN) {
+ dev->net->stats.rx_length_errors++;
+ return -EINVAL;
+ }
+ len = urb->actual_length - IPHETH_IP_ALIGN;
+ buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
+
+ return ipheth_consume_skb(buf, len, dev);
+}
+
+static int ipheth_rcvbulk_callback_ncm(struct urb *urb)
+{
+ struct usb_cdc_ncm_nth16 *ncmh;
+ struct usb_cdc_ncm_ndp16 *ncm0;
+ struct usb_cdc_ncm_dpe16 *dpe;
+ struct ipheth_device *dev;
+ int retval = -EINVAL;
+ char *buf;
+ int len;
+
+ dev = urb->context;
+
+ if (urb->actual_length < IPHETH_NCM_HEADER_SIZE) {
+ dev->net->stats.rx_length_errors++;
+ return retval;
+ }
+
+ ncmh = urb->transfer_buffer;
+ if (ncmh->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN) ||
+ le16_to_cpu(ncmh->wNdpIndex) >= urb->actual_length) {
+ dev->net->stats.rx_errors++;
+ return retval;
+ }
+
+ ncm0 = urb->transfer_buffer + le16_to_cpu(ncmh->wNdpIndex);
+ if (ncm0->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN) ||
+ le16_to_cpu(ncmh->wHeaderLength) + le16_to_cpu(ncm0->wLength) >=
+ urb->actual_length) {
+ dev->net->stats.rx_errors++;
+ return retval;
+ }
+
+ dpe = ncm0->dpe16;
+ while (le16_to_cpu(dpe->wDatagramIndex) != 0 &&
+ le16_to_cpu(dpe->wDatagramLength) != 0) {
+ if (le16_to_cpu(dpe->wDatagramIndex) >= urb->actual_length ||
+ le16_to_cpu(dpe->wDatagramIndex) +
+ le16_to_cpu(dpe->wDatagramLength) > urb->actual_length) {
+ dev->net->stats.rx_length_errors++;
+ return retval;
+ }
+
+ buf = urb->transfer_buffer + le16_to_cpu(dpe->wDatagramIndex);
+ len = le16_to_cpu(dpe->wDatagramLength);
+
+ retval = ipheth_consume_skb(buf, len, dev);
+ if (retval != 0)
+ return retval;
+
+ dpe++;
+ }
+
+ return 0;
+}
+
+static void ipheth_rcvbulk_callback(struct urb *urb)
+{
+ struct ipheth_device *dev;
+ int retval, status;
+
+ dev = urb->context;
if (dev == NULL)
return;
@@ -191,25 +290,27 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
dev->net->stats.rx_length_errors++;
return;
}
- len = urb->actual_length - IPHETH_IP_ALIGN;
- buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
- skb = dev_alloc_skb(len);
- if (!skb) {
- dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n",
- __func__);
- dev->net->stats.rx_dropped++;
+ /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames,
+ * but rather are control frames. Their purpose is not documented, and
+ * they don't affect driver functionality, okay to drop them.
+ * There is usually just one 4-byte control frame as the very first
+ * URB received from the bulk IN endpoint.
+ */
+ if (unlikely
+ (((char *)urb->transfer_buffer)[0] == 0 &&
+ ((char *)urb->transfer_buffer)[1] == 1))
+ goto rx_submit;
+
+ retval = dev->rcvbulk_callback(urb);
+ if (retval != 0) {
+ dev_err(&dev->intf->dev, "%s: callback retval: %d\n",
+ __func__, retval);
return;
}
- skb_put_data(skb, buf, len);
- skb->dev = dev->net;
- skb->protocol = eth_type_trans(skb, dev->net);
-
- dev->net->stats.rx_packets++;
- dev->net->stats.rx_bytes += len;
+rx_submit:
dev->confirmed_pairing = true;
- netif_rx(skb);
ipheth_rx_submit(dev, GFP_ATOMIC);
}
@@ -310,6 +411,27 @@ static int ipheth_get_macaddr(struct ipheth_device *dev)
return retval;
}
+static int ipheth_enable_ncm(struct ipheth_device *dev)
+{
+ struct usb_device *udev = dev->udev;
+ int retval;
+
+ retval = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, IPHETH_CTRL_ENDP),
+ IPHETH_CMD_ENABLE_NCM, /* request */
+ 0x41, /* request type */
+ 0x00, /* value */
+ 0x02, /* index */
+ NULL,
+ 0,
+ IPHETH_CTRL_TIMEOUT);
+
+ dev_info(&dev->intf->dev, "%s: usb_control_msg: %d\n",
+ __func__, retval);
+
+ return retval;
+}
+
static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
{
struct usb_device *udev = dev->udev;
@@ -317,7 +439,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags)
usb_fill_bulk_urb(dev->rx_urb, udev,
usb_rcvbulkpipe(udev, dev->bulk_in),
- dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
+ dev->rx_buf, dev->rx_buf_len,
ipheth_rcvbulk_callback,
dev);
dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -365,7 +487,7 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net)
int retval;
/* Paranoid */
- if (skb->len > IPHETH_BUF_SIZE) {
+ if (skb->len > IPHETH_TX_BUF_SIZE) {
WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
dev->net->stats.tx_dropped++;
dev_kfree_skb_any(skb);
@@ -373,12 +495,10 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net)
}
memcpy(dev->tx_buf, skb->data, skb->len);
- if (skb->len < IPHETH_BUF_SIZE)
- memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len);
usb_fill_bulk_urb(dev->tx_urb, udev,
usb_sndbulkpipe(udev, dev->bulk_out),
- dev->tx_buf, IPHETH_BUF_SIZE,
+ dev->tx_buf, skb->len,
ipheth_sndbulk_callback,
dev);
dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -450,6 +570,8 @@ static int ipheth_probe(struct usb_interface *intf,
dev->net = netdev;
dev->intf = intf;
dev->confirmed_pairing = false;
+ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_LEGACY;
+ dev->rcvbulk_callback = ipheth_rcvbulk_callback_legacy;
/* Set up endpoints */
hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
if (hintf == NULL) {
@@ -481,6 +603,12 @@ static int ipheth_probe(struct usb_interface *intf,
if (retval)
goto err_get_macaddr;
+ retval = ipheth_enable_ncm(dev);
+ if (!retval) {
+ dev->rx_buf_len = IPHETH_RX_BUF_SIZE_NCM;
+ dev->rcvbulk_callback = ipheth_rcvbulk_callback_ncm;
+ }
+
INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);
retval = ipheth_alloc_urbs(dev);
@@ -510,8 +638,8 @@ err_register_netdev:
ipheth_free_urbs(dev);
err_alloc_urbs:
err_get_macaddr:
-err_alloc_ctrl_buf:
kfree(dev->ctrl_buf);
+err_alloc_ctrl_buf:
err_endpoints:
free_netdev(netdev);
return retval;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index c458c030fadf..59cde06aa7f6 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
if (!dev)
return;
- set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
-
netif_napi_del(&dev->napi);
udev = interface_to_usbdev(intf);
@@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf)
unregister_netdev(net);
+ timer_shutdown_sync(&dev->stat_monitor);
+ set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
cancel_delayed_work_sync(&dev->wq);
phydev = net->phydev;
@@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
usb_scuttle_anchored_urbs(&dev->deferred);
- if (timer_pending(&dev->stat_monitor))
- del_timer_sync(&dev->stat_monitor);
-
lan78xx_unbind(dev, intf);
lan78xx_free_tx_resources(dev);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 2e7c7b0cdc54..344af3c5c836 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1423,10 +1423,12 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
{QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */
+ {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
{QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
+ {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
/* 4. Gobi 1000 devices */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0999a58ca9d2..e88bedca8f32 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -27,6 +27,7 @@
#include <linux/firmware.h>
#include <crypto/hash.h>
#include <linux/usb/r8152.h>
+#include <net/gso.h>
/* Information for net-next */
#define NETNEXT_VERSION "12"
@@ -2628,6 +2629,9 @@ static int r8152_poll(struct napi_struct *napi, int budget)
struct r8152 *tp = container_of(napi, struct r8152, napi);
int work_done;
+ if (!budget)
+ return 0;
+
work_done = rx_bottom(tp, budget);
if (work_done < budget) {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 283ffddda821..2d14b0d78541 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1775,6 +1775,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
} else if (!info->in || !info->out)
status = usbnet_get_endpoints (dev, udev);
else {
+ u8 ep_addrs[3] = {
+ info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
+ };
+
dev->in = usb_rcvbulkpipe (xdev, info->in);
dev->out = usb_sndbulkpipe (xdev, info->out);
if (!(info->flags & FLAG_NO_SETINT))
@@ -1784,6 +1788,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
else
status = 0;
+ if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
+ status = -EINVAL;
}
if (status >= 0 && dev->status)
status = init_status (dev, udev);
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c
index 7984f2157d22..df3617c4c44e 100644
--- a/drivers/net/usb/zaurus.c
+++ b/drivers/net/usb/zaurus.c
@@ -289,11 +289,25 @@ static const struct usb_device_id products [] = {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ .idProduct = 0x8005, /* A-300 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
.idProduct = 0x8006, /* B-500/SL-5600 */
ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8006, /* B-500/SL-5600 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8007, /* C-700 */
@@ -301,6 +315,13 @@ static const struct usb_device_id products [] = {
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ .idProduct = 0x8007, /* C-700 */
+ ZAURUS_FAKE_INTERFACE,
+ .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9031, /* C-750 C-760 */
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index dce9f9d63e04..fc0d0114d8c2 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -176,12 +176,27 @@ static int veth_get_sset_count(struct net_device *dev, int sset)
}
}
+static void veth_get_page_pool_stats(struct net_device *dev, u64 *data)
+{
+#ifdef CONFIG_PAGE_POOL_STATS
+ struct veth_priv *priv = netdev_priv(dev);
+ struct page_pool_stats pp_stats = {};
+ int i;
+
+ for (i = 0; i < dev->real_num_rx_queues; i++) {
+ if (!priv->rq[i].page_pool)
+ continue;
+ page_pool_get_stats(priv->rq[i].page_pool, &pp_stats);
+ }
+ page_pool_ethtool_stats_get(data, &pp_stats);
+#endif /* CONFIG_PAGE_POOL_STATS */
+}
+
static void veth_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
struct net_device *peer = rtnl_dereference(priv->peer);
- struct page_pool_stats pp_stats = {};
int i, j, idx, pp_idx;
data[0] = peer ? peer->ifindex : 0;
@@ -225,12 +240,7 @@ static void veth_get_ethtool_stats(struct net_device *dev,
}
page_pool_stats:
- for (i = 0; i < dev->real_num_rx_queues; i++) {
- if (!priv->rq[i].page_pool)
- continue;
- page_pool_get_stats(priv->rq[i].page_pool, &pp_stats);
- }
- page_pool_ethtool_stats_get(&data[pp_idx], &pp_stats);
+ veth_get_page_pool_stats(dev, &data[pp_idx]);
}
static void veth_get_channels(struct net_device *dev,
@@ -334,6 +344,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
struct veth_rq *rq = NULL;
+ int ret = NETDEV_TX_OK;
struct net_device *rcv;
int length = skb->len;
bool use_napi = false;
@@ -366,6 +377,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
} else {
drop:
atomic64_inc(&priv->dropped);
+ ret = NET_XMIT_DROP;
}
if (use_napi)
@@ -373,7 +385,7 @@ drop:
rcu_read_unlock();
- return NETDEV_TX_OK;
+ return ret;
}
static u64 veth_stats_tx(struct net_device *dev, u64 *packets, u64 *bytes)
@@ -747,7 +759,7 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
if (!page)
goto drop;
- nskb = build_skb(page_address(page), PAGE_SIZE);
+ nskb = napi_build_skb(page_address(page), PAGE_SIZE);
if (!nskb) {
page_pool_put_full_page(rq->page_pool, page, true);
goto drop;
@@ -1071,8 +1083,9 @@ static int __veth_napi_enable_range(struct net_device *dev, int start, int end)
err_xdp_ring:
for (i--; i >= start; i--)
ptr_ring_cleanup(&priv->rq[i].xdp_ring, veth_ptr_free);
+ i = end;
err_page_pool:
- for (i = start; i < end; i++) {
+ for (i--; i >= start; i--) {
page_pool_destroy(priv->rq[i].page_pool);
priv->rq[i].page_pool = NULL;
}
@@ -1434,6 +1447,8 @@ static int veth_open(struct net_device *dev)
netif_carrier_on(peer);
}
+ veth_set_xdp_features(dev);
+
return 0;
}
@@ -1850,10 +1865,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
nla_peer = data[VETH_INFO_PEER];
ifmp = nla_data(nla_peer);
- err = rtnl_nla_parse_ifla(peer_tb,
- nla_data(nla_peer) + sizeof(struct ifinfomsg),
- nla_len(nla_peer) - sizeof(struct ifinfomsg),
- NULL);
+ err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
if (err < 0)
return err;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 486b5849033d..8e9f4cfe941f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -445,6 +445,22 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1);
}
+static struct sk_buff *virtnet_build_skb(void *buf, unsigned int buflen,
+ unsigned int headroom,
+ unsigned int len)
+{
+ struct sk_buff *skb;
+
+ skb = build_skb(buf, buflen);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, headroom);
+ skb_put(skb, len);
+
+ return skb;
+}
+
/* Called from bottom half context */
static struct sk_buff *page_to_skb(struct virtnet_info *vi,
struct receive_queue *rq,
@@ -478,13 +494,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
/* copy small packet so we can reuse these pages */
if (!NET_IP_ALIGN && len > GOOD_COPY_LEN && tailroom >= shinfo_size) {
- skb = build_skb(buf, truesize);
+ skb = virtnet_build_skb(buf, truesize, p - buf, len);
if (unlikely(!skb))
return NULL;
- skb_reserve(skb, p - buf);
- skb_put(skb, len);
-
page = (struct page *)page->private;
if (page)
give_pages(rq, page);
@@ -791,6 +804,75 @@ out:
return ret;
}
+static void put_xdp_frags(struct xdp_buff *xdp)
+{
+ struct skb_shared_info *shinfo;
+ struct page *xdp_page;
+ int i;
+
+ if (xdp_buff_has_frags(xdp)) {
+ shinfo = xdp_get_shared_info_from_buff(xdp);
+ for (i = 0; i < shinfo->nr_frags; i++) {
+ xdp_page = skb_frag_page(&shinfo->frags[i]);
+ put_page(xdp_page);
+ }
+ }
+}
+
+static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
+ struct net_device *dev,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ struct xdp_frame *xdpf;
+ int err;
+ u32 act;
+
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
+ stats->xdp_packets++;
+
+ switch (act) {
+ case XDP_PASS:
+ return act;
+
+ case XDP_TX:
+ stats->xdp_tx++;
+ xdpf = xdp_convert_buff_to_frame(xdp);
+ if (unlikely(!xdpf)) {
+ netdev_dbg(dev, "convert buff to frame failed for xdp\n");
+ return XDP_DROP;
+ }
+
+ err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
+ if (unlikely(!err)) {
+ xdp_return_frame_rx_napi(xdpf);
+ } else if (unlikely(err < 0)) {
+ trace_xdp_exception(dev, xdp_prog, act);
+ return XDP_DROP;
+ }
+ *xdp_xmit |= VIRTIO_XDP_TX;
+ return act;
+
+ case XDP_REDIRECT:
+ stats->xdp_redirects++;
+ err = xdp_do_redirect(dev, xdp, xdp_prog);
+ if (err)
+ return XDP_DROP;
+
+ *xdp_xmit |= VIRTIO_XDP_REDIR;
+ return act;
+
+ default:
+ bpf_warn_invalid_xdp_action(dev, xdp_prog, act);
+ fallthrough;
+ case XDP_ABORTED:
+ trace_xdp_exception(dev, xdp_prog, act);
+ fallthrough;
+ case XDP_DROP:
+ return XDP_DROP;
+ }
+}
+
static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
{
return vi->xdp_enabled ? VIRTIO_XDP_HEADROOM : 0;
@@ -864,134 +946,103 @@ err_buf:
return NULL;
}
-static struct sk_buff *receive_small(struct net_device *dev,
- struct virtnet_info *vi,
- struct receive_queue *rq,
- void *buf, void *ctx,
- unsigned int len,
- unsigned int *xdp_xmit,
- struct virtnet_rq_stats *stats)
+static struct sk_buff *receive_small_build_skb(struct virtnet_info *vi,
+ unsigned int xdp_headroom,
+ void *buf,
+ unsigned int len)
{
+ unsigned int header_offset;
+ unsigned int headroom;
+ unsigned int buflen;
struct sk_buff *skb;
- struct bpf_prog *xdp_prog;
- unsigned int xdp_headroom = (unsigned long)ctx;
+
+ header_offset = VIRTNET_RX_PAD + xdp_headroom;
+ headroom = vi->hdr_len + header_offset;
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ skb = virtnet_build_skb(buf, buflen, headroom, len);
+ if (unlikely(!skb))
+ return NULL;
+
+ buf += header_offset;
+ memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
+
+ return skb;
+}
+
+static struct sk_buff *receive_small_xdp(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *buf,
+ unsigned int xdp_headroom,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
unsigned int header_offset = VIRTNET_RX_PAD + xdp_headroom;
unsigned int headroom = vi->hdr_len + header_offset;
- unsigned int buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
struct page *page = virt_to_head_page(buf);
- unsigned int delta = 0;
struct page *xdp_page;
- int err;
+ unsigned int buflen;
+ struct xdp_buff xdp;
+ struct sk_buff *skb;
unsigned int metasize = 0;
+ u32 act;
- len -= vi->hdr_len;
- stats->bytes += len;
+ if (unlikely(hdr->hdr.gso_type))
+ goto err_xdp;
- if (unlikely(len > GOOD_PACKET_LEN)) {
- pr_debug("%s: rx error: len %u exceeds max size %d\n",
- dev->name, len, GOOD_PACKET_LEN);
- dev->stats.rx_length_errors++;
- goto err;
- }
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+ if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) {
+ int offset = buf - page_address(page) + header_offset;
+ unsigned int tlen = len + vi->hdr_len;
+ int num_buf = 1;
+
+ xdp_headroom = virtnet_get_headroom(vi);
+ header_offset = VIRTNET_RX_PAD + xdp_headroom;
+ headroom = vi->hdr_len + header_offset;
+ buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ xdp_page = xdp_linearize_page(rq, &num_buf, page,
+ offset, header_offset,
+ &tlen);
+ if (!xdp_page)
+ goto err_xdp;
- if (likely(!vi->xdp_enabled)) {
- xdp_prog = NULL;
- goto skip_xdp;
+ buf = page_address(xdp_page);
+ put_page(page);
+ page = xdp_page;
}
- rcu_read_lock();
- xdp_prog = rcu_dereference(rq->xdp_prog);
- if (xdp_prog) {
- struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
- struct xdp_frame *xdpf;
- struct xdp_buff xdp;
- void *orig_data;
- u32 act;
+ xdp_init_buff(&xdp, buflen, &rq->xdp_rxq);
+ xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
+ xdp_headroom, len, true);
- if (unlikely(hdr->hdr.gso_type))
- goto err_xdp;
+ act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
- if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) {
- int offset = buf - page_address(page) + header_offset;
- unsigned int tlen = len + vi->hdr_len;
- int num_buf = 1;
-
- xdp_headroom = virtnet_get_headroom(vi);
- header_offset = VIRTNET_RX_PAD + xdp_headroom;
- headroom = vi->hdr_len + header_offset;
- buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- xdp_page = xdp_linearize_page(rq, &num_buf, page,
- offset, header_offset,
- &tlen);
- if (!xdp_page)
- goto err_xdp;
-
- buf = page_address(xdp_page);
- put_page(page);
- page = xdp_page;
- }
+ switch (act) {
+ case XDP_PASS:
+ /* Recalculate length in case bpf program changed it */
+ len = xdp.data_end - xdp.data;
+ metasize = xdp.data - xdp.data_meta;
+ break;
- xdp_init_buff(&xdp, buflen, &rq->xdp_rxq);
- xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
- xdp_headroom, len, true);
- orig_data = xdp.data;
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
- stats->xdp_packets++;
-
- switch (act) {
- case XDP_PASS:
- /* Recalculate length in case bpf program changed it */
- delta = orig_data - xdp.data;
- len = xdp.data_end - xdp.data;
- metasize = xdp.data - xdp.data_meta;
- break;
- case XDP_TX:
- stats->xdp_tx++;
- xdpf = xdp_convert_buff_to_frame(&xdp);
- if (unlikely(!xdpf))
- goto err_xdp;
- err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
- if (unlikely(!err)) {
- xdp_return_frame_rx_napi(xdpf);
- } else if (unlikely(err < 0)) {
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp;
- }
- *xdp_xmit |= VIRTIO_XDP_TX;
- rcu_read_unlock();
- goto xdp_xmit;
- case XDP_REDIRECT:
- stats->xdp_redirects++;
- err = xdp_do_redirect(dev, &xdp, xdp_prog);
- if (err)
- goto err_xdp;
- *xdp_xmit |= VIRTIO_XDP_REDIR;
- rcu_read_unlock();
- goto xdp_xmit;
- default:
- bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_ABORTED:
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp;
- case XDP_DROP:
- goto err_xdp;
- }
+ case XDP_TX:
+ case XDP_REDIRECT:
+ goto xdp_xmit;
+
+ default:
+ goto err_xdp;
}
- rcu_read_unlock();
-skip_xdp:
- skb = build_skb(buf, buflen);
- if (!skb)
+ skb = virtnet_build_skb(buf, buflen, xdp.data - buf, len);
+ if (unlikely(!skb))
goto err;
- skb_reserve(skb, headroom - delta);
- skb_put(skb, len);
- if (!xdp_prog) {
- buf += header_offset;
- memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
- } /* keep zeroed vnet hdr since XDP is loaded */
if (metasize)
skb_metadata_set(skb, metasize);
@@ -999,7 +1050,6 @@ skip_xdp:
return skb;
err_xdp:
- rcu_read_unlock();
stats->xdp_drops++;
err:
stats->drops++;
@@ -1008,6 +1058,53 @@ xdp_xmit:
return NULL;
}
+static struct sk_buff *receive_small(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ void *buf, void *ctx,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ unsigned int xdp_headroom = (unsigned long)ctx;
+ struct page *page = virt_to_head_page(buf);
+ struct sk_buff *skb;
+
+ len -= vi->hdr_len;
+ stats->bytes += len;
+
+ if (unlikely(len > GOOD_PACKET_LEN)) {
+ pr_debug("%s: rx error: len %u exceeds max size %d\n",
+ dev->name, len, GOOD_PACKET_LEN);
+ dev->stats.rx_length_errors++;
+ goto err;
+ }
+
+ if (unlikely(vi->xdp_enabled)) {
+ struct bpf_prog *xdp_prog;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(rq->xdp_prog);
+ if (xdp_prog) {
+ skb = receive_small_xdp(dev, vi, rq, xdp_prog, buf,
+ xdp_headroom, len, xdp_xmit,
+ stats);
+ rcu_read_unlock();
+ return skb;
+ }
+ rcu_read_unlock();
+ }
+
+ skb = receive_small_build_skb(vi, xdp_headroom, buf, len);
+ if (likely(skb))
+ return skb;
+
+err:
+ stats->drops++;
+ put_page(page);
+ return NULL;
+}
+
static struct sk_buff *receive_big(struct net_device *dev,
struct virtnet_info *vi,
struct receive_queue *rq,
@@ -1031,6 +1128,28 @@ err:
return NULL;
}
+static void mergeable_buf_free(struct receive_queue *rq, int num_buf,
+ struct net_device *dev,
+ struct virtnet_rq_stats *stats)
+{
+ struct page *page;
+ void *buf;
+ int len;
+
+ while (num_buf-- > 1) {
+ buf = virtqueue_get_buf(rq->vq, &len);
+ if (unlikely(!buf)) {
+ pr_debug("%s: rx error: %d buffers missing\n",
+ dev->name, num_buf);
+ dev->stats.rx_length_errors++;
+ break;
+ }
+ stats->bytes += len;
+ page = virt_to_head_page(buf);
+ put_page(page);
+ }
+}
+
/* Why not use xdp_build_skb_from_frame() ?
* XDP core assumes that xdp frags are PAGE_SIZE in length, while in
* virtio-net there are 2 points that do not match its requirements:
@@ -1132,7 +1251,7 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
dev->name, *num_buf,
virtio16_to_cpu(vi->vdev, hdr->num_buffers));
dev->stats.rx_length_errors++;
- return -EINVAL;
+ goto err;
}
stats->bytes += len;
@@ -1151,13 +1270,11 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
dev->name, len, (unsigned long)(truesize - room));
dev->stats.rx_length_errors++;
- return -EINVAL;
+ goto err;
}
frag = &shinfo->frags[shinfo->nr_frags++];
- __skb_frag_set_page(frag, page);
- skb_frag_off_set(frag, offset);
- skb_frag_size_set(frag, len);
+ skb_frag_fill_page_desc(frag, page, offset, len);
if (page_is_pfmemalloc(page))
xdp_buff_set_frag_pfmemalloc(xdp);
@@ -1166,6 +1283,144 @@ static int virtnet_build_xdp_buff_mrg(struct net_device *dev,
*xdp_frags_truesize = xdp_frags_truesz;
return 0;
+
+err:
+ put_xdp_frags(xdp);
+ return -EINVAL;
+}
+
+static void *mergeable_xdp_get_buf(struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *ctx,
+ unsigned int *frame_sz,
+ int *num_buf,
+ struct page **page,
+ int offset,
+ unsigned int *len,
+ struct virtio_net_hdr_mrg_rxbuf *hdr)
+{
+ unsigned int truesize = mergeable_ctx_to_truesize(ctx);
+ unsigned int headroom = mergeable_ctx_to_headroom(ctx);
+ struct page *xdp_page;
+ unsigned int xdp_room;
+
+ /* Transient failure which in theory could occur if
+ * in-flight packets from before XDP was enabled reach
+ * the receive path after XDP is loaded.
+ */
+ if (unlikely(hdr->hdr.gso_type))
+ return NULL;
+
+ /* Now XDP core assumes frag size is PAGE_SIZE, but buffers
+ * with headroom may add hole in truesize, which
+ * make their length exceed PAGE_SIZE. So we disabled the
+ * hole mechanism for xdp. See add_recvbuf_mergeable().
+ */
+ *frame_sz = truesize;
+
+ if (likely(headroom >= virtnet_get_headroom(vi) &&
+ (*num_buf == 1 || xdp_prog->aux->xdp_has_frags))) {
+ return page_address(*page) + offset;
+ }
+
+ /* This happens when headroom is not enough because
+ * of the buffer was prefilled before XDP is set.
+ * This should only happen for the first several packets.
+ * In fact, vq reset can be used here to help us clean up
+ * the prefilled buffers, but many existing devices do not
+ * support it, and we don't want to bother users who are
+ * using xdp normally.
+ */
+ if (!xdp_prog->aux->xdp_has_frags) {
+ /* linearize data for XDP */
+ xdp_page = xdp_linearize_page(rq, num_buf,
+ *page, offset,
+ VIRTIO_XDP_HEADROOM,
+ len);
+ if (!xdp_page)
+ return NULL;
+ } else {
+ xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM +
+ sizeof(struct skb_shared_info));
+ if (*len + xdp_room > PAGE_SIZE)
+ return NULL;
+
+ xdp_page = alloc_page(GFP_ATOMIC);
+ if (!xdp_page)
+ return NULL;
+
+ memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM,
+ page_address(*page) + offset, *len);
+ }
+
+ *frame_sz = PAGE_SIZE;
+
+ put_page(*page);
+
+ *page = xdp_page;
+
+ return page_address(*page) + VIRTIO_XDP_HEADROOM;
+}
+
+static struct sk_buff *receive_mergeable_xdp(struct net_device *dev,
+ struct virtnet_info *vi,
+ struct receive_queue *rq,
+ struct bpf_prog *xdp_prog,
+ void *buf,
+ void *ctx,
+ unsigned int len,
+ unsigned int *xdp_xmit,
+ struct virtnet_rq_stats *stats)
+{
+ struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
+ int num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
+ struct page *page = virt_to_head_page(buf);
+ int offset = buf - page_address(page);
+ unsigned int xdp_frags_truesz = 0;
+ struct sk_buff *head_skb;
+ unsigned int frame_sz;
+ struct xdp_buff xdp;
+ void *data;
+ u32 act;
+ int err;
+
+ data = mergeable_xdp_get_buf(vi, rq, xdp_prog, ctx, &frame_sz, &num_buf, &page,
+ offset, &len, hdr);
+ if (unlikely(!data))
+ goto err_xdp;
+
+ err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz,
+ &num_buf, &xdp_frags_truesz, stats);
+ if (unlikely(err))
+ goto err_xdp;
+
+ act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
+
+ switch (act) {
+ case XDP_PASS:
+ head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
+ if (unlikely(!head_skb))
+ break;
+ return head_skb;
+
+ case XDP_TX:
+ case XDP_REDIRECT:
+ return NULL;
+
+ default:
+ break;
+ }
+
+ put_xdp_frags(&xdp);
+
+err_xdp:
+ put_page(page);
+ mergeable_buf_free(rq, num_buf, dev, stats);
+
+ stats->xdp_drops++;
+ stats->drops++;
+ return NULL;
}
static struct sk_buff *receive_mergeable(struct net_device *dev,
@@ -1182,13 +1437,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
struct page *page = virt_to_head_page(buf);
int offset = buf - page_address(page);
struct sk_buff *head_skb, *curr_skb;
- struct bpf_prog *xdp_prog;
unsigned int truesize = mergeable_ctx_to_truesize(ctx);
unsigned int headroom = mergeable_ctx_to_headroom(ctx);
unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
unsigned int room = SKB_DATA_ALIGN(headroom + tailroom);
- unsigned int frame_sz, xdp_room;
- int err;
head_skb = NULL;
stats->bytes += len - vi->hdr_len;
@@ -1200,149 +1452,20 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
goto err_skb;
}
- if (likely(!vi->xdp_enabled)) {
- xdp_prog = NULL;
- goto skip_xdp;
- }
-
- rcu_read_lock();
- xdp_prog = rcu_dereference(rq->xdp_prog);
- if (xdp_prog) {
- unsigned int xdp_frags_truesz = 0;
- struct skb_shared_info *shinfo;
- struct xdp_frame *xdpf;
- struct page *xdp_page;
- struct xdp_buff xdp;
- void *data;
- u32 act;
- int i;
-
- /* Transient failure which in theory could occur if
- * in-flight packets from before XDP was enabled reach
- * the receive path after XDP is loaded.
- */
- if (unlikely(hdr->hdr.gso_type))
- goto err_xdp;
-
- /* Now XDP core assumes frag size is PAGE_SIZE, but buffers
- * with headroom may add hole in truesize, which
- * make their length exceed PAGE_SIZE. So we disabled the
- * hole mechanism for xdp. See add_recvbuf_mergeable().
- */
- frame_sz = truesize;
-
- /* This happens when headroom is not enough because
- * of the buffer was prefilled before XDP is set.
- * This should only happen for the first several packets.
- * In fact, vq reset can be used here to help us clean up
- * the prefilled buffers, but many existing devices do not
- * support it, and we don't want to bother users who are
- * using xdp normally.
- */
- if (!xdp_prog->aux->xdp_has_frags &&
- (num_buf > 1 || headroom < virtnet_get_headroom(vi))) {
- /* linearize data for XDP */
- xdp_page = xdp_linearize_page(rq, &num_buf,
- page, offset,
- VIRTIO_XDP_HEADROOM,
- &len);
- frame_sz = PAGE_SIZE;
-
- if (!xdp_page)
- goto err_xdp;
- offset = VIRTIO_XDP_HEADROOM;
- } else if (unlikely(headroom < virtnet_get_headroom(vi))) {
- xdp_room = SKB_DATA_ALIGN(VIRTIO_XDP_HEADROOM +
- sizeof(struct skb_shared_info));
- if (len + xdp_room > PAGE_SIZE)
- goto err_xdp;
-
- xdp_page = alloc_page(GFP_ATOMIC);
- if (!xdp_page)
- goto err_xdp;
-
- memcpy(page_address(xdp_page) + VIRTIO_XDP_HEADROOM,
- page_address(page) + offset, len);
- frame_sz = PAGE_SIZE;
- offset = VIRTIO_XDP_HEADROOM;
- } else {
- xdp_page = page;
- }
+ if (unlikely(vi->xdp_enabled)) {
+ struct bpf_prog *xdp_prog;
- data = page_address(xdp_page) + offset;
- err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz,
- &num_buf, &xdp_frags_truesz, stats);
- if (unlikely(err))
- goto err_xdp_frags;
-
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
- stats->xdp_packets++;
-
- switch (act) {
- case XDP_PASS:
- head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
- if (unlikely(!head_skb))
- goto err_xdp_frags;
-
- if (unlikely(xdp_page != page))
- put_page(page);
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(rq->xdp_prog);
+ if (xdp_prog) {
+ head_skb = receive_mergeable_xdp(dev, vi, rq, xdp_prog, buf, ctx,
+ len, xdp_xmit, stats);
rcu_read_unlock();
return head_skb;
- case XDP_TX:
- stats->xdp_tx++;
- xdpf = xdp_convert_buff_to_frame(&xdp);
- if (unlikely(!xdpf)) {
- netdev_dbg(dev, "convert buff to frame failed for xdp\n");
- goto err_xdp_frags;
- }
- err = virtnet_xdp_xmit(dev, 1, &xdpf, 0);
- if (unlikely(!err)) {
- xdp_return_frame_rx_napi(xdpf);
- } else if (unlikely(err < 0)) {
- trace_xdp_exception(vi->dev, xdp_prog, act);
- goto err_xdp_frags;
- }
- *xdp_xmit |= VIRTIO_XDP_TX;
- if (unlikely(xdp_page != page))
- put_page(page);
- rcu_read_unlock();
- goto xdp_xmit;
- case XDP_REDIRECT:
- stats->xdp_redirects++;
- err = xdp_do_redirect(dev, &xdp, xdp_prog);
- if (err)
- goto err_xdp_frags;
- *xdp_xmit |= VIRTIO_XDP_REDIR;
- if (unlikely(xdp_page != page))
- put_page(page);
- rcu_read_unlock();
- goto xdp_xmit;
- default:
- bpf_warn_invalid_xdp_action(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_ABORTED:
- trace_xdp_exception(vi->dev, xdp_prog, act);
- fallthrough;
- case XDP_DROP:
- goto err_xdp_frags;
}
-err_xdp_frags:
- if (unlikely(xdp_page != page))
- __free_pages(xdp_page, 0);
-
- if (xdp_buff_has_frags(&xdp)) {
- shinfo = xdp_get_shared_info_from_buff(&xdp);
- for (i = 0; i < shinfo->nr_frags; i++) {
- xdp_page = skb_frag_page(&shinfo->frags[i]);
- put_page(xdp_page);
- }
- }
-
- goto err_xdp;
+ rcu_read_unlock();
}
- rcu_read_unlock();
-skip_xdp:
head_skb = page_to_skb(vi, rq, page, offset, len, truesize, headroom);
curr_skb = head_skb;
@@ -1408,27 +1531,13 @@ skip_xdp:
ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len);
return head_skb;
-err_xdp:
- rcu_read_unlock();
- stats->xdp_drops++;
err_skb:
put_page(page);
- while (num_buf-- > 1) {
- buf = virtqueue_get_buf(rq->vq, &len);
- if (unlikely(!buf)) {
- pr_debug("%s: rx error: %d buffers missing\n",
- dev->name, num_buf);
- dev->stats.rx_length_errors++;
- break;
- }
- stats->bytes += len;
- page = virt_to_head_page(buf);
- put_page(page);
- }
+ mergeable_buf_free(rq, num_buf, dev, stats);
+
err_buf:
stats->drops++;
dev_kfree_skb(head_skb);
-xdp_xmit:
return NULL;
}
@@ -2652,7 +2761,7 @@ static void virtnet_init_default_rss(struct virtnet_info *vi)
vi->ctrl->rss.indirection_table[i] = indir_val;
}
- vi->ctrl->rss.max_tx_vq = vi->curr_queue_pairs;
+ vi->ctrl->rss.max_tx_vq = vi->has_rss ? vi->curr_queue_pairs : 0;
vi->ctrl->rss.hash_key_length = vi->rss_key_size;
netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size);
@@ -4122,6 +4231,8 @@ static int virtnet_probe(struct virtio_device *vdev)
virtio_device_ready(vdev);
+ _virtnet_set_queues(vi, vi->curr_queue_pairs);
+
/* a random MAC address has been assigned, notify the device.
* We don't fail probe if VIRTIO_NET_F_CTRL_MAC_ADDR is not there
* because many devices work fine without getting MAC explicitly
@@ -4148,8 +4259,6 @@ static int virtnet_probe(struct virtio_device *vdev)
goto free_unregister_netdev;
}
- virtnet_set_queues(vi, vi->curr_queue_pairs);
-
/* Assume link up if device can't report link status,
otherwise get link status from config. */
netif_carrier_off(dev);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index f2b76ee866a4..7fa74b8b2100 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -686,9 +686,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
- __skb_frag_set_page(frag, rbi->page);
- skb_frag_off_set(frag, 0);
- skb_frag_size_set(frag, rcd->len);
+ skb_frag_fill_page_desc(frag, rbi->page, 0, rcd->len);
skb->data_len += rcd->len;
skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index bdb3a76a352e..6043e63b42f9 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -664,7 +664,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
- rcu_read_lock_bh();
+ rcu_read_lock();
nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
if (unlikely(!neigh))
@@ -672,10 +672,10 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
if (!IS_ERR(neigh)) {
sock_confirm_neigh(skb, neigh);
ret = neigh_output(neigh, skb, false);
- rcu_read_unlock_bh();
+ rcu_read_unlock();
return ret;
}
- rcu_read_unlock_bh();
+ rcu_read_unlock();
IP6_INC_STATS(dev_net(dst->dev),
ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -889,7 +889,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
}
}
- rcu_read_lock_bh();
+ rcu_read_lock();
neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
if (!IS_ERR(neigh)) {
@@ -898,11 +898,11 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
sock_confirm_neigh(skb, neigh);
/* if crossing protocols, can not use the cached header */
ret = neigh_output(neigh, skb, is_v6gw);
- rcu_read_unlock_bh();
+ rcu_read_unlock();
return ret;
}
- rcu_read_unlock_bh();
+ rcu_read_unlock();
vrf_tx_error(skb->dev, skb);
return -EINVAL;
}
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 561fe1b314f5..c9a9373733c0 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -623,6 +623,32 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
return 1;
}
+static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+{
+ struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+ /* Need to have Next Protocol set for interfaces in GPE mode. */
+ if (!gpe->np_applied)
+ return false;
+ /* "The initial version is 0. If a receiver does not support the
+ * version indicated it MUST drop the packet.
+ */
+ if (gpe->version != 0)
+ return false;
+ /* "When the O bit is set to 1, the packet is an OAM packet and OAM
+ * processing MUST occur." However, we don't implement OAM
+ * processing, thus drop the packet.
+ */
+ if (gpe->oam_flag)
+ return false;
+
+ *protocol = tun_p_to_eth_p(gpe->next_protocol);
+ if (!*protocol)
+ return false;
+
+ return true;
+}
+
static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
unsigned int off,
struct vxlanhdr *vh, size_t hdrlen,
@@ -649,26 +675,24 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
return vh;
}
-static struct sk_buff *vxlan_gro_receive(struct sock *sk,
- struct list_head *head,
- struct sk_buff *skb)
+static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb,
+ struct gro_remcsum *grc)
{
- struct sk_buff *pp = NULL;
struct sk_buff *p;
struct vxlanhdr *vh, *vh2;
unsigned int hlen, off_vx;
- int flush = 1;
struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
__be32 flags;
- struct gro_remcsum grc;
- skb_gro_remcsum_init(&grc);
+ skb_gro_remcsum_init(grc);
off_vx = skb_gro_offset(skb);
hlen = off_vx + sizeof(*vh);
vh = skb_gro_header(skb, hlen, off_vx);
if (unlikely(!vh))
- goto out;
+ return NULL;
skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
@@ -676,12 +700,12 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
- vh->vx_vni, &grc,
+ vh->vx_vni, grc,
!!(vs->flags &
VXLAN_F_REMCSUM_NOPARTIAL));
if (!vh)
- goto out;
+ return NULL;
}
skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
@@ -698,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
}
}
- pp = call_gro_receive(eth_gro_receive, head, skb);
- flush = 0;
+ return vh;
+}
-out:
+static struct sk_buff *vxlan_gro_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb)
+{
+ struct sk_buff *pp = NULL;
+ struct gro_remcsum grc;
+ int flush = 1;
+
+ if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
+ pp = call_gro_receive(eth_gro_receive, head, skb);
+ flush = 0;
+ }
skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
+ return pp;
+}
+
+static struct sk_buff *vxlan_gpe_gro_receive(struct sock *sk,
+ struct list_head *head,
+ struct sk_buff *skb)
+{
+ const struct packet_offload *ptype;
+ struct sk_buff *pp = NULL;
+ struct gro_remcsum grc;
+ struct vxlanhdr *vh;
+ __be16 protocol;
+ int flush = 1;
+ vh = vxlan_gro_prepare_receive(sk, head, skb, &grc);
+ if (vh) {
+ if (!vxlan_parse_gpe_proto(vh, &protocol))
+ goto out;
+ ptype = gro_find_receive_by_type(protocol);
+ if (!ptype)
+ goto out;
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+ flush = 0;
+ }
+out:
+ skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
return pp;
}
@@ -715,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
}
+static int vxlan_gpe_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+ struct vxlanhdr *vh = (struct vxlanhdr *)(skb->data + nhoff);
+ const struct packet_offload *ptype;
+ int err = -ENOSYS;
+ __be16 protocol;
+
+ if (!vxlan_parse_gpe_proto(vh, &protocol))
+ return err;
+ ptype = gro_find_complete_by_type(protocol);
+ if (ptype)
+ err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
+ return err;
+}
+
static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
__u16 state, __be32 src_vni,
__u16 ndm_flags)
@@ -1525,35 +1600,6 @@ out:
unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
}
-static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
- __be16 *protocol,
- struct sk_buff *skb, u32 vxflags)
-{
- struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
-
- /* Need to have Next Protocol set for interfaces in GPE mode. */
- if (!gpe->np_applied)
- return false;
- /* "The initial version is 0. If a receiver does not support the
- * version indicated it MUST drop the packet.
- */
- if (gpe->version != 0)
- return false;
- /* "When the O bit is set to 1, the packet is an OAM packet and OAM
- * processing MUST occur." However, we don't implement OAM
- * processing, thus drop the packet.
- */
- if (gpe->oam_flag)
- return false;
-
- *protocol = tun_p_to_eth_p(gpe->next_protocol);
- if (!*protocol)
- return false;
-
- unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
- return true;
-}
-
static bool vxlan_set_mac(struct vxlan_dev *vxlan,
struct vxlan_sock *vs,
struct sk_buff *skb, __be32 vni)
@@ -1655,8 +1701,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
* used by VXLAN extensions if explicitly requested.
*/
if (vs->flags & VXLAN_F_GPE) {
- if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+ if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
goto drop;
+ unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
raw_proto = true;
}
@@ -2352,7 +2399,8 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
#endif
/* Bypass encapsulation if the destination is local */
if (rt_flags & RTCF_LOCAL &&
- !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+ !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
+ vxlan->cfg.flags & VXLAN_F_LOCALBYPASS) {
struct vxlan_dev *dst_vxlan;
dst_release(dst);
@@ -2515,7 +2563,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
}
ndst = &rt->dst;
- err = skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM,
+ err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
netif_is_any_bridge_port(dev));
if (err < 0) {
goto tx_error;
@@ -2576,7 +2624,8 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
goto out_unlock;
}
- err = skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM,
+ err = skb_tunnel_check_pmtu(skb, ndst,
+ vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
netif_is_any_bridge_port(dev));
if (err < 0) {
goto tx_error;
@@ -2988,14 +3037,12 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
struct vxlan_rdst *dst = &vxlan->default_dst;
struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
dst->remote_ifindex);
- bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
/* This check is different than dev->max_mtu, because it looks at
* the lowerdev->mtu, rather than the static dev->max_mtu
*/
if (lowerdev) {
- int max_mtu = lowerdev->mtu -
- (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+ int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
if (new_mtu > max_mtu)
return -EINVAL;
}
@@ -3172,6 +3219,7 @@ static void vxlan_raw_setup(struct net_device *dev)
}
static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
+ [IFLA_VXLAN_UNSPEC] = { .strict_start_type = IFLA_VXLAN_LOCALBYPASS },
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .len = sizeof_field(struct iphdr, daddr) },
[IFLA_VXLAN_GROUP6] = { .len = sizeof(struct in6_addr) },
@@ -3202,6 +3250,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG },
[IFLA_VXLAN_DF] = { .type = NLA_U8 },
[IFLA_VXLAN_VNIFILTER] = { .type = NLA_U8 },
+ [IFLA_VXLAN_LOCALBYPASS] = NLA_POLICY_MAX(NLA_U8, 1),
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -3376,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
tunnel_cfg.encap_rcv = vxlan_rcv;
tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
tunnel_cfg.encap_destroy = NULL;
- tunnel_cfg.gro_receive = vxlan_gro_receive;
- tunnel_cfg.gro_complete = vxlan_gro_complete;
+ if (vs->flags & VXLAN_F_GPE) {
+ tunnel_cfg.gro_receive = vxlan_gpe_gro_receive;
+ tunnel_cfg.gro_complete = vxlan_gpe_gro_complete;
+ } else {
+ tunnel_cfg.gro_receive = vxlan_gro_receive;
+ tunnel_cfg.gro_complete = vxlan_gro_complete;
+ }
setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
@@ -3641,11 +3695,11 @@ static void vxlan_config_apply(struct net_device *dev,
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_rdst *dst = &vxlan->default_dst;
unsigned short needed_headroom = ETH_HLEN;
- bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6);
int max_mtu = ETH_MAX_MTU;
+ u32 flags = conf->flags;
if (!changelink) {
- if (conf->flags & VXLAN_F_GPE)
+ if (flags & VXLAN_F_GPE)
vxlan_raw_setup(dev);
else
vxlan_ether_setup(dev);
@@ -3670,8 +3724,7 @@ static void vxlan_config_apply(struct net_device *dev,
dev->needed_tailroom = lowerdev->needed_tailroom;
- max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
- VXLAN_HEADROOM);
+ max_mtu = lowerdev->mtu - vxlan_headroom(flags);
if (max_mtu < ETH_MIN_MTU)
max_mtu = ETH_MIN_MTU;
@@ -3682,10 +3735,9 @@ static void vxlan_config_apply(struct net_device *dev,
if (dev->mtu > max_mtu)
dev->mtu = max_mtu;
- if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
- needed_headroom += VXLAN6_HEADROOM;
- else
- needed_headroom += VXLAN_HEADROOM;
+ if (flags & VXLAN_F_COLLECT_METADATA)
+ flags |= VXLAN_F_IPV6;
+ needed_headroom += vxlan_headroom(flags);
dev->needed_headroom = needed_headroom;
memcpy(&vxlan->cfg, conf, sizeof(*conf));
@@ -4011,6 +4063,17 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX;
}
+ if (data[IFLA_VXLAN_LOCALBYPASS]) {
+ err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LOCALBYPASS,
+ VXLAN_F_LOCALBYPASS, changelink,
+ true, extack);
+ if (err)
+ return err;
+ } else if (!changelink) {
+ /* default to local bypass on a new device */
+ conf->flags |= VXLAN_F_LOCALBYPASS;
+ }
+
if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
VXLAN_F_UDP_ZERO_CSUM6_TX, changelink,
@@ -4232,6 +4295,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBYPASS */
0;
}
@@ -4308,7 +4372,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX,
!!(vxlan->cfg.flags & VXLAN_F_REMCSUM_TX)) ||
nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX,
- !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)))
+ !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)) ||
+ nla_put_u8(skb, IFLA_VXLAN_LOCALBYPASS,
+ !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS)))
goto nla_put_failure;
if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports))
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index a3de081cda5e..c3ff30ab782e 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -713,6 +713,12 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
return vninode;
}
+static void vxlan_vni_free(struct vxlan_vni_node *vninode)
+{
+ free_percpu(vninode->stats);
+ kfree(vninode);
+}
+
static int vxlan_vni_add(struct vxlan_dev *vxlan,
struct vxlan_vni_group *vg,
u32 vni, union vxlan_addr *group,
@@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
&vninode->vnode,
vxlan_vni_rht_params);
if (err) {
- kfree(vninode);
+ vxlan_vni_free(vninode);
return err;
}
@@ -763,8 +769,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu)
struct vxlan_vni_node *v;
v = container_of(rcu, struct vxlan_vni_node, rcu);
- free_percpu(v->stats);
- kfree(v);
+ vxlan_vni_free(v);
}
static int vxlan_vni_del(struct vxlan_dev *vxlan,
diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index 5bf7822c53f1..0ba714ca5185 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -6,7 +6,7 @@
#include "allowedips.h"
#include "peer.h"
-enum { MAX_ALLOWEDIPS_BITS = 128 };
+enum { MAX_ALLOWEDIPS_DEPTH = 129 };
static struct kmem_cache *node_cache;
@@ -42,7 +42,7 @@ static void push_rcu(struct allowedips_node **stack,
struct allowedips_node __rcu *p, unsigned int *len)
{
if (rcu_access_pointer(p)) {
- if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS))
+ if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_DEPTH))
return;
stack[(*len)++] = rcu_dereference_raw(p);
}
@@ -55,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu)
static void root_free_rcu(struct rcu_head *rcu)
{
- struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = {
+ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
container_of(rcu, struct allowedips_node, rcu) };
unsigned int len = 1;
@@ -68,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu)
static void root_remove_peer_lists(struct allowedips_node *root)
{
- struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root };
+ struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { root };
unsigned int len = 1;
while (len > 0 && (node = stack[--len])) {
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index d58e9f818d3b..258dcc103921 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -20,6 +20,7 @@
#include <linux/icmp.h>
#include <linux/suspend.h>
#include <net/dst_metadata.h>
+#include <net/gso.h>
#include <net/icmp.h>
#include <net/rtnetlink.h>
#include <net/ip_tunnels.h>
diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c
index 43c8c84e7ea8..6d1bd9f52d02 100644
--- a/drivers/net/wireguard/netlink.c
+++ b/drivers/net/wireguard/netlink.c
@@ -546,6 +546,7 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
u8 *private_key = nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]);
u8 public_key[NOISE_PUBLIC_KEY_LEN];
struct wg_peer *peer, *temp;
+ bool send_staged_packets;
if (!crypto_memneq(wg->static_identity.static_private,
private_key, NOISE_PUBLIC_KEY_LEN))
@@ -564,14 +565,17 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info)
}
down_write(&wg->static_identity.lock);
- wg_noise_set_static_identity_private_key(&wg->static_identity,
- private_key);
- list_for_each_entry_safe(peer, temp, &wg->peer_list,
- peer_list) {
+ send_staged_packets = !wg->static_identity.has_identity && netif_running(wg->dev);
+ wg_noise_set_static_identity_private_key(&wg->static_identity, private_key);
+ send_staged_packets = send_staged_packets && wg->static_identity.has_identity;
+
+ wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
+ list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) {
wg_noise_precompute_static_static(peer);
wg_noise_expire_current_peer_keypairs(peer);
+ if (send_staged_packets)
+ wg_packet_send_staged_packets(peer);
}
- wg_cookie_checker_precompute_device_keys(&wg->cookie_checker);
up_write(&wg->static_identity.lock);
}
skip_set_private_key:
diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c
index 8084e7408c0a..26d235d15235 100644
--- a/drivers/net/wireguard/queueing.c
+++ b/drivers/net/wireguard/queueing.c
@@ -28,6 +28,7 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
int ret;
memset(queue, 0, sizeof(*queue));
+ queue->last_cpu = -1;
ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL);
if (ret)
return ret;
diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h
index 125284b346a7..1ea4f874e367 100644
--- a/drivers/net/wireguard/queueing.h
+++ b/drivers/net/wireguard/queueing.h
@@ -117,20 +117,17 @@ static inline int wg_cpumask_choose_online(int *stored_cpu, unsigned int id)
return cpu;
}
-/* This function is racy, in the sense that next is unlocked, so it could return
- * the same CPU twice. A race-free version of this would be to instead store an
- * atomic sequence number, do an increment-and-return, and then iterate through
- * every possible CPU until we get to that index -- choose_cpu. However that's
- * a bit slower, and it doesn't seem like this potential race actually
- * introduces any performance loss, so we live with it.
+/* This function is racy, in the sense that it's called while last_cpu is
+ * unlocked, so it could return the same CPU twice. Adding locking or using
+ * atomic sequence numbers is slower though, and the consequences of racing are
+ * harmless, so live with it.
*/
-static inline int wg_cpumask_next_online(int *next)
+static inline int wg_cpumask_next_online(int *last_cpu)
{
- int cpu = *next;
-
- while (unlikely(!cpumask_test_cpu(cpu, cpu_online_mask)))
- cpu = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits;
- *next = cpumask_next(cpu, cpu_online_mask) % nr_cpumask_bits;
+ int cpu = cpumask_next(*last_cpu, cpu_online_mask);
+ if (cpu >= nr_cpu_ids)
+ cpu = cpumask_first(cpu_online_mask);
+ *last_cpu = cpu;
return cpu;
}
@@ -159,7 +156,7 @@ static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue)
static inline int wg_queue_enqueue_per_device_and_peer(
struct crypt_queue *device_queue, struct prev_queue *peer_queue,
- struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu)
+ struct sk_buff *skb, struct workqueue_struct *wq)
{
int cpu;
@@ -173,7 +170,7 @@ static inline int wg_queue_enqueue_per_device_and_peer(
/* Then we queue it up in the device queue, which consumes the
* packet as soon as it can.
*/
- cpu = wg_cpumask_next_online(next_cpu);
+ cpu = wg_cpumask_next_online(&device_queue->last_cpu);
if (unlikely(ptr_ring_produce_bh(&device_queue->ring, skb)))
return -EPIPE;
queue_work_on(cpu, wq, &per_cpu_ptr(device_queue->worker, cpu)->work);
diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
index 7135d51d2d87..0b3f0c843550 100644
--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -524,7 +524,7 @@ static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb)
goto err;
ret = wg_queue_enqueue_per_device_and_peer(&wg->decrypt_queue, &peer->rx_queue, skb,
- wg->packet_crypt_wq, &wg->decrypt_queue.last_cpu);
+ wg->packet_crypt_wq);
if (unlikely(ret == -EPIPE))
wg_queue_enqueue_per_peer_rx(skb, PACKET_STATE_DEAD);
if (likely(!ret || ret == -EPIPE)) {
diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c
index 78ebe2892a78..3d1f64ff2e12 100644
--- a/drivers/net/wireguard/selftest/allowedips.c
+++ b/drivers/net/wireguard/selftest/allowedips.c
@@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void)
wg_allowedips_remove_by_peer(&t, a, &mutex);
test_negative(4, a, 192, 168, 0, 1);
- /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node
+ /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node
* if something goes wrong.
*/
- for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) {
- part = cpu_to_be64(~(1LLU << (i % 64)));
- memset(&ip, 0xff, 16);
- memcpy((u8 *)&ip + (i < 64) * 8, &part, 8);
+ for (i = 0; i < 64; ++i) {
+ part = cpu_to_be64(~0LLU << i);
+ memset(&ip, 0xff, 8);
+ memcpy((u8 *)&ip + 8, &part, 8);
+ wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
+ memcpy(&ip, &part, 8);
+ memset((u8 *)&ip + 8, 0, 8);
wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
}
-
+ memset(&ip, 0, 16);
+ wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
wg_allowedips_free(&t, &mutex);
wg_allowedips_init(&t);
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index 5368f7c35b4b..95c853b59e1d 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -318,7 +318,7 @@ static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first)
goto err;
ret = wg_queue_enqueue_per_device_and_peer(&wg->encrypt_queue, &peer->tx_queue, first,
- wg->packet_crypt_wq, &wg->encrypt_queue.last_cpu);
+ wg->packet_crypt_wq);
if (unlikely(ret == -EPIPE))
wg_queue_enqueue_per_peer_tx(first, PACKET_STATE_DEAD);
err:
diff --git a/drivers/net/wireguard/timers.c b/drivers/net/wireguard/timers.c
index 53d8a57a0dfa..968bdb4df0b3 100644
--- a/drivers/net/wireguard/timers.c
+++ b/drivers/net/wireguard/timers.c
@@ -234,10 +234,10 @@ void wg_timers_init(struct wg_peer *peer)
void wg_timers_stop(struct wg_peer *peer)
{
- del_timer_sync(&peer->timer_retransmit_handshake);
- del_timer_sync(&peer->timer_send_keepalive);
- del_timer_sync(&peer->timer_new_handshake);
- del_timer_sync(&peer->timer_zero_key_material);
- del_timer_sync(&peer->timer_persistent_keepalive);
+ timer_delete_sync(&peer->timer_retransmit_handshake);
+ timer_delete_sync(&peer->timer_send_keepalive);
+ timer_delete_sync(&peer->timer_new_handshake);
+ timer_delete_sync(&peer->timer_zero_key_material);
+ timer_delete_sync(&peer->timer_persistent_keepalive);
flush_work(&peer->clear_peer_work);
}
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index f0c615fa5614..4a006fb4d424 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -27,7 +27,7 @@ MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
{
- return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
+ return &ath10k_pci_priv(ar)->ahb[0];
}
static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value)
@@ -816,23 +816,13 @@ err_resource_deinit:
err_core_destroy:
ath10k_core_destroy(ar);
- platform_set_drvdata(pdev, NULL);
return ret;
}
-static int ath10k_ahb_remove(struct platform_device *pdev)
+static void ath10k_ahb_remove(struct platform_device *pdev)
{
struct ath10k *ar = platform_get_drvdata(pdev);
- struct ath10k_ahb *ar_ahb;
-
- if (!ar)
- return -EINVAL;
-
- ar_ahb = ath10k_ahb_priv(ar);
-
- if (!ar_ahb)
- return -EINVAL;
ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n");
@@ -844,10 +834,6 @@ static int ath10k_ahb_remove(struct platform_device *pdev)
ath10k_ahb_clock_disable(ar);
ath10k_ahb_resource_deinit(ar);
ath10k_core_destroy(ar);
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
}
static struct platform_driver ath10k_ahb_driver = {
@@ -856,7 +842,7 @@ static struct platform_driver ath10k_ahb_driver = {
.of_match_table = ath10k_ahb_of_match,
},
.probe = ath10k_ahb_probe,
- .remove = ath10k_ahb_remove,
+ .remove_new = ath10k_ahb_remove,
};
int ath10k_ahb_init(void)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 5eb131ab916f..6cdb225b7eac 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2504,7 +2504,6 @@ EXPORT_SYMBOL(ath10k_core_napi_sync_disable);
static void ath10k_core_restart(struct work_struct *work)
{
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
- struct ath10k_vif *arvif;
int ret;
set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2543,14 +2542,6 @@ static void ath10k_core_restart(struct work_struct *work)
ar->state = ATH10K_STATE_RESTARTING;
ath10k_halt(ar);
ath10k_scan_finish(ar);
- if (ar->hw_params.hw_restart_disconnect) {
- list_for_each_entry(arvif, &ar->arvifs, list) {
- if (arvif->is_up &&
- arvif->vdev_type == WMI_VDEV_TYPE_STA)
- ieee80211_hw_restart_disconnect(arvif->vif);
- }
- }
-
ieee80211_restart_hw(ar->hw);
break;
case ATH10K_STATE_OFF:
@@ -3643,6 +3634,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->dump_mutex);
spin_lock_init(&ar->data_lock);
+ for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ spin_lock_init(&ar->queue_lock[ac]);
+
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f5de8ce8fb45..4b5239de4018 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1170,6 +1170,9 @@ struct ath10k {
/* protects shared structure data */
spinlock_t data_lock;
+ /* serialize wake_tx_queue calls per ac */
+ spinlock_t queue_lock[IEEE80211_NUM_ACS];
+
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index b9aea1510f7b..f9518e1c9903 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -293,8 +293,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
+ num_peers = list_count_nodes(&ar->debug.fw_stats.peers);
+ num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index c051a22fce14..e0c9f45e7476 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -707,7 +707,7 @@ struct htt_rx_indication_prefix {
__le16 fw_rx_desc_bytes;
u8 pad0;
u8 pad1;
-};
+} __packed;
struct htt_rx_indication {
struct htt_rx_indication_hdr hdr;
@@ -1565,7 +1565,7 @@ struct htt_tx_fetch_ind {
/* ath10k_htt_get_tx_fetch_ind_resp_ids() */
DECLARE_FLEX_ARRAY(__le32, resp_ids);
DECLARE_FLEX_ARRAY(struct htt_tx_fetch_record, records);
- };
+ } __packed;
} __packed;
static inline void *
@@ -1723,7 +1723,7 @@ struct htt_resp {
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
struct htt_peer_tx_stats peer_tx_stats;
- };
+ } __packed;
} __packed;
/*** host side structures follow ***/
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 7675858f069b..03e7bc5b6c0b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4732,13 +4732,14 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
{
struct ath10k *ar = hw->priv;
int ret;
- u8 ac;
+ u8 ac = txq->ac;
ath10k_htt_tx_txq_update(hw, txq);
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
return;
- ac = txq->ac;
+ spin_lock_bh(&ar->queue_lock[ac]);
+
ieee80211_txq_schedule_start(hw, ac);
txq = ieee80211_next_txq(hw, ac);
if (!txq)
@@ -4753,6 +4754,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
ath10k_htt_tx_txq_update(hw, txq);
out:
ieee80211_txq_schedule_end(hw, ac);
+ spin_unlock_bh(&ar->queue_lock[ac]);
}
/* Must not be called with conf_mutex held as workers can use that also. */
@@ -8107,6 +8109,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
{
struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif;
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
return;
@@ -8121,6 +8124,12 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
ar->state = ATH10K_STATE_ON;
ieee80211_wake_queues(ar->hw);
clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags);
+ if (ar->hw_params.hw_restart_disconnect) {
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ ieee80211_hw_restart_disconnect(arvif->vif);
+ }
+ }
}
mutex_unlock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index a7f44f6335fb..73463ded4204 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -1963,8 +1963,9 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
ath10k_pci_irq_enable(ar);
ath10k_pci_rx_post(ar);
- pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
- ar_pci->link_ctl);
+ pcie_capability_clear_and_set_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC,
+ ar_pci->link_ctl & PCI_EXP_LNKCTL_ASPMC);
return 0;
}
@@ -2821,8 +2822,8 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar,
pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL,
&ar_pci->link_ctl);
- pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
- ar_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+ pcie_capability_clear_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC);
/*
* Bring the target up cleanly.
@@ -3816,7 +3817,7 @@ static void __exit ath10k_pci_exit(void)
module_exit(ath10k_pci_exit);
MODULE_AUTHOR("Qualcomm Atheros");
-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN PCIe/AHB devices");
+MODULE_DESCRIPTION("Driver support for Qualcomm Atheros PCIe/AHB 802.11ac WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
/* QCA988x 2.0 firmware files */
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 038c5903c0dc..52c1a3de8da6 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -1082,8 +1082,7 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
if (ret)
goto err;
- qmi->event_wq = alloc_workqueue("ath10k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ qmi->event_wq = alloc_ordered_workqueue("ath10k_qmi_driver_event", 0);
if (!qmi->event_wq) {
ath10k_err(ar, "failed to allocate workqueue\n");
ret = -EFAULT;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 5128a452c65f..26214c00cd0d 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1848,7 +1848,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar)
return 0;
}
-static int ath10k_snoc_remove(struct platform_device *pdev)
+static void ath10k_snoc_remove(struct platform_device *pdev)
{
struct ath10k *ar = platform_get_drvdata(pdev);
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1861,8 +1861,6 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
wait_for_completion_timeout(&ar->driver_recovery, 3 * HZ);
ath10k_snoc_free_resources(ar);
-
- return 0;
}
static void ath10k_snoc_shutdown(struct platform_device *pdev)
@@ -1875,8 +1873,8 @@ static void ath10k_snoc_shutdown(struct platform_device *pdev)
static struct platform_driver ath10k_snoc_driver = {
.probe = ath10k_snoc_probe,
- .remove = ath10k_snoc_remove,
- .shutdown = ath10k_snoc_shutdown,
+ .remove_new = ath10k_snoc_remove,
+ .shutdown = ath10k_snoc_shutdown,
.driver = {
.name = "ath10k_snoc",
.of_match_table = ath10k_snoc_dt_match,
diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
index b0067af685b1..3c482baacec1 100644
--- a/drivers/net/wireless/ath/ath10k/usb.c
+++ b/drivers/net/wireless/ath/ath10k/usb.c
@@ -1126,5 +1126,5 @@ static struct usb_driver ath10k_usb_driver = {
module_usb_driver(ath10k_usb_driver);
MODULE_AUTHOR("Atheros Communications, Inc.");
-MODULE_DESCRIPTION("Driver support for Qualcomm Atheros 802.11ac WLAN USB devices");
+MODULE_DESCRIPTION("Driver support for Qualcomm Atheros USB 802.11ac WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 980d4124fa28..05fa7d4c0e1a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -8164,28 +8164,6 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param)
return skb;
}
-size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head)
-{
- struct ath10k_fw_stats_peer *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath10k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
static void
ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev,
char *buf, u32 *length)
@@ -8462,8 +8440,8 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
@@ -8520,8 +8498,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
@@ -8668,8 +8646,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
goto unlock;
}
- num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
+ num_peers = list_count_nodes(&fw_stats->peers);
+ num_vdevs = list_count_nodes(&fw_stats->vdevs);
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 6de3cc4640a0..6d04a66fe5e0 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -7502,8 +7502,6 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar,
void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats,
char *buf);
-size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
-size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats,
char *buf);
diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 5cbba9a8b6ba..139da578831a 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
if (!irq_grp->napi_enabled) {
- dev_set_threaded(&irq_grp->napi_ndev, true);
napi_enable(&irq_grp->napi);
irq_grp->napi_enabled = true;
}
@@ -734,7 +733,7 @@ static int ath11k_ahb_hif_suspend(struct ath11k_base *ab)
return ret;
}
- ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device suspended\n");
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "device suspended\n");
return ret;
}
@@ -777,7 +776,7 @@ static int ath11k_ahb_hif_resume(struct ath11k_base *ab)
return -ETIMEDOUT;
}
- ath11k_dbg(ab, ATH11K_DBG_AHB, "ahb device resumed\n");
+ ath11k_dbg(ab, ATH11K_DBG_AHB, "device resumed\n");
return 0;
}
@@ -1127,6 +1126,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
switch (hw_rev) {
case ATH11K_HW_IPQ8074:
case ATH11K_HW_IPQ6018_HW10:
+ case ATH11K_HW_IPQ5018_HW10:
hif_ops = &ath11k_ahb_hif_ops_ipq8074;
pci_ops = NULL;
break;
@@ -1155,6 +1155,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ab->hif.ops = hif_ops;
ab->pdev = pdev;
ab->hw_rev = hw_rev;
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
platform_set_drvdata(pdev, ab);
ret = ath11k_pcic_register_pci_ops(ab, pci_ops);
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index f2da95fd4253..289d47ae92af 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -442,7 +442,7 @@ static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe)
}
while ((skb = __skb_dequeue(&list))) {
- ath11k_dbg(ab, ATH11K_DBG_AHB, "rx ce pipe %d len %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_CE, "rx ce pipe %d len %d\n",
pipe->pipe_num, skb->len);
pipe->recv_cb(ab, skb);
}
@@ -520,7 +520,7 @@ static void ath11k_ce_tx_process_cb(struct ath11k_ce_pipe *pipe)
}
while ((skb = __skb_dequeue(&list))) {
- ath11k_dbg(ab, ATH11K_DBG_AHB, "tx ce pipe %d len %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_CE, "tx ce pipe %d len %d\n",
pipe->pipe_num, skb->len);
pipe->send_cb(ab, skb);
}
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index b1b90bd34d67..bebfd342e28b 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -32,6 +32,10 @@ module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
+bool ath11k_ftm_mode;
+module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);
+MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
+
static const struct ath11k_hw_params ath11k_hw_params[] = {
{
.hw_rev = ATH11K_HW_IPQ8074,
@@ -664,6 +668,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.hal_params = &ath11k_hw_hal_params_ipq8074,
.single_pdev_only = false,
.cold_boot_calib = true,
+ .cbcal_restart_fw = true,
.fix_l1ss = true,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@@ -874,16 +879,16 @@ static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void
case ATH11K_SMBIOS_CC_ISO:
ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff;
ab->new_alpha2[1] = smbios->cc_code & 0xff;
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios cc_code %c%c\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios cc_code %c%c\n",
ab->new_alpha2[0], ab->new_alpha2[1]);
break;
case ATH11K_SMBIOS_CC_WW:
ab->new_alpha2[0] = '0';
ab->new_alpha2[1] = '0';
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios worldwide regdomain\n");
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios worldwide regdomain\n");
break;
default:
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot ignore smbios country code setting %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "ignore smbios country code setting %d\n",
smbios->country_code_flag);
break;
}
@@ -961,7 +966,8 @@ int ath11k_core_check_dt(struct ath11k_base *ab)
}
static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
- size_t name_len, bool with_variant)
+ size_t name_len, bool with_variant,
+ bool bus_type_mode)
{
/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
@@ -972,15 +978,20 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
switch (ab->id.bdf_search) {
case ATH11K_BDF_SEARCH_BUS_AND_BOARD:
- scnprintf(name, name_len,
- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
- ath11k_bus_str(ab->hif.bus),
- ab->id.vendor, ab->id.device,
- ab->id.subsystem_vendor,
- ab->id.subsystem_device,
- ab->qmi.target.chip_id,
- ab->qmi.target.board_id,
- variant);
+ if (bus_type_mode)
+ scnprintf(name, name_len,
+ "bus=%s",
+ ath11k_bus_str(ab->hif.bus));
+ else
+ scnprintf(name, name_len,
+ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
+ ath11k_bus_str(ab->hif.bus),
+ ab->id.vendor, ab->id.device,
+ ab->id.subsystem_vendor,
+ ab->id.subsystem_device,
+ ab->qmi.target.chip_id,
+ ab->qmi.target.board_id,
+ variant);
break;
default:
scnprintf(name, name_len,
@@ -991,7 +1002,7 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
break;
}
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board name '%s'\n", name);
return 0;
}
@@ -999,13 +1010,19 @@ static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
size_t name_len)
{
- return __ath11k_core_create_board_name(ab, name, name_len, true);
+ return __ath11k_core_create_board_name(ab, name, name_len, true, false);
}
static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name,
size_t name_len)
{
- return __ath11k_core_create_board_name(ab, name, name_len, false);
+ return __ath11k_core_create_board_name(ab, name, name_len, false, false);
+}
+
+static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name,
+ size_t name_len)
+{
+ return __ath11k_core_create_board_name(ab, name, name_len, false, true);
}
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
@@ -1024,7 +1041,7 @@ const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
if (ret)
return ERR_PTR(ret);
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "firmware request %s size %zu\n",
path, fw->size);
return fw;
@@ -1085,7 +1102,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
name_match_found = true;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot found match %s for name '%s'",
+ "found match %s for name '%s'",
ath11k_bd_ie_type_str(ie_id),
boardname);
} else if (board_ie_id == data_id) {
@@ -1094,7 +1111,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
goto next;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot found %s for '%s'",
+ "found %s for '%s'",
ath11k_bd_ie_type_str(ie_id),
boardname);
@@ -1309,7 +1326,7 @@ success:
int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
{
- char boardname[BOARD_NAME_SIZE];
+ char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];
int ret;
ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
@@ -1326,6 +1343,21 @@ int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd
if (!ret)
goto exit;
+ ret = ath11k_core_create_bus_type_board_name(ab, default_boardname,
+ BOARD_NAME_SIZE);
+ if (ret) {
+ ath11k_dbg(ab, ATH11K_DBG_BOOT,
+ "failed to create default board name for regdb: %d", ret);
+ goto exit;
+ }
+
+ ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname,
+ ATH11K_BD_IE_REGDB,
+ ATH11K_BD_IE_REGDB_NAME,
+ ATH11K_BD_IE_REGDB_DATA);
+ if (!ret)
+ goto exit;
+
ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
if (ret)
ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
@@ -1354,6 +1386,11 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
{
int ret;
+ if (ath11k_ftm_mode) {
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM;
+ ath11k_info(ab, "Booting in factory test mode\n");
+ }
+
ret = ath11k_qmi_init_service(ab);
if (ret) {
ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
@@ -1580,7 +1617,7 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
{
int ret;
- ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL);
+ ret = ath11k_core_start_firmware(ab, ab->fw_mode);
if (ret) {
ath11k_err(ab, "failed to start firmware: %d\n", ret);
return ret;
@@ -1745,7 +1782,8 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
ar = pdev->ar;
- if (!ar || ar->state == ATH11K_STATE_OFF)
+ if (!ar || ar->state == ATH11K_STATE_OFF ||
+ ar->state == ATH11K_STATE_FTM)
continue;
ieee80211_stop_queues(ar->hw);
@@ -1814,7 +1852,12 @@ static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
ath11k_warn(ab,
"device is wedged, will not restart radio %d\n", i);
break;
+ case ATH11K_STATE_FTM:
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "fw mode reset done radio %d\n", i);
+ break;
}
+
mutex_unlock(&ar->conf_mutex);
}
complete(&ab->driver_recovery);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 0830276e5028..9d15b4390b9c 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_CORE_H
@@ -52,6 +52,7 @@
#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_"
extern unsigned int ath11k_frame_mode;
+extern bool ath11k_ftm_mode;
#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ)
@@ -277,6 +278,7 @@ enum ath11k_dev_flags {
ATH11K_FLAG_FIXED_MEM_RGN,
ATH11K_FLAG_DEVICE_INIT_DONE,
ATH11K_FLAG_MULTI_MSI_VECTORS,
+ ATH11K_FLAG_FTM_SEGMENTED,
};
enum ath11k_monitor_flags {
@@ -530,6 +532,7 @@ enum ath11k_state {
ATH11K_STATE_RESTARTING,
ATH11K_STATE_RESTARTED,
ATH11K_STATE_WEDGED,
+ ATH11K_STATE_FTM,
/* Add other states as required */
};
@@ -709,6 +712,8 @@ struct ath11k {
u32 last_ppdu_id;
u32 cached_ppdu_id;
int monitor_vdev_id;
+ struct completion fw_mode_reset;
+ u8 ftm_msgref;
#ifdef CONFIG_ATH11K_DEBUGFS
struct ath11k_debug debug;
#endif
@@ -838,6 +843,7 @@ struct ath11k_msi_config {
/* Master structure to hold the hw data which may be used in core module */
struct ath11k_base {
enum ath11k_hw_rev hw_rev;
+ enum ath11k_firmware_mode fw_mode;
struct platform_device *pdev;
struct device *dev;
struct ath11k_qmi qmi;
@@ -978,6 +984,14 @@ struct ath11k_base {
const struct ath11k_pci_ops *ops;
} pci;
+#ifdef CONFIG_NL80211_TESTMODE
+ struct {
+ u32 data_pos;
+ u32 expected_seq;
+ u8 *eventdata;
+ } testmode;
+#endif
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
diff --git a/drivers/net/wireless/ath/ath11k/debug.c b/drivers/net/wireless/ath/ath11k/debug.c
index 958d87429062..f5c8a34c8802 100644
--- a/drivers/net/wireless/ath/ath11k/debug.c
+++ b/drivers/net/wireless/ath/ath11k/debug.c
@@ -66,7 +66,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
vaf.va = &args;
if (ath11k_debug_mask & mask)
- dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
+ dev_printk(KERN_DEBUG, ab->dev, "%s %pV", ath11k_dbg_str(mask), &vaf);
trace_ath11k_log_dbg(ab, mask, &vaf);
diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless/ath/ath11k/debug.h
index 91545640c47b..9c52804ef8ac 100644
--- a/drivers/net/wireless/ath/ath11k/debug.h
+++ b/drivers/net/wireless/ath/ath11k/debug.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _ATH11K_DEBUG_H_
@@ -21,13 +22,57 @@ enum ath11k_debug_mask {
ATH11K_DBG_MGMT = 0x00000100,
ATH11K_DBG_REG = 0x00000200,
ATH11K_DBG_TESTMODE = 0x00000400,
- ATH11k_DBG_HAL = 0x00000800,
+ ATH11K_DBG_HAL = 0x00000800,
ATH11K_DBG_PCI = 0x00001000,
ATH11K_DBG_DP_TX = 0x00002000,
ATH11K_DBG_DP_RX = 0x00004000,
- ATH11K_DBG_ANY = 0xffffffff,
+ ATH11K_DBG_CE = 0x00008000,
};
+static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
+{
+ switch (mask) {
+ case ATH11K_DBG_AHB:
+ return "ahb";
+ case ATH11K_DBG_WMI:
+ return "wmi";
+ case ATH11K_DBG_HTC:
+ return "htc";
+ case ATH11K_DBG_DP_HTT:
+ return "dp_htt";
+ case ATH11K_DBG_MAC:
+ return "mac";
+ case ATH11K_DBG_BOOT:
+ return "boot";
+ case ATH11K_DBG_QMI:
+ return "qmi";
+ case ATH11K_DBG_DATA:
+ return "data";
+ case ATH11K_DBG_MGMT:
+ return "mgmt";
+ case ATH11K_DBG_REG:
+ return "reg";
+ case ATH11K_DBG_TESTMODE:
+ return "testmode";
+ case ATH11K_DBG_HAL:
+ return "hal";
+ case ATH11K_DBG_PCI:
+ return "pci";
+ case ATH11K_DBG_DP_TX:
+ return "dp_tx";
+ case ATH11K_DBG_DP_RX:
+ return "dp_rx";
+ case ATH11K_DBG_CE:
+ return "ce";
+
+ /* no default handler to allow compiler to check that the
+ * enum is fully handled
+ */
+ }
+
+ return "<?>";
+}
+
__printf(2, 3) void ath11k_info(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_err(struct ath11k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
index b3efca6bd7dd..0207fc4910f3 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c
@@ -4011,6 +4011,114 @@ void htt_print_phy_stats_tlv(const void *tag_buf,
stats_req->buf_len = len;
}
+static inline void
+htt_print_phy_reset_counters_tlv(const void *tag_buf,
+ u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_phy_reset_counters_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n");
+
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ htt_stats_buf->pdev_id);
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_fail_cnt = %u\n",
+ htt_stats_buf->cf_active_low_fail_cnt);
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_pass_cnt = %u\n",
+ htt_stats_buf->cf_active_low_pass_cnt);
+ len += scnprintf(buf + len, buf_len - len, "phy_off_through_vreg_cnt = %u\n",
+ htt_stats_buf->phy_off_through_vreg_cnt);
+ len += scnprintf(buf + len, buf_len - len, "force_calibration_cnt = %u\n",
+ htt_stats_buf->force_calibration_cnt);
+ len += scnprintf(buf + len, buf_len - len, "rf_mode_switch_phy_off_cnt = %u\n",
+ htt_stats_buf->rf_mode_switch_phy_off_cnt);
+
+ stats_req->buf_len = len;
+}
+
+static inline void
+htt_print_phy_reset_stats_tlv(const void *tag_buf,
+ u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct htt_phy_reset_stats_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n");
+
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ htt_stats_buf->pdev_id);
+ len += scnprintf(buf + len, buf_len - len, "chan_mhz = %u\n",
+ htt_stats_buf->chan_mhz);
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq1 = %u\n",
+ htt_stats_buf->chan_band_center_freq1);
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq2 = %u\n",
+ htt_stats_buf->chan_band_center_freq2);
+ len += scnprintf(buf + len, buf_len - len, "chan_phy_mode = %u\n",
+ htt_stats_buf->chan_phy_mode);
+ len += scnprintf(buf + len, buf_len - len, "chan_flags = 0x%0x\n",
+ htt_stats_buf->chan_flags);
+ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n",
+ htt_stats_buf->chan_num);
+ len += scnprintf(buf + len, buf_len - len, "reset_cause = 0x%0x\n",
+ htt_stats_buf->reset_cause);
+ len += scnprintf(buf + len, buf_len - len, "prev_reset_cause = 0x%0x\n",
+ htt_stats_buf->prev_reset_cause);
+ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_src = 0x%0x\n",
+ htt_stats_buf->phy_warm_reset_src);
+ len += scnprintf(buf + len, buf_len - len, "rx_gain_tbl_mode = %d\n",
+ htt_stats_buf->rx_gain_tbl_mode);
+ len += scnprintf(buf + len, buf_len - len, "xbar_val = 0x%0x\n",
+ htt_stats_buf->xbar_val);
+ len += scnprintf(buf + len, buf_len - len, "force_calibration = %u\n",
+ htt_stats_buf->force_calibration);
+ len += scnprintf(buf + len, buf_len - len, "phyrf_mode = %u\n",
+ htt_stats_buf->phyrf_mode);
+ len += scnprintf(buf + len, buf_len - len, "phy_homechan = %u\n",
+ htt_stats_buf->phy_homechan);
+ len += scnprintf(buf + len, buf_len - len, "phy_tx_ch_mask = 0x%0x\n",
+ htt_stats_buf->phy_tx_ch_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_rx_ch_mask = 0x%0x\n",
+ htt_stats_buf->phy_rx_ch_mask);
+ len += scnprintf(buf + len, buf_len - len, "phybb_ini_mask = 0x%0x\n",
+ htt_stats_buf->phybb_ini_mask);
+ len += scnprintf(buf + len, buf_len - len, "phyrf_ini_mask = 0x%0x\n",
+ htt_stats_buf->phyrf_ini_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_dfs_en_mask = 0x%0x\n",
+ htt_stats_buf->phy_dfs_en_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_sscan_en_mask = 0x%0x\n",
+ htt_stats_buf->phy_sscan_en_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_synth_sel_mask = 0x%0x\n",
+ htt_stats_buf->phy_synth_sel_mask);
+ len += scnprintf(buf + len, buf_len - len, "phy_adfs_freq = %u\n",
+ htt_stats_buf->phy_adfs_freq);
+ len += scnprintf(buf + len, buf_len - len, "cck_fir_settings = 0x%0x\n",
+ htt_stats_buf->cck_fir_settings);
+ len += scnprintf(buf + len, buf_len - len, "phy_dyn_pri_chan = %u\n",
+ htt_stats_buf->phy_dyn_pri_chan);
+ len += scnprintf(buf + len, buf_len - len, "cca_thresh = 0x%0x\n",
+ htt_stats_buf->cca_thresh);
+ len += scnprintf(buf + len, buf_len - len, "dyn_cca_status = %u\n",
+ htt_stats_buf->dyn_cca_status);
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_hw = 0x%x\n",
+ htt_stats_buf->rxdesense_thresh_hw);
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_sw = 0x%x\n",
+ htt_stats_buf->rxdesense_thresh_sw);
+
+ stats_req->buf_len = len;
+}
+
static inline
void htt_print_peer_ctrl_path_txrx_stats_tlv(const void *tag_buf,
struct debug_htt_stats_req *stats_req)
@@ -4425,6 +4533,12 @@ static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
case HTT_STATS_PHY_STATS_TAG:
htt_print_phy_stats_tlv(tag_buf, stats_req);
break;
+ case HTT_STATS_PHY_RESET_COUNTERS_TAG:
+ htt_print_phy_reset_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_RESET_STATS_TAG:
+ htt_print_phy_reset_stats_tlv(tag_buf, len, stats_req);
+ break;
case HTT_STATS_PEER_CTRL_PATH_TXRX_STATS_TAG:
htt_print_peer_ctrl_path_txrx_stats_tlv(tag_buf, stats_req);
break;
diff --git a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
index 0bbd58a380de..96219301f05b 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h
@@ -111,6 +111,8 @@ enum htt_tlv_tag_t {
HTT_STATS_TXBF_OFDMA_STEER_STATS_TAG = 116,
HTT_STATS_PHY_COUNTERS_TAG = 121,
HTT_STATS_PHY_STATS_TAG = 122,
+ HTT_STATS_PHY_RESET_COUNTERS_TAG = 123,
+ HTT_STATS_PHY_RESET_STATS_TAG = 124,
HTT_STATS_MAX_TAG,
};
@@ -1964,6 +1966,47 @@ struct htt_phy_stats_tlv {
u32 fw_run_time;
};
+struct htt_phy_reset_counters_tlv {
+ u32 pdev_id;
+ u32 cf_active_low_fail_cnt;
+ u32 cf_active_low_pass_cnt;
+ u32 phy_off_through_vreg_cnt;
+ u32 force_calibration_cnt;
+ u32 rf_mode_switch_phy_off_cnt;
+};
+
+struct htt_phy_reset_stats_tlv {
+ u32 pdev_id;
+ u32 chan_mhz;
+ u32 chan_band_center_freq1;
+ u32 chan_band_center_freq2;
+ u32 chan_phy_mode;
+ u32 chan_flags;
+ u32 chan_num;
+ u32 reset_cause;
+ u32 prev_reset_cause;
+ u32 phy_warm_reset_src;
+ u32 rx_gain_tbl_mode;
+ u32 xbar_val;
+ u32 force_calibration;
+ u32 phyrf_mode;
+ u32 phy_homechan;
+ u32 phy_tx_ch_mask;
+ u32 phy_rx_ch_mask;
+ u32 phybb_ini_mask;
+ u32 phyrf_ini_mask;
+ u32 phy_dfs_en_mask;
+ u32 phy_sscan_en_mask;
+ u32 phy_synth_sel_mask;
+ u32 phy_adfs_freq;
+ u32 cck_fir_settings;
+ u32 phy_dyn_pri_chan;
+ u32 cca_thresh;
+ u32 dyn_cca_status;
+ u32 rxdesense_thresh_hw;
+ u32 rxdesense_thresh_sw;
+};
+
struct htt_peer_ctrl_path_txrx_stats_tlv {
/* peer mac address */
u8 peer_mac_addr[ETH_ALEN];
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index f67ce62b2b48..1e488eed282b 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -1651,7 +1651,7 @@ static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab,
backpressure_time = *data;
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "backpressure event, pdev %d, ring type %d,ring id %d, hp %d tp %d, backpressure time %d\n",
pdev_id, ring_type, ring_id, hp, tp, backpressure_time);
if (ring_type == HTT_BACKPRESSURE_UMAC_RING_TYPE) {
@@ -2408,7 +2408,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_status->freq = center_freq;
} else if (channel_num >= 1 && channel_num <= 14) {
rx_status->band = NL80211_BAND_2GHZ;
- } else if (channel_num >= 36 && channel_num <= 173) {
+ } else if (channel_num >= 36 && channel_num <= 177) {
rx_status->band = NL80211_BAND_5GHZ;
} else {
spin_lock_bh(&ar->data_lock);
@@ -2466,7 +2466,7 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
spin_unlock_bh(&ar->ab->base_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
- "rx skb %pK len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
+ "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
msdu,
msdu->len,
peer ? peer->addr : NULL,
@@ -4908,7 +4908,7 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11k *ar,
goto err_merge_fail;
ath11k_dbg(ab, ATH11K_DBG_DATA,
- "mpdu_buf %pK mpdu_buf->len %u",
+ "mpdu_buf %p mpdu_buf->len %u",
prev_buf, prev_buf->len);
} else {
ath11k_dbg(ab, ATH11K_DBG_DATA,
@@ -5099,7 +5099,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
if (!mon_dst_srng) {
ath11k_warn(ar->ab,
- "HAL Monitor Destination Ring Init Failed -- %pK",
+ "HAL Monitor Destination Ring Init Failed -- %p",
mon_dst_srng);
return;
}
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 08a28464eb7a..b85a4a03b37a 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -344,7 +344,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
if (!skb_cb->vif) {
- dev_kfree_skb_any(msdu);
+ ieee80211_free_txskb(ar->hw, msdu);
return;
}
@@ -369,7 +369,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,
"dp_tx: failed to find the peer with peer_id %d\n",
ts->peer_id);
spin_unlock_bh(&ab->base_lock);
- dev_kfree_skb_any(msdu);
+ ieee80211_free_txskb(ar->hw, msdu);
return;
}
spin_unlock_bh(&ab->base_lock);
@@ -566,12 +566,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) {
- dev_kfree_skb_any(msdu);
+ ieee80211_free_txskb(ar->hw, msdu);
return;
}
if (unlikely(!skb_cb->vif)) {
- dev_kfree_skb_any(msdu);
+ ieee80211_free_txskb(ar->hw, msdu);
return;
}
@@ -624,7 +624,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
"dp_tx: failed to find the peer with peer_id %d\n",
ts->peer_id);
spin_unlock_bh(&ab->base_lock);
- dev_kfree_skb_any(msdu);
+ ieee80211_free_txskb(ar->hw, msdu);
return;
}
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
@@ -964,14 +964,10 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
params.low_threshold);
}
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n",
- __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
- cmd->msi_data);
-
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n",
- ring_id, ring_type, cmd->intr_info, cmd->info2);
+ ath11k_dbg(ab, ATH11K_DBG_DP_TX,
+ "htt srng setup msi_addr_lo 0x%x msi_addr_hi 0x%x msi_data 0x%x ring_id %d ring_type %d intr_info 0x%x flags 0x%x\n",
+ cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi,
+ cmd->msi_data, ring_id, ring_type, cmd->intr_info, cmd->info2);
ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb);
if (ret)
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index 22422237500c..0a99aa7ddbf4 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -1009,8 +1009,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
srng->u.src_ring.hp_addr =
(u32 *)((unsigned long)ab->mem + reg_base);
else
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
+ "type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
type, ring_num,
reg_base,
(unsigned long)srng->u.src_ring.hp_addr -
@@ -1043,7 +1043,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
(u32 *)((unsigned long)ab->mem + reg_base +
(HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab)));
else
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"type %d ring_num %d target_reg 0x%x shadow 0x%lx\n",
type, ring_num,
reg_base + (HAL_REO1_RING_TP(ab) -
@@ -1118,8 +1118,8 @@ int ath11k_hal_srng_update_shadow_config(struct ath11k_base *ab,
ath11k_hal_srng_update_hp_tp_addr(ab, shadow_cfg_idx, ring_type,
ring_num);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
- "target_reg %x, shadow reg 0x%x shadow_idx 0x%x, ring_type %d, ring num %d",
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
+ "update shadow config target_reg %x shadow reg 0x%x shadow_idx 0x%x ring_type %d ring num %d",
target_reg,
HAL_SHADOW_REG(ab, shadow_cfg_idx),
shadow_cfg_idx,
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c
index bb1d40034aa8..e5ed5efb139e 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -442,54 +442,54 @@ void ath11k_hal_reo_status_queue_stats(struct ath11k_base *ab, u32 *reo_desc,
FIELD_GET(HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS,
desc->hdr.info0);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "Queue stats status:\n");
- ath11k_dbg(ab, ATH11k_DBG_HAL, "header: cmd_num %d status %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "Queue stats status:\n");
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "header: cmd_num %d status %d\n",
status->uniform_hdr.cmd_num,
status->uniform_hdr.cmd_status);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "ssn %ld cur_idx %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "ssn %ld cur_idx %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_SSN,
desc->info0),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX,
desc->info0));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "pn = [%08x, %08x, %08x, %08x]\n",
desc->pn[0], desc->pn[1], desc->pn[2], desc->pn[3]);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"last_rx: enqueue_tstamp %08x dequeue_tstamp %08x\n",
desc->last_rx_enqueue_timestamp,
desc->last_rx_dequeue_timestamp);
- ath11k_dbg(ab, ATH11k_DBG_HAL,
+ ath11k_dbg(ab, ATH11K_DBG_HAL,
"rx_bitmap [%08x %08x %08x %08x %08x %08x %08x %08x]\n",
desc->rx_bitmap[0], desc->rx_bitmap[1], desc->rx_bitmap[2],
desc->rx_bitmap[3], desc->rx_bitmap[4], desc->rx_bitmap[5],
desc->rx_bitmap[6], desc->rx_bitmap[7]);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "count: cur_mpdu %ld cur_msdu %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MPDU_COUNT,
desc->info1),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MSDU_COUNT,
desc->info1));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "fwd_timeout %ld fwd_bar %ld dup_count %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_TIMEOUT_COUNT,
desc->info2),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_FDTB_COUNT,
desc->info2),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO2_DUPLICATE_COUNT,
desc->info2));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "frames_in_order %ld bar_rcvd %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_FIO_COUNT,
desc->info3),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO3_BAR_RCVD_CNT,
desc->info3));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "num_mpdus %d num_msdus %d total_bytes %d\n",
desc->num_mpdu_frames, desc->num_msdu_frames,
desc->total_bytes);
- ath11k_dbg(ab, ATH11k_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "late_rcvd %ld win_jump_2k %ld hole_cnt %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_LATE_RX_MPDU,
desc->info4),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_WINDOW_JMP2K,
desc->info4),
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT,
desc->info4));
- ath11k_dbg(ab, ATH11k_DBG_HAL, "looping count %ld\n",
+ ath11k_dbg(ab, ATH11K_DBG_HAL, "looping count %ld\n",
FIELD_GET(HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT,
desc->info5));
}
diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c
index ca3aedc0252d..2c2e425c8665 100644
--- a/drivers/net/wireless/ath/ath11k/htc.c
+++ b/drivers/net/wireless/ath/ath11k/htc.c
@@ -46,7 +46,6 @@ static struct sk_buff *ath11k_htc_build_tx_ctrl_skb(void *ab)
skb_cb = ATH11K_SKB_CB(skb);
memset(skb_cb, 0, sizeof(*skb_cb));
- ath11k_dbg(ab, ATH11K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
return skb;
}
@@ -96,7 +95,7 @@ int ath11k_htc_send(struct ath11k_htc *htc,
spin_lock_bh(&htc->tx_lock);
if (ep->tx_credits < credits) {
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc insufficient credits ep %d required %d available %d\n",
+ "ep %d insufficient credits required %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
ret = -EAGAIN;
@@ -104,7 +103,7 @@ int ath11k_htc_send(struct ath11k_htc *htc,
}
ep->tx_credits -= credits;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc ep %d consumed %d credits (total %d)\n",
+ "ep %d credits consumed %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
}
@@ -119,6 +118,9 @@ int ath11k_htc_send(struct ath11k_htc *htc,
goto err_credits;
}
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "tx skb %p eid %d paddr %pad\n",
+ skb, skb_cb->eid, &skb_cb->paddr);
+
ret = ath11k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid);
if (ret)
goto err_unmap;
@@ -132,7 +134,7 @@ err_credits:
spin_lock_bh(&htc->tx_lock);
ep->tx_credits += credits;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "htc ep %d reverted %d credits back (total %d)\n",
+ "ep %d credits reverted %d total %d\n",
eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock);
@@ -167,7 +169,7 @@ ath11k_htc_process_credit_report(struct ath11k_htc *htc,
ep = &htc->endpoint[report->eid];
ep->tx_credits += report->credits;
- ath11k_dbg(ab, ATH11K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "ep %d credits got %d total %d\n",
report->eid, report->credits, ep->tx_credits);
if (ep->ep_ops.ep_tx_credits) {
@@ -239,7 +241,7 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc,
static void ath11k_htc_suspend_complete(struct ath11k_base *ab, bool ack)
{
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot suspend complete %d\n", ack);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "suspend complete %d\n", ack);
if (ack)
set_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
@@ -276,7 +278,7 @@ void ath11k_htc_tx_completion_handler(struct ath11k_base *ab,
static void ath11k_htc_wakeup_from_suspend(struct ath11k_base *ab)
{
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot wakeup from suspend is received\n");
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "wakeup from suspend is received\n");
}
void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
@@ -287,7 +289,7 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
struct ath11k_htc_hdr *hdr;
struct ath11k_htc_ep *ep;
u16 payload_len;
- u32 trailer_len = 0;
+ u32 message_id, trailer_len = 0;
size_t min_len;
u8 eid;
bool trailer_present;
@@ -322,6 +324,9 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
trailer_present = (FIELD_GET(HTC_HDR_FLAGS, hdr->htc_info)) &
ATH11K_HTC_FLAG_TRAILER_PRESENT;
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p trailer_present %d\n",
+ eid, skb, trailer_present);
+
if (trailer_present) {
u8 *trailer;
@@ -354,7 +359,12 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
if (eid == ATH11K_HTC_EP_0) {
struct ath11k_htc_msg *msg = (struct ath11k_htc_msg *)skb->data;
- switch (FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id)) {
+ message_id = FIELD_GET(HTC_MSG_MESSAGEID, msg->msg_svc_id);
+
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "rx ep %d skb %p message_id %d\n",
+ eid, skb, message_id);
+
+ switch (message_id) {
case ATH11K_HTC_MSG_READY_ID:
case ATH11K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
/* handle HTC control message */
@@ -393,8 +403,6 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab,
goto out;
}
- ath11k_dbg(ab, ATH11K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
- eid, skb);
ep->ep_ops.ep_rx_complete(ab, skb);
/* poll tx completion for interrupt disabled CE's */
@@ -564,7 +572,7 @@ int ath11k_htc_wait_target(struct ath11k_htc *htc)
htc->target_credit_size = credit_size;
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "Target ready! transmit resources: %d size:%d\n",
+ "target ready total_transmit_credits %d target_credit_size %d\n",
htc->total_transmit_credits, htc->target_credit_size);
if ((htc->total_transmit_credits == 0) ||
@@ -615,7 +623,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc,
conn_req->service_id);
if (!tx_alloc)
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service %s does not allocate target credits\n",
+ "htc service %s does not allocate target credits\n",
htc_service_name(conn_req->service_id));
skb = ath11k_htc_build_tx_ctrl_skb(htc->ab);
@@ -680,7 +688,7 @@ int ath11k_htc_connect_service(struct ath11k_htc *htc,
}
ath11k_dbg(ab, ATH11K_DBG_HTC,
- "HTC Service %s connect response: status: 0x%lx, assigned ep: 0x%lx\n",
+ "service %s connect response status 0x%lx assigned ep 0x%lx\n",
htc_service_name(service_id),
FIELD_GET(HTC_SVC_RESP_MSG_STATUS, resp_msg->flags_len),
FIELD_GET(HTC_SVC_RESP_MSG_ENDPOINTID, resp_msg->flags_len));
@@ -740,14 +748,14 @@ setup:
return status;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
+ "htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
htc_service_name(ep->service_id), ep->ul_pipe_id,
ep->dl_pipe_id, ep->eid);
if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
ep->tx_credit_flow_enabled = false;
ath11k_dbg(ab, ATH11K_DBG_BOOT,
- "boot htc service '%s' eid %d TX flow control disabled\n",
+ "htc service '%s' eid %d tx flow control disabled\n",
htc_service_name(ep->service_id), assigned_eid);
}
@@ -773,7 +781,7 @@ int ath11k_htc_start(struct ath11k_htc *htc)
ATH11K_HTC_MSG_SETUP_COMPLETE_EX_ID);
if (ab->hw_params.credit_flow)
- ath11k_dbg(ab, ATH11K_DBG_HTC, "HTC is using TX credit flow control\n");
+ ath11k_dbg(ab, ATH11K_DBG_HTC, "using tx credit flow control\n");
else
msg->flags |= ATH11K_GLOBAL_DISABLE_CREDIT_FLOW;
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index eb995f9cf0fa..d7b5ec6e6904 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
config->twt_ap_sta_count = 1000;
config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64;
config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI;
+ config->ema_max_vap_cnt = ab->num_radios;
+ config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD;
+ config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt;
}
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
@@ -1175,7 +1178,7 @@ const struct ath11k_hw_ops ipq5018_ops = {
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
-
+ .get_ring_selector = ath11k_hw_ipq8074_get_tcl_ring_selector,
};
#define ATH11K_TX_RING_MASK_0 BIT(0)
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 6a5dd2dbdb3a..f5533630a7f9 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -64,6 +64,7 @@
#define TARGET_NUM_WDS_ENTRIES 32
#define TARGET_DMA_BURST_SIZE 1
#define TARGET_RX_BATCHMODE 1
+#define TARGET_EMA_MAX_PROFILE_PERIOD 8
#define ATH11K_HW_MAX_QUEUES 4
#define ATH11K_QUEUE_LEN 4096
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 1c93f1afccc5..8c77ade49437 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <net/mac80211.h>
@@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
}
static u32
-ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask)
{
int nss;
@@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static u32
-ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask)
{
int nss;
@@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
}
static u32
-ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+ath11k_mac_max_he_nss(const u16 *he_mcs_mask)
{
int nss;
@@ -643,7 +643,10 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
return NULL;
for (i = 0; i < ab->num_radios; i++) {
- pdev = rcu_dereference(ab->pdevs_active[i]);
+ if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
+ pdev = &ab->pdevs[i];
+ else
+ pdev = rcu_dereference(ab->pdevs_active[i]);
if (pdev && pdev->pdev_id == pdev_id)
return (pdev->ar ? pdev->ar : NULL);
@@ -815,7 +818,7 @@ static int ath11k_recalc_rtscts_prot(struct ath11k_vif *arvif)
arvif->rtscts_prot_mode = rts_cts;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d recalc rts/cts prot %d\n",
arvif->vdev_id, rts_cts);
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
@@ -964,14 +967,14 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id,
return ret;
}
- ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
+ ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0);
if (ret) {
ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
vdev_id, ret);
goto vdev_stop;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i started\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i started\n",
vdev_id);
return 0;
@@ -1025,7 +1028,7 @@ static int ath11k_mac_monitor_vdev_stop(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %i stopped\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %i stopped\n",
ar->monitor_vdev_id);
return 0;
@@ -1096,7 +1099,7 @@ static int ath11k_mac_monitor_vdev_create(struct ath11k *ar)
ar->num_created_vdevs++;
set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d created\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d created\n",
ar->monitor_vdev_id);
return 0;
@@ -1131,7 +1134,7 @@ static int ath11k_mac_monitor_vdev_delete(struct ath11k *ar)
if (time_left == 0) {
ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n");
} else {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor vdev %d deleted\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor vdev %d deleted\n",
ar->monitor_vdev_id);
ar->allocated_vdev_map &= ~(1LL << ar->monitor_vdev_id);
@@ -1177,7 +1180,7 @@ static int ath11k_mac_monitor_start(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor started\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor started\n");
return 0;
}
@@ -1207,7 +1210,7 @@ static int ath11k_mac_monitor_stop(struct ath11k *ar)
return ret;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac monitor stopped ret %d\n", ret);
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "monitor stopped ret %d\n", ret);
return 0;
}
@@ -1258,7 +1261,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
psmode = WMI_STA_PS_MODE_DISABLED;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d psmode %s\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d psmode %s\n",
arvif->vdev_id, psmode ? "enable" : "disable");
ret = ath11k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode);
@@ -1351,28 +1354,92 @@ err_mon_del:
return ret;
}
-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
+static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
+ bool tx_arvif_rsnie_present,
+ const u8 *profile, u8 profile_len)
{
- struct ath11k *ar = arvif->ar;
- struct ath11k_base *ab = ar->ab;
- struct ieee80211_hw *hw = ar->hw;
- struct ieee80211_vif *vif = arvif->vif;
- struct ieee80211_mutable_offsets offs = {};
- struct sk_buff *bcn;
- struct ieee80211_mgmt *mgmt;
- u8 *ies;
- int ret;
+ if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
+ arvif->rsnie_present = true;
+ } else if (tx_arvif_rsnie_present) {
+ int i;
+ u8 nie_len;
+ const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
+ profile, profile_len);
+ if (!nie)
+ return;
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
- return 0;
+ nie_len = nie[1];
+ nie += 2;
+ for (i = 0; i < nie_len; i++) {
+ if (nie[i] == WLAN_EID_RSN) {
+ arvif->rsnie_present = false;
+ break;
+ }
+ }
+ }
+}
- bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
- if (!bcn) {
- ath11k_warn(ab, "failed to get beacon template from mac80211\n");
- return -EPERM;
+static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
+ struct ath11k_vif *arvif,
+ struct sk_buff *bcn)
+{
+ struct ieee80211_mgmt *mgmt;
+ const u8 *ies, *profile, *next_profile;
+ int ies_len;
+
+ ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
+ mgmt = (struct ieee80211_mgmt *)bcn->data;
+ ies += sizeof(mgmt->u.beacon);
+ ies_len = skb_tail_pointer(bcn) - ies;
+
+ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
+ arvif->rsnie_present = tx_arvif->rsnie_present;
+
+ while (ies) {
+ u8 mbssid_len;
+
+ ies_len -= (2 + ies[1]);
+ mbssid_len = ies[1] - 1;
+ profile = &ies[3];
+
+ while (mbssid_len) {
+ u8 profile_len;
+
+ profile_len = profile[1];
+ next_profile = profile + (2 + profile_len);
+ mbssid_len -= (2 + profile_len);
+
+ profile += 2;
+ profile_len -= (2 + profile[1]);
+ profile += (2 + profile[1]); /* nontx capabilities */
+ profile_len -= (2 + profile[1]);
+ profile += (2 + profile[1]); /* SSID */
+ if (profile[2] == arvif->vif->bss_conf.bssid_index) {
+ profile_len -= 5;
+ profile = profile + 5;
+ ath11k_mac_setup_nontx_vif_rsnie(arvif,
+ tx_arvif->rsnie_present,
+ profile,
+ profile_len);
+ return true;
+ }
+ profile = next_profile;
+ }
+ ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
+ ies_len);
}
+ return false;
+}
+
+static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
+ struct sk_buff *bcn)
+{
+ struct ieee80211_mgmt *mgmt;
+ u8 *ies;
+
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
+ mgmt = (struct ieee80211_mgmt *)bcn->data;
ies += sizeof(mgmt->u.beacon);
if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies)))
@@ -1386,9 +1453,95 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
arvif->wpaie_present = true;
else
arvif->wpaie_present = false;
+}
+
+static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
+{
+ struct ath11k_vif *tx_arvif;
+ struct ieee80211_ema_beacons *beacons;
+ int ret = 0;
+ bool nontx_vif_params_set = false;
+ u32 params = 0;
+ u8 i = 0;
+
+ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
- ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
+ beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw,
+ tx_arvif->vif, 0);
+ if (!beacons || !beacons->cnt) {
+ ath11k_warn(arvif->ar->ab,
+ "failed to get ema beacon templates from mac80211\n");
+ return -EPERM;
+ }
+ if (tx_arvif == arvif)
+ ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb);
+ else
+ arvif->wpaie_present = tx_arvif->wpaie_present;
+
+ for (i = 0; i < beacons->cnt; i++) {
+ if (tx_arvif != arvif && !nontx_vif_params_set)
+ nontx_vif_params_set =
+ ath11k_mac_set_nontx_vif_params(tx_arvif, arvif,
+ beacons->bcn[i].skb);
+
+ params = beacons->cnt;
+ params |= (i << WMI_EMA_TMPL_IDX_SHIFT);
+ params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
+ params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
+
+ ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
+ &beacons->bcn[i].offs,
+ beacons->bcn[i].skb, params);
+ if (ret) {
+ ath11k_warn(tx_arvif->ar->ab,
+ "failed to set ema beacon template id %i error %d\n",
+ i, ret);
+ break;
+ }
+ }
+
+ ieee80211_beacon_free_ema_list(beacons);
+
+ if (tx_arvif != arvif && !nontx_vif_params_set)
+ return -EINVAL; /* Profile not found in the beacons */
+
+ return ret;
+}
+
+static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
+{
+ struct ath11k *ar = arvif->ar;
+ struct ath11k_base *ab = ar->ab;
+ struct ath11k_vif *tx_arvif = arvif;
+ struct ieee80211_hw *hw = ar->hw;
+ struct ieee80211_vif *vif = arvif->vif;
+ struct ieee80211_mutable_offsets offs = {};
+ struct sk_buff *bcn;
+ int ret;
+
+ if (arvif->vif->mbssid_tx_vif) {
+ tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
+ if (tx_arvif != arvif) {
+ ar = tx_arvif->ar;
+ ab = ar->ab;
+ hw = ar->hw;
+ vif = tx_arvif->vif;
+ }
+ }
+
+ bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
+ if (!bcn) {
+ ath11k_warn(ab, "failed to get beacon template from mac80211\n");
+ return -EPERM;
+ }
+
+ if (tx_arvif == arvif)
+ ath11k_mac_set_vif_params(tx_arvif, bcn);
+ else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
+ return -EINVAL;
+
+ ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
kfree_skb(bcn);
if (ret)
@@ -1398,6 +1551,26 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
return ret;
}
+static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
+{
+ struct ieee80211_vif *vif = arvif->vif;
+
+ if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+ return 0;
+
+ /* Target does not expect beacon templates for the already up
+ * non-transmitting interfaces, and results in a crash if sent.
+ */
+ if (vif->mbssid_tx_vif &&
+ arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
+ return 0;
+
+ if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif)
+ return ath11k_mac_setup_bcn_tmpl_ema(arvif);
+
+ return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
+}
+
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
{
struct ieee80211_vif *vif = arvif->vif;
@@ -1423,6 +1596,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
struct ieee80211_bss_conf *info)
{
struct ath11k *ar = arvif->ar;
+ struct ath11k_vif *tx_arvif = NULL;
int ret = 0;
lockdep_assert_held(&arvif->ar->conf_mutex);
@@ -1451,8 +1625,14 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
ether_addr_copy(arvif->bssid, info->bssid);
+ if (arvif->vif->mbssid_tx_vif)
+ tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv;
+
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ arvif->bssid,
+ tx_arvif ? tx_arvif->bssid : NULL,
+ info->bssid_index,
+ 1 << info->bssid_indicator);
if (ret) {
ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
arvif->vdev_id, ret);
@@ -1461,7 +1641,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
arvif->is_up = true;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %d up\n", arvif->vdev_id);
}
static void ath11k_mac_handle_beacon_iter(void *data, u8 *mac,
@@ -1658,7 +1838,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar,
}
static bool
-ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
{
int nss;
@@ -1670,7 +1850,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static bool
-ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[])
+ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
{
int nss;
@@ -1784,7 +1964,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "ht peer %pM mcs cnt %d nss %d\n",
arg->peer_mac,
arg->peer_ht_rates.num_rates,
arg->peer_nss);
@@ -1948,7 +2128,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
}
if (!user_rate_valid) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting vht range mcs value to peer supported nss %d for peer %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting vht range mcs value to peer supported nss %d for peer %pM\n",
sta->deflink.rx_nss, sta->addr);
vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
}
@@ -2005,7 +2185,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
+ "vht peer %pM max_mpdu %d flags 0x%x nss_override 0x%x\n",
sta->addr, arg->peer_max_mpdu, arg->peer_flags,
arg->peer_bw_rxnss_override);
}
@@ -2065,7 +2245,7 @@ static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set,
}
static bool
-ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX])
+ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask)
{
int nss;
@@ -2230,7 +2410,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
}
if (!user_rate_valid) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting he range mcs value to peer supported nss %d for peer %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "setting he range mcs value to peer supported nss %d for peer %pM\n",
sta->deflink.rx_nss, sta->addr);
he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
}
@@ -2311,7 +2491,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
+ "he peer %pM nss %d mcs cnt %d nss_override 0x%x\n",
sta->addr, arg->peer_nss,
arg->peer_he_mcs_count,
arg->peer_bw_rxnss_override);
@@ -2431,7 +2611,7 @@ static void ath11k_peer_assoc_h_qos(struct ath11k *ar,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM qos %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM qos %d\n",
sta->addr, arg->qos_flag);
}
@@ -2448,7 +2628,7 @@ static int ath11k_peer_assoc_qos_ap(struct ath11k *ar,
params.vdev_id = arvif->vdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "uapsd_queues 0x%x max_sp %d\n",
sta->uapsd_queues, sta->max_sp);
uapsd = 0;
@@ -2634,7 +2814,7 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac peer %pM phymode %s\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "peer %pM phymode %s\n",
sta->addr, ath11k_wmi_phymode_str(phymode));
arg->peer_phymode = phymode;
@@ -2825,7 +3005,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
lockdep_assert_held(&ar->conf_mutex);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i assoc bssid %pM aid %d\n",
arvif->vdev_id, arvif->bssid, arvif->aid);
rcu_read_lock();
@@ -2879,7 +3059,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
arvif->aid = vif->cfg.aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
+ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid,
+ NULL, 0, 0);
if (ret) {
ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
arvif->vdev_id, ret);
@@ -2890,7 +3071,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
arvif->rekey_data.enable_offload = false;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vdev %d up (associated) bssid %pM aid %d\n",
+ "vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, vif->cfg.aid);
spin_lock_bh(&ar->ab->base_lock);
@@ -2935,7 +3116,7 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
lockdep_assert_held(&ar->conf_mutex);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %i disassoc bssid %pM\n",
arvif->vdev_id, arvif->bssid);
ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
@@ -3084,7 +3265,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
+ "obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset,
he_obss_pd->max_offset);
@@ -3412,7 +3593,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_TXPOWER) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev_id %i txpower %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev_id %i txpower %d\n",
arvif->vdev_id, info->txpower);
arvif->txpower = info->txpower;
@@ -3453,7 +3634,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac vdev %d mcast_rate %x\n",
+ "vdev %d mcast_rate %x\n",
arvif->vdev_id, rate);
vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
@@ -3562,7 +3743,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN);
arvif->arp_ns_offload.ipv4_count = ipv4_cnt;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n",
vif->cfg.arp_addr_cnt,
vif->addr, arvif->arp_ns_offload.ipv4_addr);
}
@@ -4160,6 +4341,20 @@ exit:
}
static int
+ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
+ enum nl80211_band band,
+ const struct cfg80211_bitrate_mask *mask)
+{
+ int num_rates = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
+ num_rates += hweight8(mask->control[band].ht_mcs[i]);
+
+ return num_rates;
+}
+
+static int
ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar,
enum nl80211_band band,
const struct cfg80211_bitrate_mask *mask)
@@ -4270,7 +4465,7 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
return -EINVAL;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac setting fixed he rate for peer %pM, device will not switch to any other selected rates",
+ "setting fixed he rate for peer %pM, device will not switch to any other selected rates",
sta->addr);
rate_code = ATH11K_HW_RATE_CODE(he_rate, nss - 1,
@@ -4288,6 +4483,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
return ret;
}
+static int
+ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif,
+ struct ieee80211_sta *sta,
+ const struct cfg80211_bitrate_mask *mask,
+ enum nl80211_band band)
+{
+ struct ath11k *ar = arvif->ar;
+ u8 ht_rate, nss = 0;
+ u32 rate_code;
+ int ret, i;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
+ if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
+ nss = i + 1;
+ ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1;
+ }
+ }
+
+ if (!nss) {
+ ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM",
+ sta->addr);
+ return -EINVAL;
+ }
+
+ /* Avoid updating invalid nss as fixed rate*/
+ if (nss > sta->deflink.rx_nss)
+ return -EINVAL;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+ "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates",
+ sta->addr);
+
+ rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1,
+ WMI_RATE_PREAMBLE_HT);
+ ret = ath11k_wmi_set_peer_param(ar, sta->addr,
+ arvif->vdev_id,
+ WMI_PEER_PARAM_FIXED_RATE,
+ rate_code);
+ if (ret)
+ ath11k_warn(ar->ab,
+ "failed to update STA %pM HT Fixed Rate %d: %d\n",
+ sta->addr, rate_code, ret);
+
+ return ret;
+}
+
static int ath11k_station_assoc(struct ath11k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -4299,7 +4542,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
struct cfg80211_chan_def def;
enum nl80211_band band;
struct cfg80211_bitrate_mask *mask;
- u8 num_vht_rates, num_he_rates;
+ u8 num_ht_rates, num_vht_rates, num_he_rates;
lockdep_assert_held(&ar->conf_mutex);
@@ -4327,6 +4570,7 @@ static int ath11k_station_assoc(struct ath11k *ar,
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask);
+ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask);
/* If single VHT/HE rate is configured (by set_bitrate_mask()),
* peer_assoc will disable VHT/HE. This is now enabled by a peer specific
@@ -4343,6 +4587,11 @@ static int ath11k_station_assoc(struct ath11k *ar,
band);
if (ret)
return ret;
+ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
+ ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
+ band);
+ if (ret)
+ return ret;
}
/* Re-assoc is run only to update supported rates for given station. It
@@ -4416,7 +4665,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
const u16 *vht_mcs_mask;
const u16 *he_mcs_mask;
u32 changed, bw, nss, smps, bw_prev;
- int err, num_vht_rates, num_he_rates;
+ int err, num_ht_rates, num_vht_rates, num_he_rates;
const struct cfg80211_bitrate_mask *mask;
struct peer_assoc_params peer_arg;
enum wmi_phy_mode peer_phymode;
@@ -4458,14 +4707,14 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg);
peer_phymode = peer_arg.peer_phymode;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM peer bw %d phymode %d\n",
sta->addr, bw, peer_phymode);
if (bw > bw_prev) {
/* BW is upgraded. In this case we send WMI_PEER_PHYMODE
* followed by WMI_PEER_CHWIDTH
*/
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW upgrade for sta %pM new BW %d, old BW %d\n",
sta->addr, bw, bw_prev);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4487,7 +4736,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
/* BW is downgraded. In this case we send WMI_PEER_CHWIDTH
* followed by WMI_PEER_PHYMODE
*/
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "BW downgrade for sta %pM new BW %d,old BW %d\n",
sta->addr, bw, bw_prev);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4509,7 +4758,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
}
if (changed & IEEE80211_RC_NSS_CHANGED) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM nss %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM nss %d\n",
sta->addr, nss);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4520,7 +4769,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
}
if (changed & IEEE80211_RC_SMPS_CHANGED) {
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM smps %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "update sta %pM smps %d\n",
sta->addr, smps);
err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
@@ -4532,6 +4781,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
mask = &arvif->bitrate_mask;
+ num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band,
+ mask);
num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band,
mask);
num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band,
@@ -4554,6 +4805,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
band);
+ } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) {
+ ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask,
+ band);
} else {
/* If the peer is non-VHT/HE or no fixed VHT/HE rate
* is provided in the new bitrate mask we set the
@@ -4973,7 +5227,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->ab->base_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
+ "sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
sta->addr, changed, sta->deflink.bandwidth,
sta->deflink.rx_nss,
sta->deflink.smps_mode);
@@ -5784,7 +6038,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&ar->txmgmt_idr_lock);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac tx mgmt frame, buf id %d\n", buf_id);
+ "tx mgmt frame, buf id %d\n", buf_id);
if (buf_id < 0)
return -ENOSPC;
@@ -5861,7 +6115,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
} else {
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac tx mgmt frame, vdev_id %d\n",
+ "tx mgmt frame, vdev_id %d\n",
arvif->vdev_id);
}
} else {
@@ -6020,6 +6274,11 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
struct ath11k_pdev *pdev = ar->pdev;
int ret;
+ if (ath11k_ftm_mode) {
+ ath11k_warn(ab, "mac operations not supported in factory test mode\n");
+ return -EOPNOTSUPP;
+ }
+
ath11k_mac_drain_tx(ar);
mutex_lock(&ar->conf_mutex);
@@ -6034,6 +6293,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
case ATH11K_STATE_RESTARTED:
case ATH11K_STATE_WEDGED:
case ATH11K_STATE_ON:
+ case ATH11K_STATE_FTM:
WARN_ON(1);
ret = -EINVAL;
goto err;
@@ -6181,17 +6441,62 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
atomic_set(&ar->num_pending_mgmt_tx, 0);
}
-static void
-ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
- struct vdev_create_params *params)
+static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif,
+ u32 *flags, u32 *tx_vdev_id)
+{
+ struct ath11k *ar = arvif->ar;
+ struct ath11k_vif *tx_arvif;
+ struct ieee80211_vif *tx_vif;
+
+ *tx_vdev_id = 0;
+ tx_vif = arvif->vif->mbssid_tx_vif;
+ if (!tx_vif) {
+ *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP;
+ return 0;
+ }
+
+ tx_arvif = (void *)tx_vif->drv_priv;
+
+ if (arvif->vif->bss_conf.nontransmitted) {
+ if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
+ return -EINVAL;
+
+ *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
+ *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id;
+ } else if (tx_arvif == arvif) {
+ *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
+ } else {
+ return -EINVAL;
+ }
+
+ if (arvif->vif->bss_conf.ema_ap)
+ *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
+
+ return 0;
+}
+
+static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
+ struct vdev_create_params *params)
{
struct ath11k *ar = arvif->ar;
struct ath11k_pdev *pdev = ar->pdev;
+ int ret;
params->if_id = arvif->vdev_id;
params->type = arvif->vdev_type;
params->subtype = arvif->vdev_subtype;
params->pdev_id = pdev->pdev_id;
+ params->mbssid_flags = 0;
+ params->mbssid_tx_vdev_id = 0;
+
+ if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
+ ar->ab->wmi_ab.svc_map)) {
+ ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
+ &params->mbssid_flags,
+ &params->mbssid_tx_vdev_id);
+ if (ret)
+ return ret;
+ }
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
@@ -6206,6 +6511,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
}
+ return 0;
}
static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
@@ -6281,7 +6587,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
mutex_lock(&ar->ab->vdev_id_11d_lock);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev id for 11d scan %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev id for 11d scan %d\n",
ar->vdev_id_11d_scan);
if (ar->regdom_set_by_user)
@@ -6300,7 +6606,7 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)
param.start_interval_msec = 0;
param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "start 11d scan\n");
ret = ath11k_wmi_send_11d_scan_start_cmd(ar, &param);
if (ret) {
@@ -6329,11 +6635,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar)
if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
return;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d scan\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d scan\n");
mutex_lock(&ar->ab->vdev_id_11d_lock);
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "stop 11d vdev id %d\n",
ar->vdev_id_11d_scan);
if (ar->state_11d == ATH11K_11D_PREPARING) {
@@ -6364,7 +6670,7 @@ void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
struct ath11k_pdev *pdev;
int i;
- ath11k_dbg(ab, ATH11K_DBG_MAC, "mac stop soc 11d scan\n");
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "stop soc 11d scan\n");
for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i];
@@ -6492,7 +6798,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
break;
}
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac add interface id %d type %d subtype %d map %llx\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "add interface id %d type %d subtype %d map %llx\n",
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
ab->free_vdev_map);
@@ -6500,7 +6806,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
- ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ if (ret) {
+ ath11k_warn(ab, "failed to create vdev parameters %d: %d\n",
+ arvif->vdev_id, ret);
+ goto err;
+ }
ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
if (ret) {
@@ -6678,7 +6989,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
- ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
+ ath11k_dbg(ab, ATH11K_DBG_MAC, "remove interface (vdev %d)\n",
arvif->vdev_id);
ret = ath11k_spectral_vif_stop(arvif);
@@ -6833,7 +7144,7 @@ static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw,
struct ath11k_base *ab = ar->ab;
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx add freq %u width %d ptr %pK\n",
+ "chanctx add freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
mutex_lock(&ar->conf_mutex);
@@ -6857,7 +7168,7 @@ static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
struct ath11k_base *ab = ar->ab;
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx remove freq %u width %d ptr %pK\n",
+ "chanctx remove freq %u width %d ptr %p\n",
ctx->def.chan->center_freq, ctx->def.width, ctx);
mutex_lock(&ar->conf_mutex);
@@ -6905,6 +7216,17 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
arg.pref_tx_streams = ar->num_tx_chains;
arg.pref_rx_streams = ar->num_rx_chains;
+ arg.mbssid_flags = 0;
+ arg.mbssid_tx_vdev_id = 0;
+ if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,
+ ar->ab->wmi_ab.svc_map)) {
+ ret = ath11k_mac_setup_vdev_params_mbssid(arvif,
+ &arg.mbssid_flags,
+ &arg.mbssid_tx_vdev_id);
+ if (ret)
+ return ret;
+ }
+
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
arg.ssid = arvif->u.ap.ssid;
arg.ssid_len = arvif->u.ap.ssid_len;
@@ -6926,7 +7248,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac vdev %d start center_freq %d phymode %s\n",
+ "vdev %d start center_freq %d phymode %s\n",
arg.vdev_id, arg.channel.freq,
ath11k_wmi_phymode_str(arg.channel.mode));
@@ -7071,7 +7393,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
int n_vifs)
{
struct ath11k_base *ab = ar->ab;
- struct ath11k_vif *arvif;
+ struct ath11k_vif *arvif, *tx_arvif = NULL;
+ struct ieee80211_vif *mbssid_tx_vif;
int ret;
int i;
bool monitor_vif = false;
@@ -7125,8 +7448,15 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
ret);
+ mbssid_tx_vif = arvif->vif->mbssid_tx_vif;
+ if (mbssid_tx_vif)
+ tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv;
+
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ arvif->bssid,
+ tx_arvif ? tx_arvif->bssid : NULL,
+ arvif->vif->bss_conf.bssid_index,
+ 1 << arvif->vif->bss_conf.bssid_indicator);
if (ret) {
ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
arvif->vdev_id, ret);
@@ -7192,7 +7522,7 @@ static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx change freq %u width %d ptr %pK changed %x\n",
+ "chanctx change freq %u width %d ptr %p changed %x\n",
ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
/* This shouldn't really happen because channel switching should use
@@ -7244,7 +7574,8 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
}
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
+ ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr,
+ NULL, 0, 0);
if (ret) {
ath11k_warn(ab, "failed put monitor up: %d\n", ret);
return ret;
@@ -7272,7 +7603,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx assign ptr %pK vdev_id %i\n",
+ "chanctx assign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
/* for QCA6390 bss peer must be created before vdev_start */
@@ -7362,7 +7693,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "mac chanctx unassign ptr %pK vdev_id %i\n",
+ "chanctx unassign ptr %p vdev_id %i\n",
ctx, arvif->vdev_id);
WARN_ON(!arvif->is_started);
@@ -7406,7 +7737,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
arvif->bssid, arvif->vdev_id, ret);
else
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac removed peer %pM vdev %d after vdev stop\n",
+ "removed peer %pM vdev %d after vdev stop\n",
arvif->bssid, arvif->vdev_id);
}
@@ -7441,7 +7772,7 @@ ath11k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
mutex_lock(&ar->conf_mutex);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac chanctx switch n_vifs %d mode %d\n",
+ "chanctx switch n_vifs %d mode %d\n",
n_vifs, mode);
ath11k_mac_update_vif_chan(ar, vifs, n_vifs);
@@ -7542,20 +7873,6 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
ath11k_mac_flush_tx_complete(ar);
}
-static int
-ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar,
- enum nl80211_band band,
- const struct cfg80211_bitrate_mask *mask)
-{
- int num_rates = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
- num_rates += hweight16(mask->control[band].ht_mcs[i]);
-
- return num_rates;
-}
-
static bool
ath11k_mac_has_single_legacy_rate(struct ath11k *ar,
enum nl80211_band band,
@@ -7787,7 +8104,7 @@ static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
+ "set rate params vdev %i rate 0x%02x nss 0x%02x sgi 0x%02x ldpc 0x%02x he_gi 0x%02x he_ltf 0x%02x he_fixed_rate %d\n",
arvif->vdev_id, rate, nss, sgi, ldpc, he_gi,
he_ltf, he_fixed_rate);
@@ -8292,7 +8609,7 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta statistics %s rssi[%d] %d\n", pre, i, rssi);
+ "sta statistics %s rssi[%d] %d\n", pre, i, rssi);
if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
rssi != ATH11K_INVALID_RSSI_FULL &&
@@ -8356,7 +8673,7 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
signal = arsta->rssi_beacon;
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
- "mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
+ "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n",
db2dbm, arsta->rssi_comb, arsta->rssi_beacon);
if (signal) {
@@ -8403,7 +8720,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
struct list_head *p;
u32 count, scope;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac op ipv6 changed\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "op ipv6 changed\n");
offload = &arvif->arp_ns_offload;
count = 0;
@@ -8428,7 +8745,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr,
sizeof(ifa6->addr.s6_addr));
offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 uc %pI6 scope %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 uc %pI6 scope %d\n",
count, offload->ipv6_addr[count],
scope);
count++;
@@ -8448,7 +8765,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw,
memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr,
sizeof(ifaca6->aca_addr));
offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 ac %pI6 scope %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "count %d ipv6 ac %pI6 scope %d\n",
count, offload->ipv6_addr[count],
scope);
count++;
@@ -8474,7 +8791,7 @@ static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw,
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
struct ath11k_rekey_data *rekey_data = &arvif->rekey_data;
- ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set rekey data vdev %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "set rekey data vdev %d\n",
arvif->vdev_id);
mutex_lock(&ar->conf_mutex);
@@ -8892,7 +9209,7 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
}
if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
- if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) {
+ if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) {
channels = kmemdup(ath11k_6ghz_channels,
sizeof(ath11k_6ghz_channels), GFP_KERNEL);
if (!channels) {
@@ -9001,19 +9318,23 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar)
static const u8 ath11k_if_types_ext_capa[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
};
static const u8 ath11k_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
static const u8 ath11k_if_types_ext_capa_ap[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
+ [10] = WLAN_EXT_CAPA11_EMA_SUPPORT,
};
static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
@@ -9251,6 +9572,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
wiphy_ext_feature_set(ar->hw->wiphy,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
+ ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
+ ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
+
ath11k_reg_init(ar);
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
@@ -9468,6 +9792,7 @@ void ath11k_mac_destroy(struct ath11k_base *ab)
if (!ar)
continue;
+ ath11k_fw_stats_free(&ar->fw_stats);
ieee80211_free_hw(ar->hw);
pdev->ar = NULL;
}
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index a62ee05c5409..3ac689f1def4 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -211,7 +211,7 @@ void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
val = ath11k_pcic_read32(ab, MHISTATUS);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "mhistatus 0x%x\n", val);
/* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
* has SYSERR bit set and thus need to set MHICTRL_RESET
@@ -263,7 +263,7 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
if (ret)
return ret;
- ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "num_vectors %d base_vector %d\n",
num_vectors, base_vector);
irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
@@ -325,7 +325,7 @@ static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
{
struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "mhi notify status reason %s\n",
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "notify status reason %s\n",
ath11k_mhi_op_callback_to_str(cb));
switch (cb) {
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7b33731a50ee..a181563ec085 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -203,10 +203,10 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
/* read cookie */
val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val);
val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
/* TODO: exact time to sleep is uncertain */
mdelay(10);
@@ -218,13 +218,13 @@ static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
mdelay(10);
val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);
/* A read clear register. clear the register to prevent
* Q6 from entering wrong code path.
*/
val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val);
}
static int ath11k_pci_set_link_reg(struct ath11k_base *ab,
@@ -312,14 +312,14 @@ static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)
val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);
}
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci ltssm 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val);
val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
val |= GCC_GCC_PCIE_HOT_RST_VAL;
ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val);
mdelay(5);
}
@@ -433,7 +433,7 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
}
clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);
ab->pci.msi.config = &msi_config_one_msi;
- ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n");
}
ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
@@ -487,7 +487,7 @@ static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data;
- ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
+ ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n",
ab_pci->ab->pci.msi.ep_base_data);
return 0;
@@ -545,7 +545,7 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
ab->mem_ce = ab->mem;
- ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem);
return 0;
release_region:
@@ -575,14 +575,14 @@ static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
&ab_pci->link_ctl);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n",
ab_pci->link_ctl,
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
/* disable L0s and L1 */
- pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
- ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+ pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC);
set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
}
@@ -590,8 +590,10 @@ static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
{
if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
- pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
- ab_pci->link_ctl);
+ pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC,
+ ab_pci->link_ctl &
+ PCI_EXP_LNKCTL_ASPMC);
}
static int ath11k_pci_power_up(struct ath11k_base *ab)
@@ -709,7 +711,7 @@ static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *
*minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
soc_hw_version);
- ath11k_dbg(ab, ATH11K_DBG_PCI, "pci tcsr_soc_hw_version major %d minor %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n",
*major, *minor);
}
@@ -745,6 +747,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
ab_pci->ab = ab;
ab_pci->pdev = pdev;
ab->hif.ops = &ath11k_pci_hif_ops;
+ ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;
pci_set_drvdata(pdev, ab);
spin_lock_init(&ab_pci->window_lock);
@@ -1033,7 +1036,7 @@ static void ath11k_pci_exit(void)
module_exit(ath11k_pci_exit);
-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
+MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
/* firmware files */
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c
index 30d66147223f..c63083633b37 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -263,7 +263,7 @@ int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
*user_base_data = *base_vector + ab->pci.msi.ep_base_data;
ath11k_dbg(ab, ATH11K_DBG_PCI,
- "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
+ "msi assignment %s num_vectors %d user_base_data %u base_vector %u\n",
user_name, *num_vectors, *user_base_data,
*base_vector);
@@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
if (!irq_grp->napi_enabled) {
- dev_set_threaded(&irq_grp->napi_ndev, true);
napi_enable(&irq_grp->napi);
irq_grp->napi_enabled = true;
}
@@ -527,7 +526,7 @@ static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg)
if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
return IRQ_HANDLED;
- ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
+ ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq %d\n", irq);
/* last interrupt received for this group */
irq_grp->timestamp = jiffies;
@@ -597,7 +596,7 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab)
ab->irq_num[irq_idx] = irq;
ath11k_dbg(ab, ATH11K_DBG_PCI,
- "irq:%d group:%d\n", irq, i);
+ "irq %d group %d\n", irq, i);
irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler,
diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c
index 1380811827a8..114aa3a9a339 100644
--- a/drivers/net/wireless/ath/ath11k/peer.c
+++ b/drivers/net/wireless/ath/ath11k/peer.c
@@ -106,7 +106,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
goto exit;
}
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer unmap vdev %d peer %pM id %d\n",
peer->vdev_id, peer->addr, peer_id);
list_del(&peer->list);
@@ -138,7 +138,7 @@ void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
wake_up(&ab->peer_mapping_wq);
}
- ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "htt peer map vdev %d peer %pM id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_DP_HTT, "peer map vdev %d peer %pM id %d\n",
vdev_id, mac_addr, peer_id);
exit:
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index ab923e24b0a9..d4eaf7d2ba84 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/elf.h>
@@ -1755,7 +1755,7 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "host cap request\n");
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
@@ -1833,7 +1833,7 @@ static int ath11k_qmi_fw_ind_register_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi indication register request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "indication register request\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_IND_REGISTER_REQ_V01,
@@ -1889,7 +1889,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
ab->qmi.target_mem_delayed) {
delayed = true;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "delays mem_request %d\n",
ab->qmi.mem_seg_count);
memset(req, 0, sizeof(*req));
} else {
@@ -1901,7 +1901,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi req mem_seg[%d] %pad %u %u\n", i,
+ "req mem_seg[%d] %pad %u %u\n", i,
&ab->qmi.target_mem[i].paddr,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].type);
@@ -1913,7 +1913,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi respond memory request delayed %i\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "respond memory request delayed %i\n",
delayed);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
@@ -2002,7 +2002,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
if (!chunk->vaddr) {
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi dma allocation failed (%d B type %u), will try later with small size\n",
+ "dma allocation failed (%d B type %u), will try later with small size\n",
chunk->size,
chunk->type);
ath11k_qmi_free_target_mem_chunk(ab);
@@ -2036,7 +2036,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!hremote_node) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to get hremote_node\n");
+ "fail to get hremote_node\n");
return -ENODEV;
}
@@ -2044,13 +2044,13 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
of_node_put(hremote_node);
if (ret) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to get reg from hremote\n");
+ "fail to get reg from hremote\n");
return ret;
}
if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
- "qmi fail to assign memory of sz\n");
+ "fail to assign memory of sz\n");
return -EINVAL;
}
@@ -2058,6 +2058,9 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
ab->qmi.target_mem[idx].iaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
+ if (!ab->qmi.target_mem[idx].iaddr)
+ return -EIO;
+
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
host_ddr_sz = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
@@ -2083,6 +2086,8 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
ab->qmi.target_mem[idx].iaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
+ if (!ab->qmi.target_mem[idx].iaddr)
+ return -EIO;
} else {
ab->qmi.target_mem[idx].paddr =
ATH11K_QMI_CALDB_ADDRESS;
@@ -2198,7 +2203,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi target cap request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "target cap request\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_CAP_REQ_V01,
@@ -2251,7 +2256,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
if (resp.eeprom_read_timeout_valid) {
ab->qmi.target.eeprom_caldata =
resp.eeprom_read_timeout;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "cal data supported from eeprom\n");
}
fw_build_id = ab->qmi.target.fw_build_id;
@@ -2348,7 +2353,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
if (ret < 0)
goto err_iounmap;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download req fixed addr type %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download req fixed addr type %d\n",
type);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
@@ -2381,7 +2386,7 @@ static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
remaining -= req->data_len;
temp += req->data_len;
req->seg_id++;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf download request remaining %i\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download request remaining %i\n",
remaining);
}
}
@@ -2427,7 +2432,7 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
else
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf_type %d\n", bdf_type);
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
@@ -2457,6 +2462,14 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
if (IS_ERR(fw_entry)) {
+ /* Caldata may not be present during first time calibration in
+ * factory hence allow to boot without loading caldata in ftm mode
+ */
+ if (ath11k_ftm_mode) {
+ ath11k_info(ab,
+ "Booting without cal data file in factory test mode\n");
+ return 0;
+ }
ret = PTR_ERR(fw_entry);
ath11k_warn(ab,
"qmi failed to load CAL data file:%s\n",
@@ -2474,14 +2487,14 @@ success:
goto out_qmi_cal;
}
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi caldata type: %u\n", file_type);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "caldata type: %u\n", file_type);
out_qmi_cal:
if (!ab->qmi.target.eeprom_caldata)
release_firmware(fw_entry);
out:
ath11k_core_free_bdf(ab, &bd);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF download sequence completed\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "BDF download sequence completed\n");
return ret;
}
@@ -2566,7 +2579,7 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi m3 info req\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "m3 info req\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_M3_INFO_REQ_V01,
@@ -2615,7 +2628,7 @@ static int ath11k_qmi_wlanfw_mode_send(struct ath11k_base *ab,
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan mode req mode %d\n", mode);
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan mode req mode %d\n", mode);
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_MODE_REQ_V01,
@@ -2710,7 +2723,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
if (ret < 0)
goto out;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wlan cfg req\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan cfg req\n");
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_CFG_REQ_V01,
@@ -2787,7 +2800,7 @@ void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
{
int ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware stop\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware stop\n");
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_OFF);
if (ret < 0) {
@@ -2801,7 +2814,7 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
{
int ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware start\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware start\n");
if (ab->hw_params.fw_wmi_diag_event) {
ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true);
@@ -2959,7 +2972,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
const struct qmi_wlanfw_request_mem_ind_msg_v01 *msg = data;
int i, ret;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware request memory request\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware request memory request\n");
if (msg->mem_seg_len == 0 ||
msg->mem_seg_len > ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01)
@@ -2971,7 +2984,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
for (i = 0; i < qmi->mem_seg_count ; i++) {
ab->qmi.target_mem[i].type = msg->mem_seg[i].type;
ab->qmi.target_mem[i].size = msg->mem_seg[i].size;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi mem seg type %d size %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "mem seg type %d size %d\n",
msg->mem_seg[i].type, msg->mem_seg[i].size);
}
@@ -3003,7 +3016,7 @@ static void ath11k_qmi_msg_mem_ready_cb(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware memory ready indication\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware memory ready indication\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_MEM_READY, NULL);
}
@@ -3015,7 +3028,7 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware ready\n");
if (!ab->qmi.cal_done) {
ab->qmi.cal_done = 1;
@@ -3036,7 +3049,7 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
ab->qmi.cal_done = 1;
wake_up(&ab->qmi.cold_boot_waitq);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "cold boot calibration done\n");
}
static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl,
@@ -3049,7 +3062,7 @@ static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl,
struct ath11k_base *ab = qmi->ab;
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL);
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware init done\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware init done\n");
}
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
@@ -3114,7 +3127,7 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
return ret;
}
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw qmi service connected\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw qmi service connected\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL);
return ret;
@@ -3126,7 +3139,7 @@ static void ath11k_qmi_ops_del_server(struct qmi_handle *qmi_hdl,
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
- ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw del server\n");
+ ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw del server\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_EXIT, NULL);
}
@@ -3256,8 +3269,7 @@ int ath11k_qmi_init_service(struct ath11k_base *ab)
return ret;
}
- ab->qmi.event_wq = alloc_workqueue("ath11k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ ab->qmi.event_wq = alloc_ordered_workqueue("ath11k_qmi_driver_event", 0);
if (!ab->qmi.event_wq) {
ath11k_err(ab, "failed to allocate workqueue\n");
return -EFAULT;
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index 67443457f4da..7f9fb968dac6 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -123,7 +123,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
ar->state_11d = ATH11K_11D_IDLE;
}
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "reg 11d scan wait left time %d\n", left);
+ "11d scan wait left time %d\n", left);
}
if (wait &&
@@ -136,7 +136,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
"failed to receive hw scan complete: timed out\n");
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "reg hw scan wait left time %d\n", left);
+ "hw scan wait left time %d\n", left);
}
if (ar->state == ATH11K_STATE_RESTARTING)
diff --git a/drivers/net/wireless/ath/ath11k/testmode.c b/drivers/net/wireless/ath/ath11k/testmode.c
index 4bf1931adbaa..8fc5cddb28bd 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.c
+++ b/drivers/net/wireless/ath/ath11k/testmode.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "testmode.h"
@@ -11,6 +12,9 @@
#include "core.h"
#include "testmode_i.h"
+#define ATH11K_FTM_SEGHDR_CURRENT_SEQ GENMASK(3, 0)
+#define ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS GENMASK(7, 4)
+
static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = {
[ATH11K_TM_ATTR_CMD] = { .type = NLA_U32 },
[ATH11K_TM_ATTR_DATA] = { .type = NLA_BINARY,
@@ -20,58 +24,162 @@ static const struct nla_policy ath11k_tm_policy[ATH11K_TM_ATTR_MAX + 1] = {
[ATH11K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
};
-/* Returns true if callee consumes the skb and the skb should be discarded.
- * Returns false if skb is not used. Does not sleep.
+static struct ath11k *ath11k_tm_get_ar(struct ath11k_base *ab)
+{
+ struct ath11k_pdev *pdev;
+ struct ath11k *ar = NULL;
+ int i;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+
+ if (ar && ar->state == ATH11K_STATE_FTM)
+ break;
+ }
+
+ return ar;
+}
+
+/* This function handles unsegmented events. Data in various events are aggregated
+ * in application layer, this event is unsegmented from host perspective.
*/
-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
+static void ath11k_tm_wmi_event_unsegmented(struct ath11k_base *ab, u32 cmd_id,
+ struct sk_buff *skb)
{
struct sk_buff *nl_skb;
- bool consumed;
- int ret;
+ struct ath11k *ar;
- ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode event wmi cmd_id %d skb %pK skb->len %d\n",
- cmd_id, skb, skb->len);
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "event wmi cmd_id %d skb length %d\n",
+ cmd_id, skb->len);
+ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
- ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
+ ar = ath11k_tm_get_ar(ab);
+ if (!ar) {
+ ath11k_warn(ab, "testmode event not handled due to invalid pdev\n");
+ return;
+ }
spin_lock_bh(&ar->data_lock);
- consumed = true;
-
nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
- 2 * sizeof(u32) + skb->len,
+ 2 * nla_total_size(sizeof(u32)) +
+ nla_total_size(skb->len),
GFP_ATOMIC);
if (!nl_skb) {
- ath11k_warn(ar->ab,
- "failed to allocate skb for testmode wmi event\n");
+ ath11k_warn(ab,
+ "failed to allocate skb for unsegmented testmode wmi event\n");
goto out;
}
- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to put testmode wmi event cmd attribute: %d\n",
- ret);
+ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD, ATH11K_TM_CMD_WMI) ||
+ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) ||
+ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data)) {
+ ath11k_warn(ab, "failed to populate testmode unsegmented event\n");
kfree_skb(nl_skb);
goto out;
}
- ret = nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to put testmode wmi even cmd_id: %d\n",
- ret);
- kfree_skb(nl_skb);
+ cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+
+out:
+ spin_unlock_bh(&ar->data_lock);
+ ath11k_warn(ab, "Failed to send testmode event to higher layers\n");
+}
+
+/* This function handles segmented events. Data of various events received
+ * from firmware is aggregated and sent to application layer
+ */
+static int ath11k_tm_process_event(struct ath11k_base *ab, u32 cmd_id,
+ const struct wmi_ftm_event_msg *ftm_msg,
+ u16 length)
+{
+ struct sk_buff *nl_skb;
+ int ret = 0;
+ struct ath11k *ar;
+ u8 const *buf_pos;
+ u16 datalen;
+ u8 total_segments, current_seq;
+ u32 data_pos;
+ u32 pdev_id;
+
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "event wmi cmd_id %d ftm event msg %pK datalen %d\n",
+ cmd_id, ftm_msg, length);
+ ath11k_dbg_dump(ab, ATH11K_DBG_TESTMODE, NULL, "", ftm_msg, length);
+ pdev_id = DP_HW2SW_MACID(ftm_msg->seg_hdr.pdev_id);
+
+ if (pdev_id >= ab->num_radios) {
+ ath11k_warn(ab, "testmode event not handled due to invalid pdev id: %d\n",
+ pdev_id);
+ return -EINVAL;
+ }
+
+ ar = ab->pdevs[pdev_id].ar;
+ if (!ar) {
+ ath11k_warn(ab, "testmode event not handled due to absence of pdev\n");
+ return -ENODEV;
+ }
+
+ current_seq = FIELD_GET(ATH11K_FTM_SEGHDR_CURRENT_SEQ,
+ ftm_msg->seg_hdr.segmentinfo);
+ total_segments = FIELD_GET(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS,
+ ftm_msg->seg_hdr.segmentinfo);
+ datalen = length - (sizeof(struct wmi_ftm_seg_hdr));
+ buf_pos = ftm_msg->data;
+
+ spin_lock_bh(&ar->data_lock);
+
+ if (current_seq == 0) {
+ ab->testmode.expected_seq = 0;
+ ab->testmode.data_pos = 0;
+ }
+
+ data_pos = ab->testmode.data_pos;
+
+ if ((data_pos + datalen) > ATH11K_FTM_EVENT_MAX_BUF_LENGTH) {
+ ath11k_warn(ab, "Invalid ftm event length at %d: %d\n",
+ data_pos, datalen);
+ ret = -EINVAL;
goto out;
}
- ret = nla_put(nl_skb, ATH11K_TM_ATTR_DATA, skb->len, skb->data);
- if (ret) {
- ath11k_warn(ar->ab,
- "failed to copy skb to testmode wmi event: %d\n",
- ret);
+ memcpy(&ab->testmode.eventdata[data_pos], buf_pos, datalen);
+ data_pos += datalen;
+
+ if (++ab->testmode.expected_seq != total_segments) {
+ ab->testmode.data_pos = data_pos;
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "partial data received current_seq %d total_seg %d\n",
+ current_seq, total_segments);
+ goto out;
+ }
+
+ ath11k_dbg(ab, ATH11K_DBG_TESTMODE,
+ "total data length pos %d len %d\n",
+ data_pos, ftm_msg->seg_hdr.len);
+ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
+ 2 * nla_total_size(sizeof(u32)) +
+ nla_total_size(data_pos),
+ GFP_ATOMIC);
+ if (!nl_skb) {
+ ath11k_warn(ab,
+ "failed to allocate skb for segmented testmode wmi event\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (nla_put_u32(nl_skb, ATH11K_TM_ATTR_CMD,
+ ATH11K_TM_CMD_WMI_FTM) ||
+ nla_put_u32(nl_skb, ATH11K_TM_ATTR_WMI_CMDID, cmd_id) ||
+ nla_put(nl_skb, ATH11K_TM_ATTR_DATA, data_pos,
+ &ab->testmode.eventdata[0])) {
+ ath11k_warn(ab, "failed to populate segmented testmode event");
kfree_skb(nl_skb);
+ ret = -ENOBUFS;
goto out;
}
@@ -79,8 +187,45 @@ bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb)
out:
spin_unlock_bh(&ar->data_lock);
+ return ret;
+}
+
+static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id,
+ struct sk_buff *skb)
+{
+ const void **tb;
+ const struct wmi_ftm_event_msg *ev;
+ u16 length;
+ int ret;
+
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath11k_warn(ab, "failed to parse ftm event tlv: %d\n", ret);
+ return;
+ }
+
+ ev = tb[WMI_TAG_ARRAY_BYTE];
+ if (!ev) {
+ ath11k_warn(ab, "failed to fetch ftm msg\n");
+ kfree(tb);
+ return;
+ }
- return consumed;
+ length = skb->len - TLV_HDR_SIZE;
+ ret = ath11k_tm_process_event(ab, cmd_id, ev, length);
+ if (ret)
+ ath11k_warn(ab, "Failed to process ftm event\n");
+
+ kfree(tb);
+}
+
+void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb)
+{
+ if (test_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags))
+ ath11k_tm_wmi_event_segmented(ab, cmd_id, skb);
+ else
+ ath11k_tm_wmi_event_unsegmented(ab, cmd_id, skb);
}
static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
@@ -89,7 +234,7 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
int ret;
ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode cmd get version_major %d version_minor %d\n",
+ "cmd get version_major %d version_minor %d\n",
ATH11K_TESTMODE_VERSION_MAJOR,
ATH11K_TESTMODE_VERSION_MINOR);
@@ -115,21 +260,56 @@ static int ath11k_tm_cmd_get_version(struct ath11k *ar, struct nlattr *tb[])
return cfg80211_testmode_reply(skb);
}
-static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[])
+static int ath11k_tm_cmd_testmode_start(struct ath11k *ar, struct nlattr *tb[])
+{
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state == ATH11K_STATE_FTM) {
+ ret = -EALREADY;
+ goto err;
+ }
+
+ /* start utf only when the driver is not in use */
+ if (ar->state != ATH11K_STATE_OFF) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ ar->ab->testmode.eventdata = kzalloc(ATH11K_FTM_EVENT_MAX_BUF_LENGTH,
+ GFP_KERNEL);
+ if (!ar->ab->testmode.eventdata) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ar->state = ATH11K_STATE_FTM;
+ ar->ftm_msgref = 0;
+
+ mutex_unlock(&ar->conf_mutex);
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE, "cmd start\n");
+ return 0;
+
+err:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[],
+ struct ieee80211_vif *vif)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct sk_buff *skb;
+ struct ath11k_vif *arvif;
u32 cmd_id, buf_len;
- int ret;
+ int ret, tag;
void *buf;
+ u32 *ptr;
mutex_lock(&ar->conf_mutex);
- if (ar->state != ATH11K_STATE_ON) {
- ret = -ENETDOWN;
- goto out;
- }
-
if (!tb[ATH11K_TM_ATTR_DATA]) {
ret = -EINVAL;
goto out;
@@ -142,11 +322,45 @@ static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[])
buf = nla_data(tb[ATH11K_TM_ATTR_DATA]);
buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]);
+ if (!buf_len) {
+ ath11k_warn(ar->ab, "No data present in testmode wmi command\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
cmd_id = nla_get_u32(tb[ATH11K_TM_ATTR_WMI_CMDID]);
+ /* Make sure that the buffer length is long enough to
+ * hold TLV and pdev/vdev id.
+ */
+ if (buf_len < sizeof(struct wmi_tlv) + sizeof(u32)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ptr = buf;
+ tag = FIELD_GET(WMI_TLV_TAG, *ptr);
+
+ /* pdev/vdev id start after TLV header */
+ ptr++;
+
+ if (tag == WMI_TAG_PDEV_SET_PARAM_CMD)
+ *ptr = ar->pdev->pdev_id;
+
+ if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM &&
+ (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) {
+ if (vif) {
+ arvif = (struct ath11k_vif *)vif->drv_priv;
+ *ptr = arvif->vdev_id;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
- "testmode cmd wmi cmd_id %d buf %pK buf_len %d\n",
- cmd_id, buf, buf_len);
+ "cmd wmi cmd_id %d buf length %d\n",
+ cmd_id, buf_len);
ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len);
@@ -173,6 +387,91 @@ out:
return ret;
}
+static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[])
+{
+ struct ath11k_pdev_wmi *wmi = ar->wmi;
+ struct ath11k_base *ab = ar->ab;
+ struct sk_buff *skb;
+ u32 cmd_id, buf_len, hdr_info;
+ int ret;
+ void *buf;
+ u8 segnumber = 0, seginfo;
+ u16 chunk_len, total_bytes, num_segments;
+ u8 *bufpos;
+ struct wmi_ftm_cmd *ftm_cmd;
+
+ set_bit(ATH11K_FLAG_FTM_SEGMENTED, &ab->dev_flags);
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH11K_STATE_FTM) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ if (!tb[ATH11K_TM_ATTR_DATA]) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf = nla_data(tb[ATH11K_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[ATH11K_TM_ATTR_DATA]);
+ cmd_id = WMI_PDEV_UTF_CMDID;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_TESTMODE,
+ "cmd wmi ftm cmd_id %d buffer length %d\n",
+ cmd_id, buf_len);
+ ath11k_dbg_dump(ar->ab, ATH11K_DBG_TESTMODE, NULL, "", buf, buf_len);
+
+ bufpos = buf;
+ total_bytes = buf_len;
+ num_segments = total_bytes / MAX_WMI_UTF_LEN;
+
+ if (buf_len - (num_segments * MAX_WMI_UTF_LEN))
+ num_segments++;
+
+ while (buf_len) {
+ chunk_len = min_t(u16, buf_len, MAX_WMI_UTF_LEN);
+
+ skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, (chunk_len +
+ sizeof(struct wmi_ftm_cmd)));
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ftm_cmd = (struct wmi_ftm_cmd *)skb->data;
+ hdr_info = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
+ FIELD_PREP(WMI_TLV_LEN, (chunk_len +
+ sizeof(struct wmi_ftm_seg_hdr)));
+ ftm_cmd->tlv_header = hdr_info;
+ ftm_cmd->seg_hdr.len = total_bytes;
+ ftm_cmd->seg_hdr.msgref = ar->ftm_msgref;
+ seginfo = FIELD_PREP(ATH11K_FTM_SEGHDR_TOTAL_SEGMENTS, num_segments) |
+ FIELD_PREP(ATH11K_FTM_SEGHDR_CURRENT_SEQ, segnumber);
+ ftm_cmd->seg_hdr.segmentinfo = seginfo;
+ segnumber++;
+
+ memcpy(&ftm_cmd->data, bufpos, chunk_len);
+
+ ret = ath11k_wmi_cmd_send(wmi, skb, cmd_id);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to send wmi ftm command: %d\n", ret);
+ goto out;
+ }
+
+ buf_len -= chunk_len;
+ bufpos += chunk_len;
+ }
+
+ ar->ftm_msgref++;
+ ret = 0;
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len)
{
@@ -192,7 +491,11 @@ int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case ATH11K_TM_CMD_GET_VERSION:
return ath11k_tm_cmd_get_version(ar, tb);
case ATH11K_TM_CMD_WMI:
- return ath11k_tm_cmd_wmi(ar, tb);
+ return ath11k_tm_cmd_wmi(ar, tb, vif);
+ case ATH11K_TM_CMD_TESTMODE_START:
+ return ath11k_tm_cmd_testmode_start(ar, tb);
+ case ATH11K_TM_CMD_WMI_FTM:
+ return ath11k_tm_cmd_wmi_ftm(ar, tb);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/ath/ath11k/testmode.h b/drivers/net/wireless/ath/ath11k/testmode.h
index aaa122ed9069..2f62f2c4422f 100644
--- a/drivers/net/wireless/ath/ath11k/testmode.h
+++ b/drivers/net/wireless/ath/ath11k/testmode.h
@@ -1,22 +1,22 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
#ifdef CONFIG_NL80211_TESTMODE
-bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id, struct sk_buff *skb);
+void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id, struct sk_buff *skb);
int ath11k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
#else
-static inline bool ath11k_tm_event_wmi(struct ath11k *ar, u32 cmd_id,
+static inline void ath11k_tm_wmi_event(struct ath11k_base *ab, u32 cmd_id,
struct sk_buff *skb)
{
- return false;
}
static inline int ath11k_tm_cmd(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath11k/testmode_i.h b/drivers/net/wireless/ath/ath11k/testmode_i.h
index 4bae2a9eeea4..91b83873d660 100644
--- a/drivers/net/wireless/ath/ath11k/testmode_i.h
+++ b/drivers/net/wireless/ath/ath11k/testmode_i.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
/* "API" level of the ath11k testmode interface. Bump it after every
@@ -11,9 +12,10 @@
/* Bump this after every _compatible_ interface change, for example
* addition of a new command or an attribute.
*/
-#define ATH11K_TESTMODE_VERSION_MINOR 0
+#define ATH11K_TESTMODE_VERSION_MINOR 1
#define ATH11K_TM_DATA_MAX_LEN 5000
+#define ATH11K_FTM_EVENT_MAX_BUF_LENGTH 2048
enum ath11k_tm_attr {
__ATH11K_TM_ATTR_INVALID = 0,
@@ -47,4 +49,18 @@ enum ath11k_tm_cmd {
* ATH11K_TM_ATTR_DATA.
*/
ATH11K_TM_CMD_WMI = 1,
+
+ /* Boots the UTF firmware, the netdev interface must be down at the
+ * time.
+ */
+ ATH11K_TM_CMD_TESTMODE_START = 2,
+
+ /* The command used to transmit a FTM WMI command to the firmware
+ * and the event to receive WMI events from the firmware. The data
+ * received only contain the payload, need to add the tlv header
+ * and send the cmd to firmware with command id WMI_PDEV_UTF_CMDID.
+ * The data payload size could be large and the driver needs to
+ * send segmented data to firmware.
+ */
+ ATH11K_TM_CMD_WMI_FTM = 3,
};
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index d0b59bc2905a..23ad6825e5be 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/skbuff.h>
#include <linux/ctype.h>
@@ -19,6 +19,7 @@
#include "mac.h"
#include "hw.h"
#include "peer.h"
+#include "testmode.h"
struct wmi_tlv_policy {
size_t min_len;
@@ -237,9 +238,8 @@ static int ath11k_wmi_tlv_parse(struct ath11k_base *ar, const void **tb,
(void *)tb);
}
-static const void **
-ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
- size_t len, gfp_t gfp)
+const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
+ size_t len, gfp_t gfp)
{
const void **tb;
int ret;
@@ -606,6 +606,8 @@ static int ath11k_service_ready_event(struct ath11k_base *ab, struct sk_buff *sk
return ret;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready");
+
return 0;
}
@@ -690,6 +692,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd mgmt tx send");
+
return ret;
}
@@ -724,6 +728,9 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
cmd->vdev_subtype = param->subtype;
cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX;
cmd->pdev_id = param->pdev_id;
+ cmd->mbssid_flags = param->mbssid_flags;
+ cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id;
+
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
ptr = skb->data + sizeof(*cmd);
@@ -763,7 +770,7 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n",
+ "cmd vdev create id %d type %d subtype %d macaddr %pM pdevid %d\n",
param->if_id, param->type, param->subtype,
macaddr, param->pdev_id);
@@ -792,7 +799,7 @@ int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev delete id %d\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev delete id %d\n", vdev_id);
return ret;
}
@@ -820,7 +827,7 @@ int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev stop id 0x%x\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev stop id 0x%x\n", vdev_id);
return ret;
}
@@ -848,7 +855,7 @@ int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id)
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "WMI vdev down id 0x%x\n", vdev_id);
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev down id 0x%x\n", vdev_id);
return ret;
}
@@ -941,6 +948,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
cmd->cac_duration_ms = arg->cac_duration_ms;
cmd->regdomain = arg->regdomain;
cmd->he_ops = arg->he_ops;
+ cmd->mbssid_flags = arg->mbssid_flags;
+ cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id;
if (!restart) {
if (arg->ssid) {
@@ -989,14 +998,15 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
dev_kfree_skb(skb);
}
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "vdev %s id 0x%x freq 0x%x mode 0x%x\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev %s id 0x%x freq 0x%x mode 0x%x\n",
restart ? "restart" : "start", arg->vdev_id,
arg->channel.freq, arg->channel.mode);
return ret;
}
-int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
+int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid,
+ u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_vdev_up_cmd *cmd;
@@ -1020,14 +1030,19 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
ether_addr_copy(cmd->vdev_bssid.addr, bssid);
+ cmd->nontx_profile_idx = nontx_profile_idx;
+ cmd->nontx_profile_cnt = nontx_profile_cnt;
+ if (tx_bssid)
+ ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid);
+
if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) {
bss_conf = &arvif->vif->bss_conf;
if (bss_conf->nontransmitted) {
- ether_addr_copy(cmd->trans_bssid.addr,
+ ether_addr_copy(cmd->tx_vdev_bssid.addr,
bss_conf->transmitter_bssid);
- cmd->profile_idx = bss_conf->bssid_index;
- cmd->profile_num = bss_conf->bssid_indicator;
+ cmd->nontx_profile_idx = bss_conf->bssid_index;
+ cmd->nontx_profile_cnt = bss_conf->bssid_indicator;
}
}
@@ -1038,7 +1053,7 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
+ "cmd vdev up id 0x%x assoc id %d bssid %pM\n",
vdev_id, aid, bssid);
return ret;
@@ -1071,7 +1086,7 @@ int ath11k_wmi_send_peer_create_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer create vdev_id %d peer_addr %pM\n",
+ "cmd peer create vdev_id %d peer_addr %pM\n",
param->vdev_id, param->peer_addr);
return ret;
@@ -1096,16 +1111,16 @@ int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
cmd->vdev_id = vdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer delete vdev_id %d peer_addr %pM\n",
- vdev_id, peer_addr);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_DELETE_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_PEER_DELETE cmd\n");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd peer delete vdev_id %d peer_addr %pM\n",
+ vdev_id, peer_addr);
+
return ret;
}
@@ -1134,11 +1149,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
cmd->dfs_domain = param->dfs_domain;
cmd->pdev_id = param->pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n",
- param->current_rd_in_use, param->current_rd_2g,
- param->current_rd_5g, param->dfs_domain, param->pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_REGDOMAIN_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@@ -1146,6 +1156,11 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev regd rd %d rd2g %d rd5g %d domain %d pdev id %d\n",
+ param->current_rd_in_use, param->current_rd_2g,
+ param->current_rd_5g, param->dfs_domain, param->pdev_id);
+
return ret;
}
@@ -1176,7 +1191,7 @@ int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %d peer 0x%pM set param %d value %d\n",
+ "cmd peer set param vdev %d peer 0x%pM set param %d value %d\n",
vdev_id, peer_addr, param_id, param_val);
return ret;
@@ -1211,7 +1226,7 @@ int ath11k_wmi_send_peer_flush_tids_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI peer flush vdev_id %d peer_addr %pM tids %08x\n",
+ "cmd peer flush tids vdev_id %d peer_addr %pM tids %08x\n",
param->vdev_id, peer_addr, param->peer_tid_bitmap);
return ret;
@@ -1254,7 +1269,7 @@ int ath11k_wmi_peer_rx_reorder_queue_setup(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi rx reorder queue setup addr %pM vdev_id %d tid %d\n",
+ "cmd peer reorder queue setup addr %pM vdev_id %d tid %d\n",
addr, vdev_id, tid);
return ret;
@@ -1282,10 +1297,6 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,
cmd->vdev_id = param->vdev_id;
cmd->tid_mask = param->peer_tid_bitmap;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "%s: peer_macaddr %pM vdev_id %d, tid_map %d", __func__,
- param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PEER_REORDER_QUEUE_REMOVE_CMDID);
if (ret) {
@@ -1294,6 +1305,10 @@ ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd peer reorder queue remove peer_macaddr %pM vdev_id %d tid_map %d",
+ param->peer_macaddr, param->vdev_id, param->peer_tid_bitmap);
+
return ret;
}
@@ -1323,7 +1338,7 @@ int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev set param %d pdev id %d value %d\n",
+ "cmd pdev set param %d pdev id %d value %d\n",
param_id, pdev_id, param_value);
return ret;
@@ -1354,7 +1369,7 @@ int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev set psmode %d vdev id %d\n",
+ "cmd sta powersave mode psmode %d vdev id %d\n",
psmode, vdev_id);
return ret;
@@ -1387,7 +1402,7 @@ int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev suspend pdev_id %d\n", pdev_id);
+ "cmd pdev suspend pdev_id %d\n", pdev_id);
return ret;
}
@@ -1409,15 +1424,15 @@ int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id)
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->pdev_id = pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev resume pdev id %d\n", pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_RESUME_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_PDEV_RESUME cmd\n");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev resume pdev id %d\n", pdev_id);
+
return ret;
}
@@ -1445,9 +1460,6 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
cmd->req_type = type;
cmd->pdev_id = ar->pdev->pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI bss chan info req type %d\n", type);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_BSS_CHAN_INFO_REQUEST_CMDID);
if (ret) {
@@ -1456,6 +1468,9 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev bss chan info request type %d\n", type);
+
return ret;
}
@@ -1488,7 +1503,7 @@ int ath11k_wmi_send_set_ap_ps_param_cmd(struct ath11k *ar, u8 *peer_addr,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI set ap ps vdev id %d peer %pM param %d value %d\n",
+ "cmd ap ps peer param vdev id %d peer %pM param %d value %d\n",
param->vdev_id, peer_addr, param->param, param->value);
return ret;
@@ -1515,16 +1530,16 @@ int ath11k_wmi_set_sta_ps_param(struct ath11k *ar, u32 vdev_id,
cmd->param = param;
cmd->value = param_value;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI set sta ps vdev_id %d param %d value %d\n",
- vdev_id, param, param_value);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_STA_POWERSAVE_PARAM_CMDID);
if (ret) {
ath11k_warn(ar->ab, "failed to send WMI_STA_POWERSAVE_PARAM_CMDID");
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd set powersave param vdev_id %d param %d value %d\n",
+ vdev_id, param, param_value);
+
return ret;
}
@@ -1554,6 +1569,9 @@ int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms)
ath11k_warn(ar->ab, "Failed to send WMI_FORCE_FW_HANG_CMDID");
dev_kfree_skb(skb);
}
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd force fw hang");
+
return ret;
}
@@ -1585,7 +1603,7 @@ int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev id 0x%x set param %d value %d\n",
+ "cmd vdev set param vdev 0x%x param %d value %d\n",
vdev_id, param_id, param_value);
return ret;
@@ -1618,7 +1636,7 @@ int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI request stats 0x%x vdev id %d pdev id %d\n",
+ "cmd request stats 0x%x vdev id %d pdev id %d\n",
param->stats_id, param->vdev_id, param->pdev_id);
return ret;
@@ -1647,7 +1665,7 @@ int ath11k_wmi_send_pdev_temperature_cmd(struct ath11k *ar)
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id);
+ "cmd pdev get temperature for pdev_id %d\n", ar->pdev->pdev_id);
return ret;
}
@@ -1672,10 +1690,6 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
cmd->vdev_id = vdev_id;
cmd->bcn_ctrl_op = bcn_ctrl_op;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI bcn ctrl offload vdev id %d ctrl_op %d\n",
- vdev_id, bcn_ctrl_op);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_BCN_OFFLOAD_CTRL_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@@ -1683,12 +1697,16 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd bcn offload ctrl vdev id %d ctrl_op %d\n",
+ vdev_id, bcn_ctrl_op);
+
return ret;
}
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
- struct sk_buff *bcn)
+ struct sk_buff *bcn, u32 ema_params)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_bcn_tmpl_cmd *cmd;
@@ -1726,6 +1744,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
}
cmd->buf_len = bcn->len;
+ cmd->mbssid_ie_offset = offs->mbssid_off;
+ cmd->ema_params = ema_params;
ptr = skb->data + sizeof(*cmd);
@@ -1750,6 +1770,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd bcn tmpl");
+
return ret;
}
@@ -1799,7 +1821,7 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev install key idx %d cipher %d len %d\n",
+ "cmd vdev install key idx %d cipher %d len %d\n",
arg->key_idx, arg->key_cipher, arg->key_len);
return ret;
@@ -2035,7 +2057,7 @@ int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
+ "cmd peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
cmd->vdev_id, cmd->peer_associd, param->peer_mac,
cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,
cmd->peer_listen_intval, cmd->peer_ht_caps,
@@ -2352,6 +2374,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd start scan");
+
return ret;
}
@@ -2400,6 +2424,8 @@ int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd stop scan");
+
return ret;
}
@@ -2444,7 +2470,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
cmd->flags |= WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",
+ "no.of chan = %d len = %d pdev_id = %d num_sends = %d\n",
num_send_chans, len, cmd->pdev_id, num_sends);
ptr = skb->data + sizeof(*cmd);
@@ -2503,7 +2529,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
tchan_info->maxregpower);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI chan scan list chan[%d] = %u, chan_info->info %8x\n",
+ "chan scan list chan[%d] = %u, chan_info->info %8x\n",
i, chan_info->mhz, chan_info->info);
ptr += sizeof(*chan_info);
@@ -2518,6 +2544,9 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar,
return ret;
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd scan chan list channels %d",
+ num_send_chans);
+
num_sends++;
}
@@ -2577,7 +2606,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
wmm_param->no_ack = wmi_wmm_arg->no_ack;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n",
+ "wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n",
ac, wmm_param->aifs, wmm_param->cwmin,
wmm_param->cwmax, wmm_param->txoplimit,
wmm_param->acm, wmm_param->no_ack);
@@ -2590,6 +2619,8 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd vdev set wmm params");
+
return ret;
}
@@ -2613,9 +2644,6 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar,
cmd->pdev_id = pdev_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI dfs phy err offload enable pdev id %d\n", pdev_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_DFS_PHYERR_OFFLOAD_ENABLE_CMDID);
if (ret) {
@@ -2624,6 +2652,9 @@ int ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(struct ath11k *ar,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev dfs phyerr offload enable pdev id %d\n", pdev_id);
+
return ret;
}
@@ -2648,10 +2679,6 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->initiator = initiator;
cmd->reasoncode = reason;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
- vdev_id, mac, tid, initiator, reason);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_DELBA_SEND_CMDID);
if (ret) {
@@ -2660,6 +2687,10 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
+ vdev_id, mac, tid, initiator, reason);
+
return ret;
}
@@ -2684,10 +2715,6 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->tid = tid;
cmd->statuscode = status;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
- vdev_id, mac, tid, status);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SET_RESP_CMDID);
if (ret) {
@@ -2696,6 +2723,10 @@ int ath11k_wmi_addba_set_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
+ vdev_id, mac, tid, status);
+
return ret;
}
@@ -2719,10 +2750,6 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
cmd->tid = tid;
cmd->buffersize = buf_size;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
- vdev_id, mac, tid, buf_size);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_SEND_CMDID);
if (ret) {
@@ -2731,6 +2758,10 @@ int ath11k_wmi_addba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
+ vdev_id, mac, tid, buf_size);
+
return ret;
}
@@ -2752,10 +2783,6 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac)
cmd->vdev_id = vdev_id;
ether_addr_copy(cmd->peer_macaddr.addr, mac);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n",
- vdev_id, mac);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ADDBA_CLEAR_RESP_CMDID);
if (ret) {
@@ -2764,6 +2791,10 @@ int ath11k_wmi_addba_clear_resp(struct ath11k *ar, u32 vdev_id, const u8 *mac)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd addba clear resp vdev_id 0x%X mac_addr %pM\n",
+ vdev_id, mac);
+
return ret;
}
@@ -2812,6 +2843,8 @@ int ath11k_wmi_pdev_peer_pktlog_filter(struct ath11k *ar, u8 *addr, u8 enable)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog filter");
+
return ret;
}
@@ -2851,21 +2884,27 @@ ath11k_wmi_send_init_country_cmd(struct ath11k *ar,
cmd->cc_info.regdom_id = init_cc_params.cc_info.regdom_id;
break;
default:
+ ath11k_warn(ar->ab, "unknown cc params flags: 0x%x",
+ init_cc_params.flags);
ret = -EINVAL;
- goto out;
+ goto err;
}
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_SET_INIT_COUNTRY_CMDID);
-
-out:
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_SET_INIT_COUNTRY CMD :%d\n",
ret);
- dev_kfree_skb(skb);
+ goto err;
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd set init country");
+
+ return 0;
+
+err:
+ dev_kfree_skb(skb);
return ret;
}
@@ -2888,20 +2927,20 @@ int ath11k_wmi_send_set_current_country_cmd(struct ath11k *ar,
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(&cmd->new_alpha2, &param->alpha2, 3);
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "set current country pdev id %d alpha2 %c%c\n",
- ar->pdev->pdev_id,
- param->alpha2[0],
- param->alpha2[1]);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd set current country pdev id %d alpha2 %c%c\n",
+ ar->pdev->pdev_id,
+ param->alpha2[0],
+ param->alpha2[1]);
+
return ret;
}
@@ -2962,7 +3001,7 @@ ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev set thermal throt pdev_id %d enable %d dc %d dc_per_event %x levels %d\n",
+ "cmd therm throt set conf pdev_id %d enable %d dc %d dc_per_event %x levels %d\n",
ar->pdev->pdev_id, param->enable, param->dc,
param->dc_per_event, THERMAL_LEVELS);
@@ -2989,20 +3028,20 @@ int ath11k_wmi_send_11d_scan_start_cmd(struct ath11k *ar,
cmd->vdev_id = param->vdev_id;
cmd->scan_period_msec = param->scan_period_msec;
cmd->start_interval_msec = param->start_interval_msec;
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "send 11d scan start vdev id %d period %d ms internal %d ms\n",
- cmd->vdev_id,
- cmd->scan_period_msec,
- cmd->start_interval_msec);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd 11d scan start vdev id %d period %d ms internal %d ms\n",
+ cmd->vdev_id,
+ cmd->scan_period_msec,
+ cmd->start_interval_msec);
+
return ret;
}
@@ -3023,18 +3062,18 @@ int ath11k_wmi_send_11d_scan_stop_cmd(struct ath11k *ar, u32 vdev_id)
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->vdev_id = vdev_id;
- ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
-
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "send 11d scan stop vdev id %d\n",
- cmd->vdev_id);
+ ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd 11d scan stop vdev id %d\n",
+ cmd->vdev_id);
+
return ret;
}
@@ -3065,6 +3104,8 @@ int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog enable");
+
return ret;
}
@@ -3093,6 +3134,8 @@ int ath11k_wmi_pdev_pktlog_disable(struct ath11k *ar)
dev_kfree_skb(skb);
}
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd pdev pktlog disable");
+
return ret;
}
@@ -3162,10 +3205,14 @@ int ath11k_wmi_send_twt_enable_cmd(struct ath11k *ar, u32 pdev_id,
if (ret) {
ath11k_warn(ab, "Failed to send WMI_TWT_ENABLE_CMDID");
dev_kfree_skb(skb);
- } else {
- ar->twt_enabled = 1;
+ return ret;
}
- return ret;
+
+ ar->twt_enabled = 1;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt enable");
+
+ return 0;
}
int
@@ -3192,10 +3239,14 @@ ath11k_wmi_send_twt_disable_cmd(struct ath11k *ar, u32 pdev_id)
if (ret) {
ath11k_warn(ab, "Failed to send WMI_TWT_DISABLE_CMDID");
dev_kfree_skb(skb);
- } else {
- ar->twt_enabled = 0;
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd twt disable");
+
+ ar->twt_enabled = 0;
+
+ return 0;
}
int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
@@ -3234,21 +3285,22 @@ int ath11k_wmi_send_twt_add_dialog_cmd(struct ath11k *ar,
if (params->flag_protection)
cmd->flags |= WMI_TWT_ADD_DIALOG_FLAG_PROTECTION;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi add twt dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n",
- cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us,
- cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us,
- cmd->flags);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_ADD_DIALOG_CMDID);
-
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to add twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt add dialog vdev %u dialog id %u wake interval %u mantissa %u wake duration %u service period offset %u flags 0x%x\n",
+ cmd->vdev_id, cmd->dialog_id, cmd->wake_intvl_us,
+ cmd->wake_intvl_mantis, cmd->wake_dura_us, cmd->sp_offset_us,
+ cmd->flags);
+
+ return 0;
}
int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar,
@@ -3274,18 +3326,20 @@ int ath11k_wmi_send_twt_del_dialog_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr);
cmd->dialog_id = params->dialog_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi delete twt dialog vdev %u dialog id %u\n",
- cmd->vdev_id, cmd->dialog_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_DEL_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to delete twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt del dialog vdev %u dialog id %u\n",
+ cmd->vdev_id, cmd->dialog_id);
+
+ return 0;
}
int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar,
@@ -3312,18 +3366,20 @@ int ath11k_wmi_send_twt_pause_dialog_cmd(struct ath11k *ar,
ether_addr_copy(cmd->peer_macaddr.addr, params->peer_macaddr);
cmd->dialog_id = params->dialog_id;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi pause twt dialog vdev %u dialog id %u\n",
- cmd->vdev_id, cmd->dialog_id);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_PAUSE_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to pause twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt pause dialog vdev %u dialog id %u\n",
+ cmd->vdev_id, cmd->dialog_id);
+
+ return 0;
}
int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar,
@@ -3352,19 +3408,21 @@ int ath11k_wmi_send_twt_resume_dialog_cmd(struct ath11k *ar,
cmd->sp_offset_us = params->sp_offset_us;
cmd->next_twt_size = params->next_twt_size;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi resume twt dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n",
- cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us,
- cmd->next_twt_size);
-
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_TWT_RESUME_DIALOG_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send wmi command to resume twt dialog: %d",
ret);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd twt resume dialog vdev %u dialog id %u service period offset %u next twt subfield size %u\n",
+ cmd->vdev_id, cmd->dialog_id, cmd->sp_offset_us,
+ cmd->next_twt_size);
+
+ return 0;
}
int
@@ -3398,8 +3456,12 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
ath11k_warn(ab,
"Failed to send WMI_PDEV_OBSS_PD_SPATIAL_REUSE_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev obss pd spatial reuse");
+
+ return 0;
}
int
@@ -3424,19 +3486,20 @@ ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd pdev_id %d bss color bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg bss color bitmap pdev_id %d bss color bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3462,19 +3525,20 @@ ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd pdev_id %d partial bssid bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg partial bssid bitmap pdev_id %d partial bssid bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3500,19 +3564,20 @@ ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg obsscolor enable pdev_id %d bss color enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3538,19 +3603,20 @@ ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3576,19 +3642,20 @@ ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set non srg obss color enable bitmap pdev_id %d bss color enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3614,19 +3681,20 @@ ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
cmd->pdev_id = ar->pdev->pdev_id;
memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n",
- cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
if (ret) {
ath11k_warn(ab,
"failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd pdev set non srg obss bssid enable bitmap pdev_id %d bssid enable bitmap %08x %08x\n",
+ cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);
+
+ return 0;
}
int
@@ -3659,18 +3727,20 @@ ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
cmd->free_slot_expiry_time_ms = 0;
cmd->flags = 0;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi_send_obss_color_collision_cfg id %d type %d bss_color %d detect_period %d scan_period %d\n",
- cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,
- cmd->detection_period_ms, cmd->scan_period_ms);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_OBSS_COLOR_COLLISION_DET_CONFIG_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd obss color collision det config id %d type %d bss_color %d detect_period %d scan_period %d\n",
+ cmd->vdev_id, cmd->evt_type, cmd->current_bss_color,
+ cmd->detection_period_ms, cmd->scan_period_ms);
+
+ return 0;
}
int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
@@ -3694,17 +3764,19 @@ int ath11k_wmi_send_bss_color_change_enable_cmd(struct ath11k *ar, u32 vdev_id,
cmd->vdev_id = vdev_id;
cmd->enable = enable ? 1 : 0;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi_send_bss_color_change_enable id %d enable %d\n",
- cmd->vdev_id, cmd->enable);
-
ret = ath11k_wmi_cmd_send(wmi, skb,
WMI_BSS_COLOR_CHANGE_ENABLE_CMDID);
if (ret) {
ath11k_warn(ab, "Failed to send WMI_BSS_COLOR_CHANGE_ENABLE_CMDID");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
+ "cmd bss color change enable id %d enable %d\n",
+ cmd->vdev_id, cmd->enable);
+
+ return 0;
}
int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
@@ -3721,7 +3793,7 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
len = sizeof(*cmd) + TLV_HDR_SIZE + aligned_len;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set FILS discovery template\n", vdev_id);
+ "vdev %i set FILS discovery template\n", vdev_id);
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
if (!skb)
@@ -3746,8 +3818,12 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
"WMI vdev %i failed to send FILS discovery template command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd fils discovery tmpl");
+
+ return 0;
}
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
@@ -3762,7 +3838,7 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
size_t aligned_len = roundup(tmpl->len, 4);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set probe response template\n", vdev_id);
+ "vdev %i set probe response template\n", vdev_id);
len = sizeof(*cmd) + sizeof(*probe_info) + TLV_HDR_SIZE + aligned_len;
@@ -3799,8 +3875,12 @@ int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
"WMI vdev %i failed to send probe response template command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd ");
+
+ return 0;
}
int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
@@ -3811,7 +3891,7 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
struct wmi_fils_discovery_cmd *cmd;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI vdev %i set %s interval to %u TU\n",
+ "vdev %i set %s interval to %u TU\n",
vdev_id, unsol_bcast_probe_resp_enabled ?
"unsolicited broadcast probe response" : "FILS discovery",
interval);
@@ -3834,8 +3914,12 @@ int ath11k_wmi_fils_discovery(struct ath11k *ar, u32 vdev_id, u32 interval,
"WMI vdev %i failed to send FILS discovery enable/disable command\n",
vdev_id);
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd enable fils");
+
+ return 0;
}
static void
@@ -3853,6 +3937,8 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event obss color collision");
+
rcu_read_lock();
ev = tb[WMI_TAG_OBSS_COLOR_COLLISION_EVT];
@@ -3987,6 +4073,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported <<
WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT);
+ wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET;
+ wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt;
+ wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period;
}
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
@@ -4044,7 +4133,7 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
host_mem_chunks[idx].req_id = param->mem_chunks[idx].req_id;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "WMI host mem chunk req_id %d paddr 0x%llx len %d\n",
+ "host mem chunk req_id %d paddr 0x%llx len %d\n",
param->mem_chunks[idx].req_id,
(u64)param->mem_chunks[idx].paddr,
param->mem_chunks[idx].len);
@@ -4098,9 +4187,12 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
if (ret) {
ath11k_warn(ab, "failed to send WMI_INIT_CMDID\n");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd wmi init");
+
+ return 0;
}
int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar,
@@ -4131,7 +4223,7 @@ int ath11k_wmi_pdev_lro_cfg(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI lro cfg cmd pdev_id 0x%x\n", pdev_id);
+ "cmd lro config pdev_id 0x%x\n", pdev_id);
return 0;
err:
dev_kfree_skb(skb);
@@ -4189,9 +4281,12 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
if (ret) {
ath11k_warn(ab, "failed to send WMI_PDEV_SET_HW_MODE_CMDID\n");
dev_kfree_skb(skb);
+ return ret;
}
- return ret;
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "cmd pdev set hw mode %d", cmd->hw_mode_index);
+
+ return 0;
}
int ath11k_wmi_cmd_init(struct ath11k_base *ab)
@@ -4252,7 +4347,7 @@ int ath11k_wmi_vdev_spectral_conf(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI spectral scan config cmd vdev_id 0x%x\n",
+ "cmd vdev spectral scan configure vdev_id 0x%x\n",
param->vdev_id);
return 0;
@@ -4290,7 +4385,7 @@ int ath11k_wmi_vdev_spectral_enable(struct ath11k *ar, u32 vdev_id,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI spectral enable cmd vdev id 0x%x\n",
+ "cmd vdev spectral scan enable vdev id 0x%x\n",
vdev_id);
return 0;
@@ -4336,7 +4431,7 @@ int ath11k_wmi_pdev_dma_ring_cfg(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI DMA ring cfg req cmd pdev_id 0x%x\n",
+ "cmd pdev dma ring cfg req pdev_id 0x%x\n",
param->pdev_id);
return 0;
@@ -4442,6 +4537,8 @@ static void ath11k_wmi_pdev_dma_ring_buf_release_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev dma ring buf release");
+
param.fixed = parse.fixed;
param.buf_entry = parse.buf_entry;
param.num_buf_entry = parse.num_buf_entry;
@@ -4836,6 +4933,8 @@ static int ath11k_service_ready_ext_event(struct ath11k_base *ab,
goto err;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext");
+
if (!test_bit(WMI_TLV_SERVICE_EXT2_MSG, ab->wmi_ab.svc_map))
complete(&ab->wmi_ab.service_ready);
@@ -4886,6 +4985,8 @@ static int ath11k_service_ready_ext2_event(struct ath11k_base *ab,
goto err;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service ready ext2");
+
complete(&ab->wmi_ab.service_ready);
return 0;
@@ -5757,7 +5858,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
WARN_ON_ONCE(1);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi mgmt tx comp pending %d desc id %d\n",
+ "mgmt tx comp pending %d desc id %d\n",
num_mgmt, tx_compl_param->desc_id);
if (!num_mgmt)
@@ -6326,7 +6427,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
stats->stats_id = WMI_REQUEST_RSSI_PER_CHAIN_STAT;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats vdev id %d mac %pM\n",
+ "stats vdev id %d mac %pM\n",
stats_rssi->vdev_id, stats_rssi->peer_macaddr.addr);
arvif = ath11k_mac_get_arvif(ar, stats_rssi->vdev_id);
@@ -6338,7 +6439,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats bssid %pM vif %pK\n",
+ "stats bssid %pM vif %p\n",
arvif->bssid, arvif->vif);
sta = ieee80211_find_sta_by_ifaddr(ar->hw,
@@ -6359,7 +6460,7 @@ static int ath11k_wmi_tlv_rssi_chain_parse(struct ath11k_base *ab,
for (j = 0; j < ARRAY_SIZE(arsta->chain_signal); j++) {
arsta->chain_signal[j] = stats_rssi->rssi_avg_beacon[j];
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats beacon rssi[%d] %d data rssi[%d] %d\n",
+ "stats beacon rssi[%d] %d data rssi[%d] %d\n",
j,
stats_rssi->rssi_avg_beacon[j],
j,
@@ -6442,7 +6543,7 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab,
arsta = (struct ath11k_sta *)sta->drv_priv;
arsta->rssi_beacon = src->beacon_snr;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats vdev id %d snr %d\n",
+ "stats vdev id %d snr %d\n",
src->vdev_id, src->beacon_snr);
} else {
ath11k_dbg(ab, ATH11K_DBG_WMI,
@@ -6512,7 +6613,7 @@ static int ath11k_wmi_tlv_fw_stats_parse(struct ath11k_base *ab,
parse->rssi_num = parse->rssi->num_per_chain_rssi_stats;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi stats id 0x%x num chain %d\n",
+ "stats id 0x%x num chain %d\n",
parse->ev->stats_id,
parse->rssi_num);
break;
@@ -6548,28 +6649,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
&parse);
}
-size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath11k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-static size_t ath11k_wmi_fw_stats_num_bcn(struct list_head *head)
-{
- struct ath11k_fw_stats_bcn *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
static void
ath11k_wmi_fw_pdev_base_stats_fill(const struct ath11k_fw_stats_pdev *pdev,
char *buf, u32 *length)
@@ -6880,7 +6959,7 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
}
if (stats_id == WMI_REQUEST_BCN_STAT) {
- num_bcn = ath11k_wmi_fw_stats_num_bcn(&fw_stats->bcn);
+ num_bcn = list_count_nodes(&fw_stats->bcn);
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
@@ -6933,7 +7012,7 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s
memcpy(&ab->new_alpha2, &ev->new_alpha2, 2);
spin_unlock_bh(&ab->base_lock);
- ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi 11d new cc %c%c\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event 11d new cc %c%c\n",
ab->new_alpha2[0],
ab->new_alpha2[1]);
@@ -7017,6 +7096,8 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
goto fallback;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg chan list id %d", id);
+
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
/* In case of failure to set the requested ctry,
* fw retains the current regd. We print a failure info
@@ -7182,6 +7263,8 @@ static int ath11k_ready_event(struct ath11k_base *ab, struct sk_buff *skb)
return ret;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event ready");
+
complete(&ab->wmi_ab.unified_ready);
return 0;
}
@@ -7196,6 +7279,8 @@ static void ath11k_peer_delete_resp_event(struct ath11k_base *ab, struct sk_buff
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer delete resp");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, peer_del_resp.vdev_id);
if (!ar) {
@@ -7235,7 +7320,7 @@ static void ath11k_vdev_delete_resp_event(struct ath11k_base *ab,
rcu_read_unlock();
- ath11k_dbg(ab, ATH11K_DBG_WMI, "vdev delete resp for vdev id %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev delete resp for vdev id %d\n",
vdev_id);
}
@@ -7266,6 +7351,8 @@ static void ath11k_vdev_start_resp_event(struct ath11k_base *ab, struct sk_buff
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event start resp event");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_start_resp.vdev_id);
if (!ar) {
@@ -7304,6 +7391,8 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event offload bcn tx status");
+
rcu_read_lock();
arvif = ath11k_mac_get_arvif_by_vdev_id(ab, vdev_id);
if (!arvif) {
@@ -7343,7 +7432,7 @@ static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
+ "event peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n",
ev->peer_macaddr.addr, ev->peer_ps_state,
ev->ps_supported_bitmap, ev->peer_ps_valid,
ev->peer_ps_timestamp);
@@ -7427,6 +7516,8 @@ static void ath11k_vdev_stopped_event(struct ath11k_base *ab, struct sk_buff *sk
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event vdev stopped");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
@@ -7460,7 +7551,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
memset(status, 0, sizeof(*status));
- ath11k_dbg(ab, ATH11K_DBG_MGMT, "mgmt rx event status %08x\n",
+ ath11k_dbg(ab, ATH11K_DBG_MGMT, "event mgmt rx status %08x\n",
rx_ev.status);
rcu_read_lock();
@@ -7503,7 +7594,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
if (rx_ev.phy_mode == MODE_11B &&
(status->band == NL80211_BAND_5GHZ || status->band == NL80211_BAND_6GHZ))
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band);
+ "mgmt rx 11b (CCK) on 5/6GHz, band = %d\n", status->band);
sband = &ar->mac.sbands[status->band];
@@ -7543,7 +7634,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
ath11k_mac_handle_beacon(ar, skb);
ath11k_dbg(ab, ATH11K_DBG_MGMT,
- "event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
+ "event mgmt rx skb %p len %d ftype %02x stype %02x\n",
skb, skb->len,
fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
@@ -7579,7 +7670,7 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s
wmi_process_mgmt_tx_comp(ar, &tx_compl_param);
ath11k_dbg(ab, ATH11K_DBG_MGMT,
- "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
+ "event mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d",
tx_compl_param.pdev_id, tx_compl_param.desc_id,
tx_compl_param.status, tx_compl_param.ack_rssi);
@@ -7650,7 +7741,7 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb)
spin_lock_bh(&ar->data_lock);
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
+ "event scan %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
ath11k_wmi_event_scan_type_str(scan_ev.event_type, scan_ev.reason),
scan_ev.event_type, scan_ev.reason, scan_ev.channel_freq,
scan_ev.scan_req_id, scan_ev.scan_id, scan_ev.vdev_id,
@@ -7733,7 +7824,7 @@ static void ath11k_peer_sta_kickout_event(struct ath11k_base *ab, struct sk_buff
goto exit;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI, "peer sta kickout event %pM",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event peer sta kickout %pM",
arg.mac_addr);
ieee80211_report_low_ack(sta, 10);
@@ -7753,7 +7844,7 @@ static void ath11k_roam_event(struct ath11k_base *ab, struct sk_buff *skb)
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "wmi roam event vdev %u reason 0x%08x rssi %d\n",
+ "event roam vdev %u reason 0x%08x rssi %d\n",
roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi);
rcu_read_lock();
@@ -7800,7 +7891,7 @@ static void ath11k_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb)
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n",
+ "event chan info vdev_id %d err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d mac_clk_mhz %d\n",
ch_info_ev.vdev_id, ch_info_ev.err_code, ch_info_ev.freq,
ch_info_ev.cmd_flags, ch_info_ev.noise_floor,
ch_info_ev.rx_clear_count, ch_info_ev.cycle_count,
@@ -7889,7 +7980,7 @@ ath11k_pdev_bss_chan_info_event(struct ath11k_base *ab, struct sk_buff *skb)
bss_ch_info_ev.rx_bss_cycle_count_low;
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",
+ "event pdev bss chan info:\n pdev_id: %d freq: %d noise: %d cycle: busy %llu total %llu tx %llu rx %llu rx_bss %llu\n",
bss_ch_info_ev.pdev_id, bss_ch_info_ev.freq,
bss_ch_info_ev.noise_floor, busy, total,
tx, rx, rx_bss);
@@ -7943,7 +8034,7 @@ static void ath11k_vdev_install_key_compl_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "vdev install key ev idx %d flags %08x macaddr %pM status %d\n",
+ "event vdev install key ev idx %d flags %08x macaddr %pM status %d\n",
install_key_compl.key_idx, install_key_compl.key_flags,
install_key_compl.macaddr, install_key_compl.status);
@@ -8026,6 +8117,8 @@ static void ath11k_service_available_event(struct ath11k_base *ab, struct sk_buf
NULL);
if (ret)
ath11k_warn(ab, "failed to parse services available tlv %d\n", ret);
+
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event service available");
}
static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff *skb)
@@ -8039,7 +8132,7 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "peer assoc conf ev vdev id %d macaddr %pM\n",
+ "event peer assoc conf ev vdev id %d macaddr %pM\n",
peer_assoc_conf.vdev_id, peer_assoc_conf.macaddr);
rcu_read_lock();
@@ -8072,6 +8165,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
goto free;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event update stats");
+
rcu_read_lock();
ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
if (!ar) {
@@ -8103,6 +8198,11 @@ complete:
rcu_read_unlock();
spin_unlock_bh(&ar->data_lock);
+ /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised
+ * at this point, no need to free the individual list.
+ */
+ return;
+
free:
ath11k_fw_stats_free(&stats);
}
@@ -8132,7 +8232,7 @@ static void ath11k_pdev_ctl_failsafe_check_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev ctl failsafe check ev status %d\n",
+ "event pdev ctl failsafe check status %d\n",
ev->ctl_failsafe_status);
/* If ctl_failsafe_status is set to 1 FW will max out the Transmit power
@@ -8199,7 +8299,7 @@ ath11k_wmi_pdev_csa_switch_count_status_event(struct ath11k_base *ab,
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev csa switch count %d for pdev %d, num_vdevs %d",
+ "event pdev csa switch count %d for pdev %d, num_vdevs %d",
ev->current_switch_count, ev->pdev_id,
ev->num_vdevs);
@@ -8232,7 +8332,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
}
ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d",
+ "event pdev dfs radar detected on pdev %d, detection mode %d, chan freq %d, chan_width %d, detector id %d, seg id %d, timestamp %d, chirp %d, freq offset %d, sidx %d",
ev->pdev_id, ev->detection_mode, ev->chan_freq, ev->chan_width,
ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,
ev->freq_offset, ev->sidx);
@@ -8280,8 +8380,8 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
return;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI,
- "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id);
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event pdev temperature ev temp %d pdev_id %d\n",
+ ev->temp, ev->pdev_id);
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
if (!ar) {
@@ -8311,6 +8411,8 @@ static void ath11k_fils_discovery_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event fils discovery");
+
ev = tb[WMI_TAG_HOST_SWFDA_EVENT];
if (!ev) {
ath11k_warn(ab, "failed to fetch FILS discovery event\n");
@@ -8341,6 +8443,8 @@ static void ath11k_probe_resp_tx_status_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event probe resp tx status");
+
ev = tb[WMI_TAG_OFFLOAD_PRB_RSP_TX_STATUS_EVENT];
if (!ev) {
ath11k_warn(ab,
@@ -8407,6 +8511,8 @@ static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_b
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event wow wakeup host");
+
complete(&ab->wow.wakeup_completed);
}
@@ -8414,6 +8520,8 @@ static void
ath11k_wmi_diag_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event diag");
+
trace_ath11k_wmi_diag(ab, skb->data, skb->len);
}
@@ -8461,6 +8569,8 @@ static void ath11k_wmi_twt_add_dialog_event(struct ath11k_base *ab,
return;
}
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event twt add dialog");
+
ev = tb[WMI_TAG_TWT_ADD_DIALOG_COMPLETE_EVENT];
if (!ev) {
ath11k_warn(ab, "failed to fetch twt add dialog wmi event\n");
@@ -8509,7 +8619,7 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
return;
}
- ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi gtk offload event refresh_cnt %d\n",
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "event gtk offload refresh_cnt %d\n",
ev->refresh_cnt);
ath11k_dbg_dump(ab, ATH11K_DBG_WMI, "replay_cnt",
NULL, ev->replay_ctr.counter, GTK_REPLAY_COUNTER_BYTES);
@@ -8612,6 +8722,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_PDEV_CSA_SWITCH_COUNT_STATUS_EVENTID:
ath11k_wmi_pdev_csa_switch_count_status_event(ab, skb);
break;
+ case WMI_PDEV_UTF_EVENTID:
+ ath11k_tm_wmi_event(ab, id, skb);
+ break;
case WMI_PDEV_TEMPERATURE_EVENTID:
ath11k_wmi_pdev_temperature_event(ab, skb);
break;
@@ -8630,19 +8743,6 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_TWT_ADD_DIALOG_EVENTID:
ath11k_wmi_twt_add_dialog_event(ab, skb);
break;
- /* add Unsupported events here */
- case WMI_TBTTOFFSET_EXT_UPDATE_EVENTID:
- case WMI_PEER_OPER_MODE_CHANGE_EVENTID:
- case WMI_TWT_ENABLE_EVENTID:
- case WMI_TWT_DISABLE_EVENTID:
- case WMI_TWT_DEL_DIALOG_EVENTID:
- case WMI_TWT_PAUSE_DIALOG_EVENTID:
- case WMI_TWT_RESUME_DIALOG_EVENTID:
- case WMI_PDEV_DMA_RING_CFG_RSP_EVENTID:
- case WMI_PEER_CREATE_CONF_EVENTID:
- ath11k_dbg(ab, ATH11K_DBG_WMI,
- "ignoring unsupported event 0x%x\n", id);
- break;
case WMI_PDEV_DFS_RADAR_DETECTION_EVENTID:
ath11k_wmi_pdev_dfs_radar_detected_event(ab, skb);
break;
@@ -8664,9 +8764,8 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
ath11k_wmi_gtk_offload_status_event(ab, skb);
break;
- /* TODO: Add remaining events */
default:
- ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
+ ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;
}
@@ -8763,7 +8862,7 @@ ath11k_wmi_send_unit_test_cmd(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI unit test : module %d vdev %d n_args %d token %d\n",
+ "cmd unit test module %d vdev %d n_args %d token %d\n",
cmd->module_id, cmd->vdev_id, cmd->num_args,
cmd->diag_token);
@@ -8855,6 +8954,9 @@ int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap,
"failed to send WMI_DBGLOG_CFG_CMDID\n");
dev_kfree_skb(skb);
}
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd dbglog cfg");
+
return ret;
}
@@ -8960,7 +9062,7 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id,
cmd->hw_filter_bitmap = ((u32)~0U);
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi hw data filter enable %d filter_bitmap 0x%x\n",
+ "hw data filter enable %d filter_bitmap 0x%x\n",
enable, filter_bitmap);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
@@ -8982,7 +9084,7 @@ int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar)
WMI_TAG_WOW_HOSTWAKEUP_FROM_SLEEP_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow host wakeup ind\n");
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
}
@@ -9004,7 +9106,7 @@ int ath11k_wmi_wow_enable(struct ath11k *ar)
cmd->enable = 1;
cmd->pause_iface_config = WOW_IFACE_PAUSE_ENABLED;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow enable\n");
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow enable\n");
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
}
@@ -9031,7 +9133,7 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
cmd->prob_req_oui = prob_req_oui;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi scan prob req oui %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "scan prob req oui %d\n",
prob_req_oui);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
@@ -9058,7 +9160,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id,
cmd->is_add = enable;
cmd->event_bitmap = (1 << event);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add wakeup event %s enable %d vdev_id %d\n",
wow_wakeup_event(event), enable, vdev_id);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
@@ -9163,7 +9265,7 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id,
WMI_TAG_ARRAY_UINT32) |
FIELD_PREP(WMI_TLV_LEN, sizeof(u32));
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n",
vdev_id, pattern_id, pattern_offset);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
@@ -9189,7 +9291,7 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id)
cmd->pattern_id = pattern_id;
cmd->pattern_type = WOW_BITMAP_PATTERN;
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv wow del pattern vdev_id %d pattern_id %d\n",
vdev_id, pattern_id);
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
@@ -9302,7 +9404,7 @@ ath11k_wmi_op_gen_config_pno_start(struct ath11k *ar,
for (i = 0; i < cmd->num_of_channels; i++)
channel_list[i] = pno->a_networks[0].channels[i];
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "tlv start pno config vdev_id %d\n",
vdev_id);
return skb;
@@ -9328,7 +9430,7 @@ static struct sk_buff *ath11k_wmi_op_gen_config_pno_stop(struct ath11k *ar,
cmd->flags = WMI_NLO_CONFIG_STOP;
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi tlv stop pno config vdev_id %d\n", vdev_id);
+ "tlv stop pno config vdev_id %d\n", vdev_id);
return skb;
}
@@ -9405,7 +9507,7 @@ static void ath11k_wmi_fill_ns_offload(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi index %d ns_solicited %pI6 target %pI6",
+ "index %d ns_solicited %pI6 target %pI6",
i, ns->solicitation_ipaddr,
ns->target_ipaddr[0]);
}
@@ -9443,7 +9545,7 @@ static void ath11k_wmi_fill_arp_offload(struct ath11k *ar,
memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4);
ath11k_ce_byte_swap(arp->target_ipaddr, 4);
- ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi arp offload address %pI4",
+ ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "arp offload address %pI4",
arp->target_ipaddr);
}
@@ -9676,7 +9778,7 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar,
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
+ "sta keepalive vdev %d enabled %d method %d interval %d\n",
arg->vdev_id, arg->enabled, arg->method, arg->interval);
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 92fddb77669c..100bb816b592 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH11K_WMI_H
@@ -68,6 +69,7 @@ struct wmi_tlv {
#define WMI_APPEND_TO_EXISTING_CHAN_LIST_FLAG 1
+#define MAX_WMI_UTF_LEN 252
#define WMI_BA_MODE_BUFFER_SIZE_256 3
/*
* HW mode config type replicated from FW header
@@ -137,6 +139,14 @@ enum {
WMI_AUTORATE_3200NS_GI = BIT(11),
};
+enum {
+ WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001,
+ WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002,
+ WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004,
+ WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008,
+ WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010,
+};
+
/*
* wmi command groups.
*/
@@ -2096,6 +2106,7 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_EXT2_MSG = 220,
WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
+ WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263,
/* The second 128 bits */
@@ -2317,6 +2328,7 @@ struct wmi_init_cmd {
} __packed;
#define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
+#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4
@@ -2389,6 +2401,9 @@ struct wmi_resource_config {
u32 msdu_flow_override_config1;
u32 flags2;
u32 host_service_flags;
+ u32 max_rnr_neighbours;
+ u32 ema_max_vap_cnt;
+ u32 ema_max_profile_period;
} __packed;
struct wmi_service_ready_event {
@@ -2579,6 +2594,8 @@ struct vdev_create_params {
u8 rx;
} chains[NUM_NL80211_BANDS];
u32 pdev_id;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
};
struct wmi_vdev_create_cmd {
@@ -2589,6 +2606,8 @@ struct wmi_vdev_create_cmd {
struct wmi_mac_addr vdev_macaddr;
u32 num_cfg_txrx_streams;
u32 pdev_id;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
} __packed;
struct wmi_vdev_txrx_streams {
@@ -2608,9 +2627,9 @@ struct wmi_vdev_up_cmd {
u32 vdev_id;
u32 vdev_assoc_id;
struct wmi_mac_addr vdev_bssid;
- struct wmi_mac_addr trans_bssid;
- u32 profile_idx;
- u32 profile_num;
+ struct wmi_mac_addr tx_vdev_bssid;
+ u32 nontx_profile_idx;
+ u32 nontx_profile_cnt;
} __packed;
struct wmi_vdev_stop_cmd {
@@ -2652,6 +2671,9 @@ struct wmi_vdev_start_request_cmd {
u32 he_ops;
u32 cac_duration_ms;
u32 regdomain;
+ u32 min_data_rate;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
} __packed;
#define MGMT_TX_DL_FRM_LEN 64
@@ -2821,6 +2843,9 @@ struct wmi_vdev_start_req_arg {
u32 pref_rx_streams;
u32 pref_tx_streams;
u32 num_noa_descriptors;
+ u32 min_data_rate;
+ u32 mbssid_flags;
+ u32 mbssid_tx_vdev_id;
};
struct peer_create_params {
@@ -3541,8 +3566,30 @@ struct wmi_get_pdev_temperature_cmd {
u32 pdev_id;
} __packed;
+struct wmi_ftm_seg_hdr {
+ u32 len;
+ u32 msgref;
+ u32 segmentinfo;
+ u32 pdev_id;
+} __packed;
+
+struct wmi_ftm_cmd {
+ u32 tlv_header;
+ struct wmi_ftm_seg_hdr seg_hdr;
+ u8 data[];
+} __packed;
+
+struct wmi_ftm_event_msg {
+ struct wmi_ftm_seg_hdr seg_hdr;
+ u8 data[];
+} __packed;
+
#define WMI_BEACON_TX_BUFFER_SIZE 512
+#define WMI_EMA_TMPL_IDX_SHIFT 8
+#define WMI_EMA_FIRST_TMPL_SHIFT 16
+#define WMI_EMA_LAST_TMPL_SHIFT 24
+
struct wmi_bcn_tmpl_cmd {
u32 tlv_header;
u32 vdev_id;
@@ -3553,6 +3600,11 @@ struct wmi_bcn_tmpl_cmd {
u32 csa_event_bitmap;
u32 mbssid_ie_offset;
u32 esp_ie_offset;
+ u32 csc_switch_count_offset;
+ u32 csc_event_bitmap;
+ u32 mu_edca_ie_offset;
+ u32 feature_enable_bitmap;
+ u32 ema_params;
} __packed;
struct wmi_key_seq_counter {
@@ -5646,6 +5698,8 @@ struct target_resource_config {
u32 twt_ap_pdev_count;
u32 twt_ap_sta_count;
u8 is_reg_cc_ext_event_supported;
+ u32 ema_max_vap_cnt;
+ u32 ema_max_profile_period;
};
enum wmi_debug_log_param {
@@ -6266,6 +6320,8 @@ enum wmi_sta_keepalive_method {
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
+const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr,
+ size_t len, gfp_t gfp);
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
@@ -6273,10 +6329,11 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
- struct sk_buff *bcn);
+ struct sk_buff *bcn, u32 ema_param);
int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id);
int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid,
- const u8 *bssid);
+ const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx,
+ u32 nontx_profile_cnt);
int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id);
int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
bool restart);
@@ -6372,9 +6429,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,
struct pdev_set_regdomain_params *param);
int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
struct ath11k_fw_stats *stats);
-size_t ath11k_wmi_fw_stats_num_peers(struct list_head *head);
-size_t ath11k_wmi_fw_stats_num_peers_extd(struct list_head *head);
-size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head);
void ath11k_wmi_fw_stats_fill(struct ath11k *ar,
struct ath11k_fw_stats *fw_stats, u32 stats_id,
char *buf);
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 1dec23b0699c..99d8ba45a75b 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/delay.h>
@@ -838,6 +838,7 @@ exit:
case ATH11K_STATE_RESTARTING:
case ATH11K_STATE_RESTARTED:
case ATH11K_STATE_WEDGED:
+ case ATH11K_STATE_FTM:
ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n",
ar->state);
ret = -EIO;
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index a89e66653f04..3df8059d5512 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -706,6 +706,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
idr_for_each(&ar->txmgmt_idr,
ath12k_mac_tx_mgmt_pending_free, ar);
idr_destroy(&ar->txmgmt_idr);
+ wake_up(&ar->txmgmt_empty_waitq);
}
wake_up(&ab->wmi_ab.tx_credits_wq);
@@ -885,6 +886,7 @@ void ath12k_core_deinit(struct ath12k_base *ab)
void ath12k_core_free(struct ath12k_base *ab)
{
+ timer_delete_sync(&ab->rx_replenish_retry);
destroy_workqueue(ab->workqueue_aux);
destroy_workqueue(ab->workqueue);
kfree(ab);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 9439052a652e..2f93296db792 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -533,6 +533,7 @@ struct ath12k {
/* protects txmgmt_idr data */
spinlock_t txmgmt_idr_lock;
atomic_t num_pending_mgmt_tx;
+ wait_queue_head_t txmgmt_empty_waitq;
/* cycle count is reported twice for each visited channel during scan.
* access protected by data_lock
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index ae1645d0f42a..f933896f2a68 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -1129,6 +1129,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
struct ath12k_dp *dp = &ab->dp;
struct sk_buff *skb;
int i;
+ u32 pool_id, tx_spt_page;
if (!dp->spt_info)
return;
@@ -1148,6 +1149,14 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
dev_kfree_skb_any(skb);
}
+ for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
+ if (!dp->spt_info->rxbaddr[i])
+ continue;
+
+ kfree(dp->spt_info->rxbaddr[i]);
+ dp->spt_info->rxbaddr[i] = NULL;
+ }
+
spin_unlock_bh(&dp->rx_desc_lock);
/* TX Descriptor cleanup */
@@ -1170,6 +1179,21 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
spin_unlock_bh(&dp->tx_desc_lock[i]);
}
+ for (pool_id = 0; pool_id < ATH12K_HW_MAX_QUEUES; pool_id++) {
+ spin_lock_bh(&dp->tx_desc_lock[pool_id]);
+
+ for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) {
+ tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
+ if (!dp->spt_info->txbaddr[tx_spt_page])
+ continue;
+
+ kfree(dp->spt_info->txbaddr[tx_spt_page]);
+ dp->spt_info->txbaddr[tx_spt_page] = NULL;
+ }
+
+ spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
+ }
+
/* unmap SPT pages */
for (i = 0; i < dp->num_spt_pages; i++) {
if (!dp->spt_info[i].vaddr)
@@ -1343,6 +1367,8 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
return -ENOMEM;
}
+ dp->spt_info->rxbaddr[i] = &rx_descs[0];
+
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
rx_descs[j].cookie = ath12k_dp_cc_cookie_gen(i, j);
rx_descs[j].magic = ATH12K_DP_RX_DESC_MAGIC;
@@ -1368,8 +1394,10 @@ static int ath12k_dp_cc_desc_init(struct ath12k_base *ab)
return -ENOMEM;
}
+ tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
+ dp->spt_info->txbaddr[tx_spt_page] = &tx_descs[0];
+
for (j = 0; j < ATH12K_MAX_SPT_ENTRIES; j++) {
- tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
ppt_idx = ATH12K_NUM_RX_SPT_PAGES + tx_spt_page;
tx_descs[j].desc_id = ath12k_dp_cc_cookie_gen(ppt_idx, j);
tx_descs[j].pool_id = pool_id;
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 7c5dafce5a68..9aeda0321cd7 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -289,6 +289,8 @@ struct ath12k_tx_desc_info {
struct ath12k_spt_info {
dma_addr_t paddr;
u64 *vaddr;
+ struct ath12k_rx_desc_info *rxbaddr[ATH12K_NUM_RX_SPT_PAGES];
+ struct ath12k_tx_desc_info *txbaddr[ATH12K_NUM_TX_SPT_PAGES];
};
struct ath12k_reo_queue_ref {
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index e78478a5b978..ffd9a2018610 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -193,11 +193,11 @@ static void ath12k_dp_rxdesc_set_msdu_len(struct ath12k_base *ab,
ab->hw_params->hal_ops->rx_desc_set_msdu_len(desc, len);
}
-static bool ath12k_dp_rx_h_is_mcbc(struct ath12k_base *ab,
- struct hal_rx_desc *desc)
+static bool ath12k_dp_rx_h_is_da_mcbc(struct ath12k_base *ab,
+ struct hal_rx_desc *desc)
{
return (ath12k_dp_rx_h_first_msdu(ab, desc) &&
- ab->hw_params->hal_ops->rx_desc_is_mcbc(desc));
+ ab->hw_params->hal_ops->rx_desc_is_da_mcbc(desc));
}
static bool ath12k_dp_rxdesc_mac_addr2_valid(struct ath12k_base *ab,
@@ -978,7 +978,19 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
return ret;
}
- return ret;
+ if (!ab->hw_params->reoq_lut_support) {
+ ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id,
+ peer_mac,
+ paddr, tid, 1,
+ ba_win_sz);
+ if (ret) {
+ ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n",
+ tid, ret);
+ return ret;
+ }
+ }
+
+ return 0;
}
rx_tid->tid = tid;
@@ -1362,11 +1374,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar,
* Firmware rate's control to be skipped for this?
*/
- if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) {
- ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
- return;
- }
-
if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) {
ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs);
return;
@@ -2201,7 +2208,7 @@ static void ath12k_dp_rx_h_mpdu(struct ath12k *ar,
/* PN for multicast packets will be checked in mac80211 */
rxcb = ATH12K_SKB_RXCB(msdu);
- fill_crypto_hdr = ath12k_dp_rx_h_is_mcbc(ar->ab, rx_desc);
+ fill_crypto_hdr = ath12k_dp_rx_h_is_da_mcbc(ar->ab, rx_desc);
rxcb->is_mcbc = fill_crypto_hdr;
if (rxcb->is_mcbc)
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index 0ec53afe9915..e7a150e7158e 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -447,10 +447,10 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
return desc->u.qcn9274.mpdu_start.addr2;
}
-static bool ath12k_hw_qcn9274_rx_desc_is_mcbc(struct hal_rx_desc *desc)
+static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
{
- return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) &
- RX_MPDU_START_INFO6_MCAST_BCAST;
+ return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
+ RX_MSDU_END_INFO5_DA_IS_MCBC;
}
static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
@@ -708,7 +708,7 @@ const struct hal_ops hal_qcn9274_ops = {
.rx_desc_get_msdu_end_offset = ath12k_hw_qcn9274_rx_desc_get_msdu_end_offset,
.rx_desc_mac_addr2_valid = ath12k_hw_qcn9274_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2,
- .rx_desc_is_mcbc = ath12k_hw_qcn9274_rx_desc_is_mcbc,
+ .rx_desc_is_da_mcbc = ath12k_hw_qcn9274_rx_desc_is_da_mcbc,
.rx_desc_get_dot11_hdr = ath12k_hw_qcn9274_rx_desc_get_dot11_hdr,
.rx_desc_get_crypto_header = ath12k_hw_qcn9274_rx_desc_get_crypto_hdr,
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_qcn9274_rx_desc_get_mpdu_frame_ctl,
@@ -887,10 +887,10 @@ static u8 *ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
return desc->u.wcn7850.mpdu_start.addr2;
}
-static bool ath12k_hw_wcn7850_rx_desc_is_mcbc(struct hal_rx_desc *desc)
+static bool ath12k_hw_wcn7850_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
{
- return __le32_to_cpu(desc->u.wcn7850.mpdu_start.info6) &
- RX_MPDU_START_INFO6_MCAST_BCAST;
+ return __le16_to_cpu(desc->u.wcn7850.msdu_end.info5) &
+ RX_MSDU_END_INFO5_DA_IS_MCBC;
}
static void ath12k_hw_wcn7850_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
@@ -1163,7 +1163,7 @@ const struct hal_ops hal_wcn7850_ops = {
.rx_desc_get_msdu_end_offset = ath12k_hw_wcn7850_rx_desc_get_msdu_end_offset,
.rx_desc_mac_addr2_valid = ath12k_hw_wcn7850_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath12k_hw_wcn7850_rx_desc_mpdu_start_addr2,
- .rx_desc_is_mcbc = ath12k_hw_wcn7850_rx_desc_is_mcbc,
+ .rx_desc_is_da_mcbc = ath12k_hw_wcn7850_rx_desc_is_da_mcbc,
.rx_desc_get_dot11_hdr = ath12k_hw_wcn7850_rx_desc_get_dot11_hdr,
.rx_desc_get_crypto_header = ath12k_hw_wcn7850_rx_desc_get_crypto_hdr,
.rx_desc_get_mpdu_frame_ctl = ath12k_hw_wcn7850_rx_desc_get_mpdu_frame_ctl,
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 0d4fa12ea622..66035a787c72 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1063,7 +1063,7 @@ struct hal_ops {
u32 (*rx_desc_get_msdu_end_offset)(void);
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
- bool (*rx_desc_is_mcbc)(struct hal_rx_desc *desc);
+ bool (*rx_desc_is_da_mcbc)(struct hal_rx_desc *desc);
void (*rx_desc_get_dot11_hdr)(struct hal_rx_desc *desc,
struct ieee80211_hdr *hdr);
u16 (*rx_desc_get_mpdu_frame_ctl)(struct hal_rx_desc *desc);
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index 1ffac7e3deaa..5991cc91cd00 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -906,6 +906,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.hal_ops = &hal_qcn9274_ops,
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
},
{
.name = "wcn7850 hw2.0",
@@ -960,6 +961,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.wmi_init = ath12k_wmi_init_wcn7850,
.hal_ops = &hal_wcn7850_ops,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
+ BIT(CNSS_PCIE_PERST_NO_PULL_V01),
},
{
.name = "qcn9274 hw2.0",
@@ -1013,6 +1017,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
.wmi_init = ath12k_wmi_init_qcn9274,
.hal_ops = &hal_qcn9274_ops,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
},
};
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index e3461004188b..e6c4223c283c 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -184,6 +184,8 @@ struct ath12k_hw_params {
struct ath12k_wmi_resource_config_arg *config);
const struct hal_ops *hal_ops;
+
+ u64 qmi_cnss_feature_bitmap;
};
struct ath12k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index ee792822b411..d165b24094ad 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -381,7 +381,7 @@ u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
}
static u32
-ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask)
{
int nss;
@@ -393,7 +393,7 @@ ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static u32
-ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask)
{
int nss;
@@ -771,6 +771,9 @@ static int ath12k_mac_vdev_setup_sync(struct ath12k *ar)
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
return -ESHUTDOWN;
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n",
+ ATH12K_VDEV_SETUP_TIMEOUT_HZ);
+
if (!wait_for_completion_timeout(&ar->vdev_setup_done,
ATH12K_VDEV_SETUP_TIMEOUT_HZ))
return -ETIMEDOUT;
@@ -1303,7 +1306,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
}
static bool
-ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
+ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask)
{
int nss;
@@ -1315,7 +1318,7 @@ ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
}
static bool
-ath12k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX])
+ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask)
{
int nss;
@@ -1634,9 +1637,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
- sizeof(arg->peer_he_cap_macinfo));
+ sizeof(he_cap->he_cap_elem.mac_cap_info));
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
- sizeof(arg->peer_he_cap_phyinfo));
+ sizeof(he_cap->he_cap_elem.phy_cap_info));
arg->peer_he_ops = vif->bss_conf.he_oper.params;
/* the top most byte is used to indicate BSS color info */
@@ -2752,9 +2755,12 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg.scan_id = ATH12K_SCAN_ID;
if (req->ie_len) {
+ arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
+ if (!arg.extraie.ptr) {
+ ret = -ENOMEM;
+ goto exit;
+ }
arg.extraie.len = req->ie_len;
- arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
- memcpy(arg.extraie.ptr, req->ie, req->ie_len);
}
if (req->n_ssids) {
@@ -4375,6 +4381,21 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
return 0;
}
+static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
+{
+ int num_mgmt;
+
+ ieee80211_free_txskb(ar->hw, skb);
+
+ num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
+ if (num_mgmt < 0)
+ WARN_ON_ONCE(1);
+
+ if (!num_mgmt)
+ wake_up(&ar->txmgmt_empty_waitq);
+}
+
int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
{
struct sk_buff *msdu = skb;
@@ -4391,7 +4412,7 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
info = IEEE80211_SKB_CB(msdu);
memset(&info->status, 0, sizeof(info->status));
- ieee80211_free_txskb(ar->hw, msdu);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
return 0;
}
@@ -4425,6 +4446,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_vif *arvif,
int buf_id;
int ret;
+ ATH12K_SKB_CB(skb)->ar = ar;
spin_lock_bh(&ar->txmgmt_idr_lock);
buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
ATH12K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
@@ -4475,7 +4497,7 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
struct sk_buff *skb;
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
@@ -4490,7 +4512,7 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
skb_cb = ATH12K_SKB_CB(skb);
if (!skb_cb->vif) {
ath12k_warn(ar->ab, "no vif found for mgmt frame\n");
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
continue;
}
@@ -4501,16 +4523,14 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
if (ret) {
ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
arvif->vdev_id, ret);
- ieee80211_free_txskb(ar->hw, skb);
- } else {
- atomic_inc(&ar->num_pending_mgmt_tx);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
} else {
ath12k_warn(ar->ab,
"dropping mgmt frame for vdev %d, is_started %d\n",
arvif->vdev_id,
arvif->is_started);
- ieee80211_free_txskb(ar->hw, skb);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
}
}
@@ -4535,12 +4555,13 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
return -ENOSPC;
}
- if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) {
+ if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
ath12k_warn(ar->ab, "mgmt tx queue is full\n");
return -ENOSPC;
}
skb_queue_tail(q, skb);
+ atomic_inc(&ar->num_pending_mgmt_tx);
ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
return 0;
@@ -5910,7 +5931,6 @@ ath12k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
}
arvif->is_started = false;
- mutex_unlock(&ar->conf_mutex);
}
ret = ath12k_mac_vdev_stop(arvif);
@@ -6014,6 +6034,13 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
ATH12K_FLUSH_TIMEOUT);
if (time_left == 0)
ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
+
+ time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
+ (atomic_read(&ar->num_pending_mgmt_tx) == 0),
+ ATH12K_FLUSH_TIMEOUT);
+ if (time_left == 0)
+ ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
+ time_left);
}
static int
@@ -6991,6 +7018,7 @@ int ath12k_mac_register(struct ath12k_base *ab)
if (ret)
goto err_cleanup;
+ init_waitqueue_head(&ar->txmgmt_empty_waitq);
idr_init(&ar->txmgmt_idr);
spin_lock_init(&ar->txmgmt_idr_lock);
}
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index 9f174daf324c..fae5dfd6e9d7 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -794,8 +794,8 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci)
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
/* disable L0s and L1 */
- pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
- ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+ pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC);
set_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags);
}
@@ -803,8 +803,10 @@ static void ath12k_pci_aspm_disable(struct ath12k_pci *ab_pci)
static void ath12k_pci_aspm_restore(struct ath12k_pci *ab_pci)
{
if (test_and_clear_bit(ATH12K_PCI_ASPM_RESTORE, &ab_pci->flags))
- pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
- ab_pci->link_ctl);
+ pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL,
+ PCI_EXP_LNKCTL_ASPMC,
+ ab_pci->link_ctl &
+ PCI_EXP_LNKCTL_ASPMC);
}
static void ath12k_pci_kill_tasklets(struct ath12k_base *ab)
@@ -1227,8 +1229,20 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
case WCN7850_DEVICE_ID:
ab_pci->msi_config = &ath12k_msi_config[0];
ab->static_window_map = false;
- ab->hw_rev = ATH12K_HW_WCN7850_HW20;
ab_pci->pci_ops = &ath12k_pci_ops_wcn7850;
+ ath12k_pci_read_hw_version(ab, &soc_hw_version_major,
+ &soc_hw_version_minor);
+ switch (soc_hw_version_major) {
+ case ATH12K_PCI_SOC_HW_VERSION_2:
+ ab->hw_rev = ATH12K_HW_WCN7850_HW20;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Unknown hardware version found for WCN7850: 0x%x\n",
+ soc_hw_version_major);
+ ret = -EOPNOTSUPP;
+ goto err_pci_free_region;
+ }
break;
default:
@@ -1397,5 +1411,5 @@ static void ath12k_pci_exit(void)
module_exit(ath12k_pci_exit);
-MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN PCIe devices");
+MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11be WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 03ba245fbee9..b510c2de1bd4 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -1942,8 +1942,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
req.cal_done_valid = 1;
req.cal_done = ab->qmi.cal_done;
- req.feature_list_valid = 1;
- req.feature_list = BIT(CNSS_QDSS_CFG_MISS_V01);
+ if (ab->hw_params->qmi_cnss_feature_bitmap) {
+ req.feature_list_valid = 1;
+ req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap;
+ }
/* BRINGUP: here we are piggybacking a lot of stuff using
* internal_sleep_clock, should it be split?
@@ -3056,8 +3058,7 @@ int ath12k_qmi_init_service(struct ath12k_base *ab)
return ret;
}
- ab->qmi.event_wq = alloc_workqueue("ath12k_qmi_driver_event",
- WQ_UNBOUND, 1);
+ ab->qmi.event_wq = alloc_ordered_workqueue("ath12k_qmi_driver_event", 0);
if (!ab->qmi.event_wq) {
ath12k_err(ab, "failed to allocate workqueue\n");
return -EFAULT;
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index ad87f19903db..df76149c49f5 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -189,6 +189,7 @@ struct wlfw_host_mlo_chip_info_s_v01 {
enum ath12k_qmi_cnss_feature {
CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN,
CNSS_QDSS_CFG_MISS_V01 = 3,
+ CNSS_PCIE_PERST_NO_PULL_V01 = 4,
CNSS_MAX_FEATURE_V01 = 64,
CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX,
};
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 7ae0bb78b2b5..eebc5a65ce3b 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -2144,8 +2144,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
struct wmi_tlv *tlv;
void *ptr;
int i, ret, len;
- u32 *tmp_ptr;
- u8 extraie_len_with_pad = 0;
+ u32 *tmp_ptr, extraie_len_with_pad = 0;
struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL;
struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL;
@@ -2163,12 +2162,6 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
if (arg->num_bssid)
len += sizeof(*bssid) * arg->num_bssid;
- len += TLV_HDR_SIZE;
- if (arg->extraie.len)
- extraie_len_with_pad =
- roundup(arg->extraie.len, sizeof(u32));
- len += extraie_len_with_pad;
-
if (arg->num_hint_bssid)
len += TLV_HDR_SIZE +
arg->num_hint_bssid * sizeof(*hint_bssid);
@@ -2177,6 +2170,18 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
len += TLV_HDR_SIZE +
arg->num_hint_s_ssid * sizeof(*s_ssid);
+ len += TLV_HDR_SIZE;
+ if (arg->extraie.len)
+ extraie_len_with_pad =
+ roundup(arg->extraie.len, sizeof(u32));
+ if (extraie_len_with_pad <= (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len)) {
+ len += extraie_len_with_pad;
+ } else {
+ ath12k_warn(ar->ab, "discard large size %d bytes extraie for scan start\n",
+ arg->extraie.len);
+ extraie_len_with_pad = 0;
+ }
+
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -2266,7 +2271,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len);
ptr += TLV_HDR_SIZE;
- if (arg->extraie.len)
+ if (extraie_len_with_pad)
memcpy(ptr, arg->extraie.ptr,
arg->extraie.len);
@@ -3181,8 +3186,8 @@ ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cf
wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);
wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);
wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);
- wmi_cfg->host_service_flags =
- cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
+ wmi_cfg->host_service_flags = cpu_to_le32(tg_cfg->is_reg_cc_ext_event_supported <<
+ WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);
}
static int ath12k_init_cmd_send(struct ath12k_wmi_pdev *wmi,
@@ -3390,6 +3395,10 @@ int ath12k_wmi_cmd_init(struct ath12k_base *ab)
struct ath12k_wmi_base *wmi_sc = &ab->wmi_ab;
struct ath12k_wmi_init_cmd_arg arg = {};
+ if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,
+ ab->wmi_ab.svc_map))
+ arg.res_cfg.is_reg_cc_ext_event_supported = true;
+
ab->hw_params->wmi_init(ab, &arg.res_cfg);
arg.num_mem_chunks = wmi_sc->num_mem_chunks;
@@ -3701,6 +3710,10 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) {
hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
mode = le32_to_cpu(hw_mode_caps->hw_mode_id);
+
+ if (mode >= WMI_HOST_HW_MODE_MAX)
+ continue;
+
pref = soc->wmi_ab.preferred_hw_mode;
if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
@@ -4640,6 +4653,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
struct sk_buff *msdu;
struct ieee80211_tx_info *info;
struct ath12k_skb_cb *skb_cb;
+ int num_mgmt;
spin_lock_bh(&ar->txmgmt_idr_lock);
msdu = idr_find(&ar->txmgmt_idr, desc_id);
@@ -4663,10 +4677,15 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id,
ieee80211_tx_status_irqsafe(ar->hw, msdu);
+ num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
+
/* WARN when we received this event without doing any mgmt tx */
- if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
+ if (num_mgmt < 0)
WARN_ON_ONCE(1);
+ if (!num_mgmt)
+ wake_up(&ar->txmgmt_empty_waitq);
+
return 0;
}
@@ -5979,47 +5998,72 @@ static void ath12k_vdev_install_key_compl_event(struct ath12k_base *ab,
rcu_read_unlock();
}
-static void ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb)
+static int ath12k_wmi_tlv_services_parser(struct ath12k_base *ab,
+ u16 tag, u16 len,
+ const void *ptr,
+ void *data)
{
- const void **tb;
const struct wmi_service_available_event *ev;
- int ret;
+ u32 *wmi_ext2_service_bitmap;
int i, j;
+ u16 expected_len;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
- if (IS_ERR(tb)) {
- ret = PTR_ERR(tb);
- ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
- return;
+ expected_len = WMI_SERVICE_SEGMENT_BM_SIZE32 * sizeof(u32);
+ if (len < expected_len) {
+ ath12k_warn(ab, "invalid length %d for the WMI services available tag 0x%x\n",
+ len, tag);
+ return -EINVAL;
}
- ev = tb[WMI_TAG_SERVICE_AVAILABLE_EVENT];
- if (!ev) {
- ath12k_warn(ab, "failed to fetch svc available ev");
- kfree(tb);
- return;
- }
+ switch (tag) {
+ case WMI_TAG_SERVICE_AVAILABLE_EVENT:
+ ev = (struct wmi_service_available_event *)ptr;
+ for (i = 0, j = WMI_MAX_SERVICE;
+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE;
+ i++) {
+ do {
+ if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) &
+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
+ set_bit(j, ab->wmi_ab.svc_map);
+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ }
- /* TODO: Use wmi_service_segment_offset information to get the service
- * especially when more services are advertised in multiple service
- * available events.
- */
- for (i = 0, j = WMI_MAX_SERVICE;
- i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT_SERVICE;
- i++) {
- do {
- if (le32_to_cpu(ev->wmi_service_segment_bitmap[i]) &
- BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
- set_bit(j, ab->wmi_ab.svc_map);
- } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "wmi_ext_service_bitmap 0x%x 0x%x 0x%x 0x%x",
+ ev->wmi_service_segment_bitmap[0],
+ ev->wmi_service_segment_bitmap[1],
+ ev->wmi_service_segment_bitmap[2],
+ ev->wmi_service_segment_bitmap[3]);
+ break;
+ case WMI_TAG_ARRAY_UINT32:
+ wmi_ext2_service_bitmap = (u32 *)ptr;
+ for (i = 0, j = WMI_MAX_EXT_SERVICE;
+ i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE;
+ i++) {
+ do {
+ if (wmi_ext2_service_bitmap[i] &
+ BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))
+ set_bit(j, ab->wmi_ab.svc_map);
+ } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "wmi_ext2_service_bitmap 0x%04x 0x%04x 0x%04x 0x%04x",
+ wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1],
+ wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]);
+ break;
}
+ return 0;
+}
- ath12k_dbg(ab, ATH12K_DBG_WMI,
- "wmi_ext_service_bitmap 0:0x%x, 1:0x%x, 2:0x%x, 3:0x%x",
- ev->wmi_service_segment_bitmap[0], ev->wmi_service_segment_bitmap[1],
- ev->wmi_service_segment_bitmap[2], ev->wmi_service_segment_bitmap[3]);
+static int ath12k_service_available_event(struct ath12k_base *ab, struct sk_buff *skb)
+{
+ int ret;
- kfree(tb);
+ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath12k_wmi_tlv_services_parser,
+ NULL);
+ return ret;
}
static void ath12k_peer_assoc_conf_event(struct ath12k_base *ab, struct sk_buff *skb)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 08a8c9e0f59f..d89c12bfb009 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2148,7 +2148,10 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
WMI_TLV_SERVICE_EXT2_MSG = 220,
- WMI_MAX_EXT_SERVICE
+ WMI_MAX_EXT_SERVICE = 256,
+
+ WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
+ WMI_MAX_EXT2_SERVICE,
};
enum {
@@ -2333,6 +2336,7 @@ struct ath12k_wmi_resource_config_arg {
u32 sched_params;
u32 twt_ap_pdev_count;
u32 twt_ap_sta_count;
+ bool is_reg_cc_ext_event_supported;
};
struct ath12k_wmi_init_cmd_arg {
@@ -2682,7 +2686,7 @@ struct ath12k_wmi_ssid_params {
u8 ssid[ATH12K_WMI_SSID_LEN];
} __packed;
-#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (1 * HZ)
+#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
struct wmi_vdev_start_request_cmd {
__le32 tlv_header;
@@ -4664,7 +4668,7 @@ struct ath12k_wmi_base {
struct completion service_ready;
struct completion unified_ready;
- DECLARE_BITMAP(svc_map, WMI_MAX_EXT_SERVICE);
+ DECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE);
wait_queue_head_t tx_credits_wq;
const struct wmi_peer_flags_map *peer_flags;
u32 num_mem_chunks;
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index a75bfa9fd1cf..dc2b3b46781e 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -36,11 +36,6 @@ ath6kl_core-y += wmi.o
ath6kl_core-y += core.o
ath6kl_core-y += recovery.o
-# FIXME: temporarily silence -Wdangling-pointer on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_htc_mbox.o += $(call cc-disable-warning, dangling-pointer)
-endif
-
ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 9cd12b20b18d..9bfaadfa6c00 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
- wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
- hw_name, (unsigned long)mem, irq);
+ wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
+ hw_name, mem, irq);
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 4f27a9fb1482..e9bd13eeee92 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue)
{
u32 dma_dbg_chain, dma_dbg_complete;
u8 dcu_chain_state, dcu_complete_state;
+ unsigned int dbg_reg, reg_offset;
int i;
- for (i = 0; i < NUM_STATUS_READS; i++) {
- if (queue < 6)
- dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
- else
- dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
+ if (queue < 6) {
+ dbg_reg = AR_DMADBG_4;
+ reg_offset = queue * 5;
+ } else {
+ dbg_reg = AR_DMADBG_5;
+ reg_offset = (queue - 6) * 5;
+ }
+ for (i = 0; i < NUM_STATUS_READS; i++) {
+ dma_dbg_chain = REG_READ(ah, dbg_reg);
dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
- dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
+ dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f;
dcu_complete_state = dma_dbg_complete & 0x3;
if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
@@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
u8 dcu_chain_state, dcu_complete_state;
bool dcu_wait_frdone = false;
unsigned long chk_dcu = 0;
+ unsigned int reg_offset;
unsigned int i = 0;
dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
@@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
goto exit;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (i < 6)
+ if (i < 6) {
chk_dbg = dma_dbg_4;
- else
+ reg_offset = i * 5;
+ } else {
chk_dbg = dma_dbg_5;
+ reg_offset = (i - 6) * 5;
+ }
- dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
+ dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f;
if (dcu_chain_state == 0x6) {
dcu_wait_frdone = true;
chk_dcu |= BIT(i);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index b3ed65e5c4da..c55aab01fff5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -491,7 +491,7 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
priv->hw->wiphy->debugfsdir);
- if (!priv->debug.debugfs_phy)
+ if (IS_ERR(priv->debug.debugfs_phy))
return -ENOMEM;
ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index fe62ff668f75..99667aba289d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target,
if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
epid = svc_rspmsg->endpoint_id;
- if (epid < 0 || epid >= ENDPOINT_MAX)
+
+ /* Check that the received epid for the endpoint to attach
+ * a new service is valid. ENDPOINT0 can't be used here as it
+ * is already reserved for HTC_CTRL_RSVD_SVC service and thus
+ * should not be modified.
+ */
+ if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX)
return;
service_id = be16_to_cpu(svc_rspmsg->service_id);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index af44b33814dd..f03d792732da 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -115,8 +115,10 @@ struct ath_tx_status {
u8 qid;
u16 desc_id;
u8 tid;
- u32 ba_low;
- u32 ba_high;
+ struct_group(ba,
+ u32 ba_low;
+ u32 ba_high;
+ );
u32 evm0;
u32 evm1;
u32 evm2;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a4197c14f0a9..6360d3356e25 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -203,7 +203,7 @@ void ath_cancel_work(struct ath_softc *sc)
void ath_restart_work(struct ath_softc *sc)
{
ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
- ATH_HW_CHECK_POLL_INT);
+ msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
{
struct ath_hw *ah = sc->sc_ah;
- int i;
+ int i, j;
struct ath_txq *txq;
bool key_in_use = false;
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
int idx = txq->txq_tailidx;
- while (!key_in_use &&
- !list_empty(&txq->txq_fifo[idx])) {
+ for (j = 0; !key_in_use &&
+ !list_empty(&txq->txq_fifo[idx]) &&
+ j < ATH_TXFIFO_DEPTH; j++) {
key_in_use = ath9k_txq_list_has_key(
&txq->txq_fifo[idx], keyix);
INCR(idx, ATH_TXFIFO_DEPTH);
@@ -2239,7 +2240,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
}
ieee80211_queue_delayed_work(hw, &sc->hw_check_work,
- ATH_HW_CHECK_POLL_INT);
+ msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
}
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index a09f9d223f3d..0633589b85c2 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->sc_ah->msi_reg = 0;
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
- wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
- hw_name, (unsigned long)sc->mem, pdev->irq);
+ wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
+ hw_name, sc->mem, pdev->irq);
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 19345b8f7bfd..1476b42b52a9 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
if (unlikely(wmi->stopped))
goto free_skb;
+ /* Validate the obtained SKB. */
+ if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
+ goto free_skb;
+
hdr = (struct wmi_cmd_hdr *) skb->data;
cmd_id = be16_to_cpu(hdr->command_id);
@@ -238,10 +242,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
goto free_skb;
}
- spin_unlock_irqrestore(&wmi->wmi_lock, flags);
/* WMI command response */
ath9k_wmi_rsp_callback(wmi, skb);
+ spin_unlock_irqrestore(&wmi->wmi_lock, flags);
free_skb:
kfree_skb(skb);
@@ -279,7 +283,8 @@ int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi,
static int ath9k_wmi_cmd_issue(struct wmi *wmi,
struct sk_buff *skb,
- enum wmi_cmd_id cmd, u16 len)
+ enum wmi_cmd_id cmd, u16 len,
+ u8 *rsp_buf, u32 rsp_len)
{
struct wmi_cmd_hdr *hdr;
unsigned long flags;
@@ -289,6 +294,11 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
spin_lock_irqsave(&wmi->wmi_lock, flags);
+
+ /* record the rsp buffer and length */
+ wmi->cmd_rsp_buf = rsp_buf;
+ wmi->cmd_rsp_len = rsp_len;
+
wmi->last_seq_id = wmi->tx_seq_id;
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
@@ -304,8 +314,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
struct ath_common *common = ath9k_hw_common(ah);
u16 headroom = sizeof(struct htc_frame_hdr) +
sizeof(struct wmi_cmd_hdr);
+ unsigned long time_left, flags;
struct sk_buff *skb;
- unsigned long time_left;
int ret = 0;
if (ah->ah_flags & AH_UNPLUGGED)
@@ -329,11 +339,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
goto out;
}
- /* record the rsp buffer and length */
- wmi->cmd_rsp_buf = rsp_buf;
- wmi->cmd_rsp_len = rsp_len;
-
- ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
+ ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len, rsp_buf, rsp_len);
if (ret)
goto out;
@@ -341,7 +347,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (!time_left) {
ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n",
wmi_cmd_to_name(cmd_id));
+ spin_lock_irqsave(&wmi->wmi_lock, flags);
wmi->last_seq_id = 0;
+ spin_unlock_irqrestore(&wmi->wmi_lock, flags);
mutex_unlock(&wmi->op_mutex);
return -ETIMEDOUT;
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f6f2ab7a63ff..42058368e637 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -468,7 +468,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
isaggr = bf_isaggr(bf);
if (isaggr) {
seq_st = ts->ts_seqnum;
- memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+ memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
}
while (bf) {
@@ -551,7 +551,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (isaggr && txok) {
if (ts->ts_flags & ATH9K_TX_BA) {
seq_st = ts->ts_seqnum;
- memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+ memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
} else {
/*
* AR5416 can become deaf/mute when BA
diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h
index 440614d61156..aa1620e0d24f 100644
--- a/drivers/net/wireless/ath/wil6210/fw.h
+++ b/drivers/net/wireless/ath/wil6210/fw.h
@@ -47,7 +47,7 @@ struct wil_fw_record_fill { /* type == wil_fw_type_fill */
* for informational purpose, data_size is @head.size from record header
*/
struct wil_fw_record_comment { /* type == wil_fw_type_comment */
- u8 data[0]; /* free-form data [data_size], see above */
+ DECLARE_FLEX_ARRAY(u8, data); /* free-form data [data_size], see above */
} __packed;
/* Comment header - common for all comment record types */
@@ -131,7 +131,7 @@ struct wil_fw_data_dwrite {
* data_size is @head.size where @head is record header
*/
struct wil_fw_record_direct_write { /* type == wil_fw_type_direct_write */
- struct wil_fw_data_dwrite data[0];
+ DECLARE_FLEX_ARRAY(struct wil_fw_data_dwrite, data);
} __packed;
/* verify condition: [@addr] & @mask == @value
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 237cbd5c5060..f29ac6de7139 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
&s->tid_crypto_rx[tid];
struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
- const u8 *pn = (u8 *)&d->mac.pn_15_0;
+ const u8 *pn = (u8 *)&d->mac.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 1ae1bec1b97f..689f68d89a44 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -343,8 +343,10 @@ struct vring_rx_mac {
u32 d0;
u32 d1;
u16 w4;
- u16 pn_15_0;
- u32 pn_47_16;
+ struct_group_attr(pn, __packed,
+ u16 pn_15_0;
+ u32 pn_47_16;
+ );
} __packed;
/* Rx descriptor - DMA part
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
index 201c8c35e0c9..1ba1f21ebea2 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil,
s = &wil->sta[cid];
c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid];
cc = &c->key_id[key_id];
- pn = (u8 *)&st->ext.pn_15_0;
+ pn = (u8 *)&st->ext.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
index c736f7413a35..ee90e225bb05 100644
--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
+++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
@@ -330,8 +330,10 @@ struct wil_rx_status_extension {
u32 d0;
u32 d1;
__le16 seq_num; /* only lower 12 bits */
- u16 pn_15_0;
- u32 pn_47_16;
+ struct_group_attr(pn, __packed,
+ u16 pn_15_0;
+ u32 pn_47_16;
+ );
} __packed;
struct wil_rx_status_extended {
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 9affa4525609..71bf2ae27a98 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -2763,7 +2763,7 @@ struct wmi_rf_xpm_write_result_event {
/* WMI_TX_MGMT_PACKET_EVENTID */
struct wmi_tx_mgmt_packet_event {
- u8 payload[0];
+ DECLARE_FLEX_ARRAY(u8, payload);
} __packed;
/* WMI_RX_MGMT_PACKET_EVENTID */
diff --git a/drivers/net/wireless/atmel/Kconfig b/drivers/net/wireless/atmel/Kconfig
index ca45a1021cf4..bafdd57b049a 100644
--- a/drivers/net/wireless/atmel/Kconfig
+++ b/drivers/net/wireless/atmel/Kconfig
@@ -14,7 +14,7 @@ if WLAN_VENDOR_ATMEL
config ATMEL
tristate "Atmel at76c50x chipset 802.11b support"
- depends on CFG80211 && (PCI || PCMCIA)
+ depends on CFG80211 && (PCI || PCMCIA) && HAS_IOPORT
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
index 009bca34ece3..447b51cff8f9 100644
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -10,7 +10,7 @@
* Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
* Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
*
- * This file is part of the Berlios driver for WLAN USB devices based on the
+ * This file is part of the Berlios driver for USB WLAN devices based on the
* Atmel AT76C503A/505/505A.
*
* Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
@@ -143,7 +143,7 @@ static const struct usb_device_id dev_table[] = {
{ USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Dynalink/Askey WLL013 (intersil) */
{ USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) },
- /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
+ /* EZ connect 11Mpbs USB Wireless Adapter SMC2662W v1 */
{ USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* BenQ AWL300 */
{ USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) },
@@ -195,7 +195,7 @@ static const struct usb_device_id dev_table[] = {
{ USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) },
/* 3Com 3CRSHEW696 */
{ USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) },
- /* Siemens Santis ADSL WLAN USB adapter WLL 013 */
+ /* Siemens Santis ADSL USB WLAN adapter WLL 013 */
{ USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) },
/* Belkin F5D6050, version 2 */
{ USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) },
@@ -238,7 +238,7 @@ static const struct usb_device_id dev_table[] = {
{ USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) },
/* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
{ USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) },
- /* Corega WLAN USB Stick 11 */
+ /* Corega USB WLAN Stick 11 */
{ USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
/* Microstar MSI Box MS6978 */
{ USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) },
diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c
index 453bb84cb338..58bba9875d36 100644
--- a/drivers/net/wireless/atmel/atmel_cs.c
+++ b/drivers/net/wireless/atmel/atmel_cs.c
@@ -72,6 +72,7 @@ struct local_info {
static int atmel_probe(struct pcmcia_device *p_dev)
{
struct local_info *local;
+ int ret;
dev_dbg(&p_dev->dev, "atmel_attach()\n");
@@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev)
p_dev->priv = local;
- return atmel_config(p_dev);
-} /* atmel_attach */
+ ret = atmel_config(p_dev);
+ if (ret)
+ goto err_free_priv;
+
+ return 0;
+
+err_free_priv:
+ kfree(p_dev->priv);
+ return ret;
+}
static void atmel_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index de8a2e27f49c..2a90bb24ba77 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -1456,6 +1456,10 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
params_v1 = kzalloc(params_size, GFP_KERNEL);
+ if (!params_v1) {
+ err = -ENOMEM;
+ goto exit_params;
+ }
params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
kfree(params);
@@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
bphy_err(drvr, "error (%d)\n", err);
}
+exit_params:
kfree(params);
exit:
return err;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 9f9bf08a70bb..2ef92ef25517 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -972,6 +972,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
u32 regdata;
u32 socitype;
int ret;
+ const u32 READ_FAILED = 0xFFFFFFFF;
/* Get CC core rev
* Chipid is assume to be at offset 0 from SI_ENUM_BASE
@@ -980,6 +981,11 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
*/
regdata = ci->ops->read32(ci->ctx,
CORE_CC_REG(ci->pub.enum_base, chipid));
+ if (regdata == READ_FAILED) {
+ brcmf_err("MMIO read failed: 0x%08x\n", regdata);
+ return -ENODEV;
+ }
+
ci->pub.chip = regdata & CID_ID_MASK;
ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 792adaf880b4..bece26741d3a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -398,7 +398,12 @@ struct brcmf_scan_params_le {
* fixed parameter portion is assumed, otherwise
* ssid in the fixed portion is ignored
*/
- __le16 channel_list[1]; /* list of chanspecs */
+ union {
+ __le16 padding; /* Reserve space for at least 1 entry for abort
+ * which uses an on stack brcmf_scan_params_le
+ */
+ DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */
+ };
};
struct brcmf_scan_params_v2_le {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
index 5a139d7ed47a..5d66e94c806d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
@@ -28,6 +28,11 @@ static inline void trace_ ## name(proto) {}
#define MAX_MSG_LEN 100
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+#endif
+
TRACE_EVENT(brcmf_err,
TP_PROTO(const char *func, struct va_format *vaf),
TP_ARGS(func, vaf),
@@ -123,6 +128,8 @@ TRACE_EVENT(brcmf_sdpcm_hdr,
__entry->len, ((u8 *)__get_dynamic_array(hdr))[4])
);
+#pragma GCC diagnostic pop
+
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
index 02de99818efa..5573a47766ad 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
@@ -12,13 +12,13 @@
static int brcmf_wcc_attach(struct brcmf_pub *drvr)
{
- pr_err("%s: executing\n", __func__);
+ pr_debug("%s: executing\n", __func__);
return 0;
}
static void brcmf_wcc_detach(struct brcmf_pub *drvr)
{
- pr_err("%s: executing\n", __func__);
+ pr_debug("%s: executing\n", __func__);
}
const struct brcmf_fwvid_ops brcmf_wcc_ops = {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
index 488456420353..42b0a91656c4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
@@ -24,6 +24,11 @@
#define MAX_MSG_LEN 100
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+#endif
+
DECLARE_EVENT_CLASS(brcms_msg_event,
TP_PROTO(struct va_format *vaf),
TP_ARGS(vaf),
@@ -71,6 +76,9 @@ TRACE_EVENT(brcms_dbg,
),
TP_printk("%s: %s", __get_str(func), __get_str(msg))
);
+
+#pragma GCC diagnostic pop
+
#endif /* __TRACE_BRCMSMAC_MSG_H */
#ifdef CONFIG_BRCM_TRACING
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
index e87e68cc46e2..fe94db0ba3f3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
@@ -186,7 +186,7 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
{
int prec;
- if (pq->len == 0)
+ if (pktq_empty(pq))
return NULL;
for (prec = 0; prec < pq->hi_prec; prec++)
@@ -223,7 +223,7 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
struct sk_buff *p;
int prec;
- if (pq->len == 0)
+ if (pktq_empty(pq))
return NULL;
while ((prec = pq->hi_prec) > 0 &&
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 7c4cc5f5e1eb..dbd13f7aa3e6 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -6157,8 +6157,11 @@ static int airo_get_rate(struct net_device *dev,
struct iw_param *vwrq = &wrqu->bitrate;
struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
+ int ret;
- readStatusRid(local, &status_rid, 1);
+ ret = readStatusRid(local, &status_rid, 1);
+ if (ret)
+ return -EBUSY;
vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
/* If more than one rate, set auto */
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig
index b20409f8c13a..20971304fdef 100644
--- a/drivers/net/wireless/intel/iwlwifi/Kconfig
+++ b/drivers/net/wireless/intel/iwlwifi/Kconfig
@@ -66,6 +66,7 @@ config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
select WANT_DEV_COREDUMP
depends on MAC80211
+ depends on PTP_1588_CLOCK_OPTIONAL
help
This is the driver that supports the MVM firmware. The list
of the devices that use this firmware is available here:
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile
index 75a703eb1bdf..b983982aee45 100644
--- a/drivers/net/wireless/intel/iwlwifi/Makefile
+++ b/drivers/net/wireless/intel/iwlwifi/Makefile
@@ -11,6 +11,7 @@ iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-gen3.o
iwlwifi-objs += pcie/trans-gen2.o pcie/tx-gen2.o
iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
+iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o cfg/bz.o cfg/sc.o
iwlwifi-objs += iwl-dbg-tlv.o
iwlwifi-objs += iwl-trans.o
iwlwifi-objs += queue/tx.o
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
index 116defb15afb..f172ffd2a841 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/1000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -22,11 +22,11 @@
#define EEPROM_1000_TX_POWER_VERSION (4)
#define EEPROM_1000_EEPROM_VERSION (0x15C)
-#define IWL1000_FW_PRE "iwlwifi-1000-"
-#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode"
+#define IWL1000_FW_PRE "iwlwifi-1000"
+#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL100_FW_PRE "iwlwifi-100-"
-#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode"
+#define IWL100_FW_PRE "iwlwifi-100"
+#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl1000_base_params = {
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
index ab2038a3fbe2..6f3f26da0ad5 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/2000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -28,17 +28,17 @@
#define EEPROM_2000_EEPROM_VERSION (0x805)
-#define IWL2030_FW_PRE "iwlwifi-2030-"
-#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
+#define IWL2030_FW_PRE "iwlwifi-2030"
+#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL2000_FW_PRE "iwlwifi-2000-"
-#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"
+#define IWL2000_FW_PRE "iwlwifi-2000"
+#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL105_FW_PRE "iwlwifi-105-"
-#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
+#define IWL105_FW_PRE "iwlwifi-105"
+#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL135_FW_PRE "iwlwifi-135-"
-#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode"
+#define IWL135_FW_PRE "iwlwifi-135"
+#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl2000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index b6f82510e980..d594694206b3 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -10,10 +10,10 @@
#include "fw/api/txq.h"
/* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX 78
+#define IWL_22000_UCODE_API_MAX 77
/* Lowest firmware API version supported */
-#define IWL_22000_UCODE_API_MIN 39
+#define IWL_22000_UCODE_API_MIN 50
/* NVM versions */
#define IWL_22000_NVM_VERSION 0x0a1d
@@ -26,162 +26,26 @@
#define IWL_22000_SMEM_OFFSET 0x400000
#define IWL_22000_SMEM_LEN 0xD0000
-#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-"
-#define IWL_QNJ_B_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-"
-#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0-"
-#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
-#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0-"
-#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-"
-#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0-"
-#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
-#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
-#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-"
-#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-"
-#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-"
-#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-"
-#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-"
-#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0-"
-#define IWL_SNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-"
-#define IWL_SNJ_A_GF_A_FW_PRE "iwlwifi-SoSnj-a0-gf-a0-"
-#define IWL_SNJ_A_HR_B_FW_PRE "iwlwifi-SoSnj-a0-hr-b0-"
-#define IWL_SNJ_A_JF_B_FW_PRE "iwlwifi-SoSnj-a0-jf-b0-"
-#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0-"
-#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0-"
-#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0-"
-#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0-"
-#define IWL_MA_A_FM_A_FW_PRE "iwlwifi-ma-a0-fm-a0-"
-#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0-"
-#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0-"
-#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0-"
-#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0-"
-#define IWL_MA_B_FM_A_FW_PRE "iwlwifi-ma-b0-fm-a0-"
-#define IWL_SNJ_A_MR_A_FW_PRE "iwlwifi-SoSnj-a0-mr-a0-"
-#define IWL_BZ_A_HR_A_FW_PRE "iwlwifi-bz-a0-hr-b0-"
-#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0-"
-#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0-"
-#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
-#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
-#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
-#define IWL_BZ_A_FM4_A_FW_PRE "iwlwifi-bz-a0-fm4-a0-"
-#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0-"
-#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0-"
-#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-"
-#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0-"
-#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
-#define IWL_BNJ_A_FM_A_FW_PRE "iwlwifi-BzBnj-a0-fm-a0-"
-#define IWL_BNJ_A_FM4_A_FW_PRE "iwlwifi-BzBnj-a0-fm4-a0-"
-#define IWL_BNJ_B_FM4_B_FW_PRE "iwlwifi-BzBnj-b0-fm4-b0-"
-#define IWL_BNJ_A_GF_A_FW_PRE "iwlwifi-BzBnj-a0-gf-a0-"
-#define IWL_BNJ_B_GF_A_FW_PRE "iwlwifi-BzBnj-b0-gf-a0-"
-#define IWL_BNJ_A_GF4_A_FW_PRE "iwlwifi-BzBnj-a0-gf4-a0-"
-#define IWL_BNJ_B_GF4_A_FW_PRE "iwlwifi-BzBnj-b0-gf4-a0-"
-#define IWL_BNJ_A_HR_A_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
-#define IWL_BNJ_A_HR_B_FW_PRE "iwlwifi-BzBnj-a0-hr-b0-"
-#define IWL_BNJ_B_HR_A_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
-#define IWL_BNJ_B_HR_B_FW_PRE "iwlwifi-BzBnj-b0-hr-b0-"
-#define IWL_BNJ_B_FM_B_FW_PRE "iwlwifi-BzBnj-b0-fm-b0-"
-
+#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0"
+#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
+#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0"
+#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0"
+#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0"
+#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0"
+#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0"
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_QNJ_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_QNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_QUZ_A_JF_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \
- IWL_QU_C_HR_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
- IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
- IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode"
+ IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
#define IWL_CC_A_MODULE_FIRMWARE(api) \
- IWL_CC_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_SO_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_SO_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_TY_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_JF_B_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_JF_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(api) \
- IWL_MA_B_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_SNJ_A_MR_A_MODULE_FIRMWARE(api) \
- IWL_SNJ_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_HR_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM4_A_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
- IWL_BZ_A_FM4_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
- IWL_GL_B_FM_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_FM_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_FM_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_FM4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_FM4_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_GF_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_GF_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_GF_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_GF4_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_HR_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_A_HR_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_A_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_HR_A_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_HR_A_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_HR_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_HR_B_FW_PRE __stringify(api) ".ucode"
-#define IWL_BNJ_B_FM_B_MODULE_FIRMWARE(api) \
- IWL_BNJ_B_FM_B_FW_PRE __stringify(api) ".ucode"
+ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl_22000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@@ -195,34 +59,14 @@ static const struct iwl_base_params iwl_22000_base_params = {
.pcie_l1_allowed = true,
};
-static const struct iwl_base_params iwl_ax210_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
- .num_of_queues = 512,
- .max_tfd_queue_size = 65536,
- .shadow_ram_support = true,
- .led_compensation = 57,
- .wd_timeout = IWL_LONG_WD_TIMEOUT,
- .max_event_log_size = 512,
- .shadow_reg_enable = true,
- .pcie_l1_allowed = true,
-};
-
-static const struct iwl_ht_params iwl_22000_ht_params = {
+const struct iwl_ht_params iwl_22000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
};
-static const struct iwl_ht_params iwl_gl_a_ht_params = {
- .stbc = false, /* we explicitly disable STBC for GL step A */
- .ldpc = true,
- .ht40_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) |
- BIT(NL80211_BAND_6GHZ),
-};
-
#define IWL_DEVICE_22000_COMMON \
- .ucode_api_max = IWL_22000_UCODE_API_MAX, \
.ucode_api_min = IWL_22000_UCODE_API_MIN, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = 10, \
@@ -240,7 +84,6 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
.mac_addr_from_csr = 0x380, \
.ht_params = &iwl_22000_ht_params, \
.nvm_ver = IWL_22000_NVM_VERSION, \
- .trans.use_tfh = true, \
.trans.rf_id = true, \
.trans.gen2 = true, \
.nvm_type = IWL_NVM_EXT, \
@@ -261,6 +104,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
#define IWL_DEVICE_22500 \
IWL_DEVICE_22000_COMMON, \
+ .ucode_api_max = IWL_22000_UCODE_API_MAX, \
.trans.device_family = IWL_DEVICE_FAMILY_22000, \
.trans.base_params = &iwl_22000_base_params, \
.gp2_reg_addr = 0xa02c68, \
@@ -275,111 +119,8 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = {
}, \
}
-#define IWL_DEVICE_AX210 \
- IWL_DEVICE_22000_COMMON, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
- .trans.base_params = &iwl_ax210_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_BZ_COMMON \
- .ucode_api_max = IWL_22000_UCODE_API_MAX, \
- .ucode_api_min = IWL_22000_UCODE_API_MIN, \
- .led_mode = IWL_LED_RF_STATE, \
- .nvm_hw_section_num = 10, \
- .non_shared_ant = ANT_B, \
- .dccm_offset = IWL_22000_DCCM_OFFSET, \
- .dccm_len = IWL_22000_DCCM_LEN, \
- .dccm2_offset = IWL_22000_DCCM2_OFFSET, \
- .dccm2_len = IWL_22000_DCCM2_LEN, \
- .smem_offset = IWL_22000_SMEM_OFFSET, \
- .smem_len = IWL_22000_SMEM_LEN, \
- .apmg_not_supported = true, \
- .trans.mq_rx_supported = true, \
- .vht_mu_mimo_supported = true, \
- .mac_addr_from_csr = 0x30, \
- .nvm_ver = IWL_22000_NVM_VERSION, \
- .trans.use_tfh = true, \
- .trans.rf_id = true, \
- .trans.gen2 = true, \
- .nvm_type = IWL_NVM_EXT, \
- .dbgc_supported = true, \
- .min_umac_error_event_table = 0xD0000, \
- .d3_debug_data_base_addr = 0x401000, \
- .d3_debug_data_length = 60 * 1024, \
- .mon_smem_regs = { \
- .write_ptr = { \
- .addr = LDBG_M2S_BUF_WPTR, \
- .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = LDBG_M2S_BUF_WRAP_CNT, \
- .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
- }, \
- }, \
- .trans.umac_prph_offset = 0x300000, \
- .trans.device_family = IWL_DEVICE_FAMILY_BZ, \
- .trans.base_params = &iwl_ax210_base_params, \
- .min_txq_size = 128, \
- .gp2_reg_addr = 0xd02c68, \
- .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
- .mon_dram_regs = { \
- .write_ptr = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
- }, \
- .cycle_cnt = { \
- .addr = DBGC_DBGBUF_WRAP_AROUND, \
- .mask = 0xffffffff, \
- }, \
- .cur_frag = { \
- .addr = DBGC_CUR_DBGBUF_STATUS, \
- .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
- }, \
- }, \
- .mon_dbgi_regs = { \
- .write_ptr = { \
- .addr = DBGI_SRAM_FIFO_POINTERS, \
- .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
- }, \
- }
-
-#define IWL_DEVICE_BZ \
- IWL_DEVICE_BZ_COMMON, \
- .ht_params = &iwl_22000_ht_params
-
-#define IWL_DEVICE_GL_A \
- IWL_DEVICE_BZ_COMMON, \
- .ht_params = &iwl_gl_a_ht_params
-
-const struct iwl_cfg_trans_params iwl_qnj_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_22000,
- .base_params = &iwl_22000_base_params,
-};
-
const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -391,7 +132,6 @@ const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -403,7 +143,6 @@ const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.device_family = IWL_DEVICE_FAMILY_22000,
@@ -414,59 +153,6 @@ const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
.ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
};
-const struct iwl_cfg_trans_params iwl_snj_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
-};
-
-const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- /* TODO: the following values need to be checked */
- .xtal_latency = 500,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
-};
-
-const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- .low_latency_xtal = true,
- .xtal_latency = 12000,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
-};
-
-const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .umac_prph_offset = 0x300000,
- .integrated = true,
- .low_latency_xtal = true,
- .xtal_latency = 12000,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
- .imr_enabled = true,
-};
-
/*
* If the device doesn't support HE, no need to have that many buffers.
* 22000 devices can split multiple frames into a single RB, so fewer are
@@ -476,7 +162,6 @@ const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
*/
#define IWL_NUM_RBDS_NON_HE 512
#define IWL_NUM_RBDS_22000_HE 2048
-#define IWL_NUM_RBDS_AX210_HE 4096
/*
* All JF radio modules are part of the 9000 series, but the MAC part
@@ -507,63 +192,20 @@ const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg = {
.num_rbds = IWL_NUM_RBDS_NON_HE,
};
-const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg = {
- .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
.device_family = IWL_DEVICE_FAMILY_22000,
.base_params = &iwl_22000_base_params,
.mq_rx_supported = true,
- .use_tfh = true,
.rf_id = true,
.gen2 = true,
.bisr_workaround = 1,
};
-const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_AX210,
- .base_params = &iwl_ax210_base_params,
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .integrated = true,
- .umac_prph_offset = 0x300000
-};
-
-const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
- .device_family = IWL_DEVICE_FAMILY_BZ,
- .base_params = &iwl_ax210_base_params,
- .mq_rx_supported = true,
- .use_tfh = true,
- .rf_id = true,
- .gen2 = true,
- .integrated = true,
- .umac_prph_offset = 0x300000,
- .xtal_latency = 12000,
- .low_latency_xtal = true,
- .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
-};
-
const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101";
const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz";
const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz";
const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203";
const char iwl_ax204_name[] = "Intel(R) Wi-Fi 6 AX204 160MHz";
-const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
-const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
-const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
-const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
-const char iwl_bz_name[] = "Intel(R) TBD Bz device";
const char iwl_ax200_killer_1650w_name[] =
"Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)";
@@ -573,18 +215,6 @@ const char iwl_ax201_killer_1650s_name[] =
"Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)";
const char iwl_ax201_killer_1650i_name[] =
"Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)";
-const char iwl_ax210_killer_1675w_name[] =
- "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
-const char iwl_ax210_killer_1675x_name[] =
- "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
-const char iwl_ax211_killer_1675s_name[] =
- "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax211_killer_1675i_name[] =
- "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
-const char iwl_ax411_killer_1690s_name[] =
- "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
-const char iwl_ax411_killer_1690i_name[] =
- "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
@@ -778,203 +408,6 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
-const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = {
- .fw_name_pre = IWL_QNJ_B_HR_B_FW_PRE,
- IWL_DEVICE_22500,
- /*
- * This device doesn't support receiving BlockAck with a large bitmap
- * so we need to restrict the size of transmitted aggregation to the
- * HT size; mac80211 would otherwise pick the HE max (256) by default.
- */
- .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
- .num_rbds = IWL_NUM_RBDS_22000_HE,
-};
-
-const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
- .name = "Intel(R) Wireless-AC 9560 160MHz",
- .fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_NON_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
- .name = "Intel(R) Wi-Fi 6 AX210 160MHz",
- .fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
- .trans.xtal_latency = 12000,
- .trans.low_latency_xtal = true,
-};
-
-const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0 = {
- .name = iwl_ax411_name,
- .fw_name_pre = IWL_SNJ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwlax211_cfg_snj_gf_a0 = {
- .name = iwl_ax211_name,
- .fw_name_pre = IWL_SNJ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_hr_b0 = {
- .fw_name_pre = IWL_SNJ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_jf_b0 = {
- .fw_name_pre = IWL_SNJ_A_JF_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_hr_b0 = {
- .fw_name_pre = IWL_MA_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_gf_a0 = {
- .fw_name_pre = IWL_MA_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0 = {
- .fw_name_pre = IWL_MA_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_mr_a0 = {
- .fw_name_pre = IWL_MA_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_ms_a0 = {
- .fw_name_pre = IWL_MA_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_fm_a0 = {
- .fw_name_pre = IWL_MA_B_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_hr_b0 = {
- .fw_name_pre = IWL_MA_B_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_gf_a0 = {
- .fw_name_pre = IWL_MA_B_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0 = {
- .fw_name_pre = IWL_MA_B_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_b0_mr_a0 = {
- .fw_name_pre = IWL_MA_B_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
- .fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_ma_a0_fm_a0 = {
- .fw_name_pre = IWL_MA_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_mr_a0 = {
- .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_snj_a0_ms_a0 = {
- .fw_name_pre = IWL_SNJ_A_MR_A_FW_PRE,
- .uhb_supported = false,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
- .fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
- IWL_DEVICE_AX210,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
IWL_DEVICE_22500,
@@ -987,243 +420,9 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
.num_rbds = IWL_NUM_RBDS_22000_HE,
};
-const struct iwl_cfg iwl_cfg_bz_a0_hr_a0 = {
- .fw_name_pre = IWL_BZ_A_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_hr_b0 = {
- .fw_name_pre = IWL_BZ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_gf_a0 = {
- .fw_name_pre = IWL_BZ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0 = {
- .fw_name_pre = IWL_BZ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
- .fw_name_pre = IWL_BZ_A_MR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = {
- .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0 = {
- .fw_name_pre = IWL_BZ_A_FM4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm_b0 = {
- .fw_name_pre = IWL_BZ_A_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0 = {
- .fw_name_pre = IWL_BZ_A_FM4_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
- .fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_GL_A,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_gl_b0_fm_b0 = {
- .fw_name_pre = IWL_GL_B_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = {
- .fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0 = {
- .fw_name_pre = IWL_BNJ_A_FM_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0 = {
- .fw_name_pre = IWL_BNJ_A_FM4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0 = {
- .fw_name_pre = IWL_BNJ_B_FM4_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0 = {
- .fw_name_pre = IWL_BNJ_A_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0 = {
- .fw_name_pre = IWL_BNJ_B_GF_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0 = {
- .fw_name_pre = IWL_BNJ_A_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0 = {
- .fw_name_pre = IWL_BNJ_B_GF4_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0 = {
- .fw_name_pre = IWL_BNJ_A_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0 = {
- .fw_name_pre = IWL_BNJ_A_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0 = {
- .fw_name_pre = IWL_BNJ_B_HR_A_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0 = {
- .fw_name_pre = IWL_BNJ_B_HR_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
-
-const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = {
- .fw_name_pre = IWL_BNJ_B_FM_B_FW_PRE,
- .uhb_supported = true,
- IWL_DEVICE_BZ,
- .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
- .num_rbds = IWL_NUM_RBDS_AX210_HE,
-};
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_A_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_MA_B_FM_A_FW_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_SNJ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_HR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL_BNJ_B_FM_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
index e2e23d2bc1fe..de7ede59a994 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/5000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -24,11 +24,11 @@
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)
-#define IWL5000_FW_PRE "iwlwifi-5000-"
-#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"
+#define IWL5000_FW_PRE "iwlwifi-5000"
+#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL5150_FW_PRE "iwlwifi-5150-"
-#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"
+#define IWL5150_FW_PRE "iwlwifi-5150"
+#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl5000_base_params = {
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index 20929e59c2f4..f013cf420569 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2020, 2023 Intel Corporation
*****************************************************************************/
#include <linux/module.h>
@@ -37,17 +37,17 @@
#define EEPROM_6035_TX_POWER_VERSION (6)
#define EEPROM_6035_EEPROM_VERSION (0x753)
-#define IWL6000_FW_PRE "iwlwifi-6000-"
-#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode"
+#define IWL6000_FW_PRE "iwlwifi-6000"
+#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6050_FW_PRE "iwlwifi-6050-"
-#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode"
+#define IWL6050_FW_PRE "iwlwifi-6050"
+#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
-#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode"
+#define IWL6005_FW_PRE "iwlwifi-6000g2a"
+#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
-#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode"
+#define IWL6030_FW_PRE "iwlwifi-6000g2b"
+#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl6000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_2K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
index b24dc5523a52..4e2afdedf4c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 Intel Deutschland GmbH
*/
@@ -34,20 +34,20 @@
#define IWL3160_DCCM_LEN 0x10000
#define IWL7265_DCCM_LEN 0x17A00
-#define IWL7260_FW_PRE "iwlwifi-7260-"
-#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
+#define IWL7260_FW_PRE "iwlwifi-7260"
+#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL3160_FW_PRE "iwlwifi-3160-"
-#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode"
+#define IWL3160_FW_PRE "iwlwifi-3160"
+#define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL3168_FW_PRE "iwlwifi-3168-"
-#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE __stringify(api) ".ucode"
+#define IWL3168_FW_PRE "iwlwifi-3168"
+#define IWL3168_MODULE_FIRMWARE(api) IWL3168_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL7265_FW_PRE "iwlwifi-7265-"
-#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
+#define IWL7265_FW_PRE "iwlwifi-7265"
+#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL7265D_FW_PRE "iwlwifi-7265D-"
-#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE __stringify(api) ".ucode"
+#define IWL7265D_FW_PRE "iwlwifi-7265D"
+#define IWL7265D_MODULE_FIRMWARE(api) IWL7265D_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl7000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_16K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
index a6454287d506..d09cf8d7dc01 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2014, 2018-2020, 2023 Intel Corporation
* Copyright (C) 2014-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -27,13 +27,13 @@
#define IWL8260_SMEM_OFFSET 0x400000
#define IWL8260_SMEM_LEN 0x68000
-#define IWL8000_FW_PRE "iwlwifi-8000C-"
+#define IWL8000_FW_PRE "iwlwifi-8000C"
#define IWL8000_MODULE_FIRMWARE(api) \
- IWL8000_FW_PRE __stringify(api) ".ucode"
+ IWL8000_FW_PRE "-" __stringify(api) ".ucode"
-#define IWL8265_FW_PRE "iwlwifi-8265-"
+#define IWL8265_FW_PRE "iwlwifi-8265"
#define IWL8265_MODULE_FIRMWARE(api) \
- IWL8265_FW_PRE __stringify(api) ".ucode"
+ IWL8265_FW_PRE "-" __stringify(api) ".ucode"
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
index 7a7ca06d46c1..0130d9a9b78b 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2021, 2023 Intel Corporation
*/
#include <linux/module.h>
#include <linux/stringify.h>
@@ -26,12 +26,12 @@
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
-#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-"
-#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
+#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0"
+#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0"
#define IWL9000_MODULE_FIRMWARE(api) \
- IWL9000_FW_PRE __stringify(api) ".ucode"
+ IWL9000_FW_PRE "-" __stringify(api) ".ucode"
#define IWL9260_MODULE_FIRMWARE(api) \
- IWL9260_FW_PRE __stringify(api) ".ucode"
+ IWL9260_FW_PRE "-" __stringify(api) ".ucode"
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
new file mode 100644
index 000000000000..8d5f9dce71d5
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_AX210_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_AX210_UCODE_API_MIN 59
+
+/* NVM versions */
+#define IWL_AX210_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_AX210_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_AX210_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_AX210_DCCM2_OFFSET 0x880000
+#define IWL_AX210_DCCM2_LEN 0x8000
+#define IWL_AX210_SMEM_OFFSET 0x400000
+#define IWL_AX210_SMEM_LEN 0xD0000
+
+#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0"
+#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0"
+#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0"
+#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0"
+#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0"
+#define IWL_SO_A_MR_A_FW_PRE "iwlwifi-so-a0-mr-a0"
+#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0"
+#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0"
+#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0"
+#define IWL_MA_A_MR_A_FW_PRE "iwlwifi-ma-a0-mr-a0"
+#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0"
+#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0"
+#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0"
+#define IWL_MA_B_MR_A_FW_PRE "iwlwifi-ma-b0-mr-a0"
+
+#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_SO_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_TY_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_A_MR_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_MA_B_MR_A_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_ax210_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_AX210_COMMON \
+ .ucode_api_min = IWL_AX210_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_AX210_DCCM_OFFSET, \
+ .dccm_len = IWL_AX210_DCCM_LEN, \
+ .dccm2_offset = IWL_AX210_DCCM2_OFFSET, \
+ .dccm2_len = IWL_AX210_DCCM2_LEN, \
+ .smem_offset = IWL_AX210_SMEM_OFFSET, \
+ .smem_len = IWL_AX210_SMEM_LEN, \
+ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x380, \
+ .ht_params = &iwl_22000_ht_params, \
+ .nvm_ver = IWL_AX210_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0x400000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_AX210 \
+ IWL_DEVICE_AX210_COMMON, \
+ .ucode_api_max = IWL_AX210_UCODE_API_MAX, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_AX210, \
+ .trans.base_params = &iwl_ax210_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_HE, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }
+
+const struct iwl_cfg_trans_params iwl_so_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ /* TODO: the following values need to be checked */
+ .xtal_latency = 500,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_200US,
+};
+
+const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ .low_latency_xtal = true,
+ .xtal_latency = 12000,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg = {
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .umac_prph_offset = 0x300000,
+ .integrated = true,
+ .low_latency_xtal = true,
+ .xtal_latency = 12000,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+ .imr_enabled = true,
+};
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * AX210 devices can split multiple frames into a single RB, so fewer are
+ * needed; AX210 cannot (but use smaller RBs by default) - these sizes
+ * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
+ * additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_AX210_HE 4096
+
+const struct iwl_cfg_trans_params iwl_ma_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_AX210,
+ .base_params = &iwl_ax210_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000
+};
+
+const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz";
+const char iwl_ax221_name[] = "Intel(R) Wi-Fi 6E AX221 160MHz";
+const char iwl_ax231_name[] = "Intel(R) Wi-Fi 6E AX231 160MHz";
+const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz";
+
+const char iwl_ax210_killer_1675w_name[] =
+ "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
+const char iwl_ax210_killer_1675x_name[] =
+ "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
+const char iwl_ax211_killer_1675s_name[] =
+ "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax211_killer_1675i_name[] =
+ "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax411_killer_1690s_name[] =
+ "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
+const char iwl_ax411_killer_1690i_name[] =
+ "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
+
+const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
+ .name = "Intel(R) Wireless-AC 9560 160MHz",
+ .fw_name_pre = IWL_SO_A_JF_B_FW_PRE,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_NON_HE,
+};
+
+const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
+ .name = iwl_ax211_name,
+ .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = {
+ .name = iwl_ax211_name,
+ .fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+ .trans.xtal_latency = 12000,
+ .trans.low_latency_xtal = true,
+};
+
+const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
+ .name = "Intel(R) Wi-Fi 6 AX210 160MHz",
+ .fw_name_pre = IWL_TY_A_GF_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
+ .name = iwl_ax411_name,
+ .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = {
+ .name = iwl_ax411_name,
+ .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE,
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+ .trans.xtal_latency = 12000,
+ .trans.low_latency_xtal = true,
+};
+
+const struct iwl_cfg iwl_cfg_so_a0_ms_a0 = {
+ .fw_name_pre = IWL_SO_A_MR_A_FW_PRE,
+ .uhb_supported = false,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_ma = {
+ .fw_name_mac = "ma",
+ .uhb_supported = true,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_so_a0_hr_a0 = {
+ .fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
+ IWL_DEVICE_AX210,
+ .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_A_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
new file mode 100644
index 000000000000..b9893b22e41d
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_BZ_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_BZ_UCODE_API_MIN 80
+
+/* NVM versions */
+#define IWL_BZ_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_BZ_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_BZ_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_BZ_DCCM2_OFFSET 0x880000
+#define IWL_BZ_DCCM2_LEN 0x8000
+#define IWL_BZ_SMEM_OFFSET 0x400000
+#define IWL_BZ_SMEM_LEN 0xD0000
+
+#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0"
+#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0"
+#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0"
+#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
+#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
+#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0"
+#define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0"
+#define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0"
+
+#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM_C_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_BZ_A_FM4_B_MODULE_FIRMWARE(api) \
+ IWL_BZ_A_FM4_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_GL_B_FM_B_MODULE_FIRMWARE(api) \
+ IWL_GL_B_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_GL_C_FM_C_MODULE_FIRMWARE(api) \
+ IWL_GL_C_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_bz_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_BZ_COMMON \
+ .ucode_api_max = IWL_BZ_UCODE_API_MAX, \
+ .ucode_api_min = IWL_BZ_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_BZ_DCCM_OFFSET, \
+ .dccm_len = IWL_BZ_DCCM_LEN, \
+ .dccm2_offset = IWL_BZ_DCCM2_OFFSET, \
+ .dccm2_len = IWL_BZ_DCCM2_LEN, \
+ .smem_offset = IWL_BZ_SMEM_OFFSET, \
+ .smem_len = IWL_BZ_SMEM_LEN, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x30, \
+ .nvm_ver = IWL_BZ_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0xD0000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_BZ, \
+ .trans.base_params = &iwl_bz_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }, \
+ .mon_dbgi_regs = { \
+ .write_ptr = { \
+ .addr = DBGI_SRAM_FIFO_POINTERS, \
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_BZ \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_22000_ht_params
+
+#define IWL_DEVICE_GL_A \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_gl_a_ht_params
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
+ * A-MPDU, with additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_BZ_HE 4096
+
+const struct iwl_cfg_trans_params iwl_bz_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_BZ,
+ .base_params = &iwl_bz_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000,
+ .xtal_latency = 12000,
+ .low_latency_xtal = true,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const char iwl_bz_name[] = "Intel(R) TBD Bz device";
+
+const struct iwl_cfg iwl_cfg_bz = {
+ .fw_name_mac = "bz",
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_BZ_HE,
+};
+
+const struct iwl_cfg iwl_cfg_gl = {
+ .fw_name_mac = "gl",
+ .uhb_supported = true,
+ IWL_DEVICE_BZ,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_BZ_HE,
+};
+
+
+MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
new file mode 100644
index 000000000000..ad283fd22e2a
--- /dev/null
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
+ */
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include "iwl-config.h"
+#include "iwl-prph.h"
+#include "fw/api/txq.h"
+
+/* Highest firmware API version supported */
+#define IWL_SC_UCODE_API_MAX 83
+
+/* Lowest firmware API version supported */
+#define IWL_SC_UCODE_API_MIN 82
+
+/* NVM versions */
+#define IWL_SC_NVM_VERSION 0x0a1d
+
+/* Memory offsets and lengths */
+#define IWL_SC_DCCM_OFFSET 0x800000 /* LMAC1 */
+#define IWL_SC_DCCM_LEN 0x10000 /* LMAC1 */
+#define IWL_SC_DCCM2_OFFSET 0x880000
+#define IWL_SC_DCCM2_LEN 0x8000
+#define IWL_SC_SMEM_OFFSET 0x400000
+#define IWL_SC_SMEM_LEN 0xD0000
+
+#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0"
+#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0"
+#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0"
+#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0"
+#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
+#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
+#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
+
+#define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
+
+static const struct iwl_base_params iwl_sc_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+ .num_of_queues = 512,
+ .max_tfd_queue_size = 65536,
+ .shadow_ram_support = true,
+ .led_compensation = 57,
+ .wd_timeout = IWL_LONG_WD_TIMEOUT,
+ .max_event_log_size = 512,
+ .shadow_reg_enable = true,
+ .pcie_l1_allowed = true,
+};
+
+#define IWL_DEVICE_BZ_COMMON \
+ .ucode_api_max = IWL_SC_UCODE_API_MAX, \
+ .ucode_api_min = IWL_SC_UCODE_API_MIN, \
+ .led_mode = IWL_LED_RF_STATE, \
+ .nvm_hw_section_num = 10, \
+ .non_shared_ant = ANT_B, \
+ .dccm_offset = IWL_SC_DCCM_OFFSET, \
+ .dccm_len = IWL_SC_DCCM_LEN, \
+ .dccm2_offset = IWL_SC_DCCM2_OFFSET, \
+ .dccm2_len = IWL_SC_DCCM2_LEN, \
+ .smem_offset = IWL_SC_SMEM_OFFSET, \
+ .smem_len = IWL_SC_SMEM_LEN, \
+ .apmg_not_supported = true, \
+ .trans.mq_rx_supported = true, \
+ .vht_mu_mimo_supported = true, \
+ .mac_addr_from_csr = 0x30, \
+ .nvm_ver = IWL_SC_NVM_VERSION, \
+ .trans.rf_id = true, \
+ .trans.gen2 = true, \
+ .nvm_type = IWL_NVM_EXT, \
+ .dbgc_supported = true, \
+ .min_umac_error_event_table = 0xD0000, \
+ .d3_debug_data_base_addr = 0x401000, \
+ .d3_debug_data_length = 60 * 1024, \
+ .mon_smem_regs = { \
+ .write_ptr = { \
+ .addr = LDBG_M2S_BUF_WPTR, \
+ .mask = LDBG_M2S_BUF_WPTR_VAL_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = LDBG_M2S_BUF_WRAP_CNT, \
+ .mask = LDBG_M2S_BUF_WRAP_CNT_VAL_MSK, \
+ }, \
+ }, \
+ .trans.umac_prph_offset = 0x300000, \
+ .trans.device_family = IWL_DEVICE_FAMILY_SC, \
+ .trans.base_params = &iwl_sc_base_params, \
+ .min_txq_size = 128, \
+ .gp2_reg_addr = 0xd02c68, \
+ .min_ba_txq_size = IWL_DEFAULT_QUEUE_SIZE_EHT, \
+ .mon_dram_regs = { \
+ .write_ptr = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK, \
+ }, \
+ .cycle_cnt = { \
+ .addr = DBGC_DBGBUF_WRAP_AROUND, \
+ .mask = 0xffffffff, \
+ }, \
+ .cur_frag = { \
+ .addr = DBGC_CUR_DBGBUF_STATUS, \
+ .mask = DBGC_CUR_DBGBUF_STATUS_IDX_MSK, \
+ }, \
+ }, \
+ .mon_dbgi_regs = { \
+ .write_ptr = { \
+ .addr = DBGI_SRAM_FIFO_POINTERS, \
+ .mask = DBGI_SRAM_FIFO_POINTERS_WR_PTR_MSK, \
+ }, \
+ }
+
+#define IWL_DEVICE_SC \
+ IWL_DEVICE_BZ_COMMON, \
+ .ht_params = &iwl_22000_ht_params
+
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * These sizes were picked according to 8 MSDUs inside 256 A-MSDUs in an
+ * A-MPDU, with additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE 512
+#define IWL_NUM_RBDS_SC_HE 4096
+
+const struct iwl_cfg_trans_params iwl_sc_trans_cfg = {
+ .device_family = IWL_DEVICE_FAMILY_SC,
+ .base_params = &iwl_sc_base_params,
+ .mq_rx_supported = true,
+ .rf_id = true,
+ .gen2 = true,
+ .integrated = true,
+ .umac_prph_offset = 0x300000,
+ .xtal_latency = 12000,
+ .low_latency_xtal = true,
+ .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US,
+};
+
+const char iwl_sc_name[] = "Intel(R) TBD Sc device";
+
+const struct iwl_cfg iwl_cfg_sc = {
+ .fw_name_mac = "sc",
+ .uhb_supported = true,
+ IWL_DEVICE_SC,
+ .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM,
+ .num_rbds = IWL_NUM_RBDS_SC_HE,
+};
+
+MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
index 687c906a9d72..f4a6f76cf193 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright (C) 2019 - 2020, 2022 Intel Corporation
+ * Copyright (C) 2019 - 2020, 2022 - 2023 Intel Corporation
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -125,7 +125,7 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
return idx;
}
- return -1;
+ return IWL_RATE_INVALID;
}
static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -203,23 +203,6 @@ static const u16 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
{0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */
};
-/* mbps, mcs */
-static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
- { "1", "BPSK DSSS"},
- { "2", "QPSK DSSS"},
- {"5.5", "BPSK CCK"},
- { "11", "QPSK CCK"},
- { "6", "BPSK 1/2"},
- { "9", "BPSK 1/2"},
- { "12", "QPSK 1/2"},
- { "18", "QPSK 3/4"},
- { "24", "16QAM 1/2"},
- { "36", "16QAM 3/4"},
- { "48", "64QAM 2/3"},
- { "54", "64QAM 3/4"},
- { "60", "64QAM 5/6"},
-};
-
#define MCS_INDEX_PER_STREAM (8)
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -3089,6 +3072,23 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
int index = 0;
ssize_t ret;
+ /* mbps, mcs */
+ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+ { "1", "BPSK DSSS"},
+ { "2", "QPSK DSSS"},
+ {"5.5", "BPSK CCK"},
+ { "11", "QPSK CCK"},
+ { "6", "BPSK 1/2"},
+ { "9", "BPSK 1/2"},
+ { "12", "QPSK 1/2"},
+ { "18", "QPSK 3/4"},
+ { "24", "16QAM 1/2"},
+ { "36", "16QAM 3/4"},
+ { "48", "64QAM 2/3"},
+ { "54", "64QAM 3/4"},
+ { "60", "64QAM 5/6"},
+ };
+
struct iwl_lq_sta *lq_sta = file->private_data;
struct iwl_priv *priv;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -3146,7 +3146,10 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
index = iwl_hwrate_to_plcp_idx(
le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
- if (is_legacy(tbl->lq_type)) {
+ if (index == IWL_RATE_INVALID) {
+ desc += sprintf(buff + desc, " rate[%d] 0x%X invalid rate\n",
+ i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+ } else if (is_legacy(tbl->lq_type)) {
desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
iwl_rate_mcs[index].mbps);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
index cb9181f05501..dfe8357036eb 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2022 Intel Corporation
+ * Copyright (C) 2019-2023 Intel Corporation
*/
#include <linux/uuid.h>
#include <linux/dmi.h>
@@ -41,6 +41,34 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
+ { .ident = "GOOGLE-HP",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ },
+ },
+ { .ident = "GOOGLE-ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."),
+ },
+ },
+ { .ident = "GOOGLE-SAMSUNG",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"),
+ },
+ },
+ { .ident = "DELL",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ },
+ },
+ { .ident = "DELL",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ },
+ },
{}
};
@@ -66,7 +94,7 @@ static int iwl_acpi_get_handle(struct device *dev, acpi_string method,
return 0;
}
-void *iwl_acpi_get_object(struct device *dev, acpi_string method)
+static void *iwl_acpi_get_object(struct device *dev, acpi_string method)
{
struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_handle handle;
@@ -87,7 +115,6 @@ void *iwl_acpi_get_object(struct device *dev, acpi_string method)
}
return buf.pointer;
}
-IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
/*
* Generic function for evaluating a method defined in the device specific
@@ -209,11 +236,12 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
}
IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32);
-union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size,
- int max_data_size,
- int *tbl_rev)
+static union acpi_object *
+iwl_acpi_get_wifi_pkg_range(struct device *dev,
+ union acpi_object *data,
+ int min_data_size,
+ int max_data_size,
+ int *tbl_rev)
{
int i;
union acpi_object *wifi_pkg;
@@ -264,7 +292,16 @@ union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
found:
return wifi_pkg;
}
-IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);
+
+static union acpi_object *
+iwl_acpi_get_wifi_pkg(struct device *dev,
+ union acpi_object *data,
+ int data_size, int *tbl_rev)
+{
+ return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
+ tbl_rev);
+}
+
int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
union iwl_tas_config_cmd *cmd, int fw_ver)
@@ -1141,33 +1178,48 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
*/
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
+ IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver);
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
*cmd_size = sizeof(cmd->v1);
if (fwrt->ppag_ver == 1 || fwrt->ppag_ver == 2) {
+ /* in this case FW supports revision 0 */
IWL_DEBUG_RADIO(fwrt,
- "PPAG table rev is %d but FW supports v1, sending truncated table\n",
+ "PPAG table rev is %d, send truncated table\n",
fwrt->ppag_ver);
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
}
} else if (cmd_ver >= 2 && cmd_ver <= 4) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v2.gain[0];
*cmd_size = sizeof(cmd->v2);
if (fwrt->ppag_ver == 0) {
+ /* in this case FW supports revisions 1 or 2 */
IWL_DEBUG_RADIO(fwrt,
- "PPAG table is v1 but FW supports v2, sending padded table\n");
- } else if (cmd_ver == 2 && fwrt->ppag_ver == 2) {
- IWL_DEBUG_RADIO(fwrt,
- "PPAG table is v3 but FW supports v2, sending partial bitmap.\n");
- cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
+ "PPAG table rev is 0, send padded table\n");
}
} else {
IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n");
return -EINVAL;
}
+ /* ppag mode */
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG MODE bits were read from bios: %d\n",
+ cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
+ if ((cmd_ver == 1 && !fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
+ (cmd_ver == 2 && fwrt->ppag_ver == 2)) {
+ cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
+ IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
+ } else {
+ IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n");
+ }
+
+ IWL_DEBUG_RADIO(fwrt,
+ "PPAG MODE bits going to be sent: %d\n",
+ cmd->v1.flags & cpu_to_le32(ACPI_PPAG_MASK));
+
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (j = 0; j < num_sub_bands; j++) {
gain[i * num_sub_bands + j] =
@@ -1196,3 +1248,40 @@ bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return true;
}
IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved);
+
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
+{
+ struct iwl_phy_specific_cfg tmp = {};
+ union acpi_object *wifi_pkg, *data;
+ int tbl_rev, i;
+
+ data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
+ if (IS_ERR(data))
+ return;
+
+ /* try to read wtas table revision 1 or revision 0*/
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WPFC_WIFI_DATA_SIZE,
+ &tbl_rev);
+ if (IS_ERR(wifi_pkg))
+ goto out_free;
+
+ if (tbl_rev != 0)
+ goto out_free;
+
+ BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE);
+
+ for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+ if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
+ return;
+ tmp.filter_cfg_chains[i] =
+ cpu_to_le32(wifi_pkg->package.elements[i].integer.value);
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
+ *filters = tmp;
+out_free:
+ kfree(data);
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
index 6f361c59106f..c36c62d6414d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __iwl_fw_acpi__
#define __iwl_fw_acpi__
@@ -11,6 +11,7 @@
#include "fw/api/power.h"
#include "fw/api/phy.h"
#include "fw/api/nvm-reg.h"
+#include "fw/api/config.h"
#include "fw/img.h"
#include "iwl-trans.h"
@@ -23,6 +24,7 @@
#define ACPI_ECKV_METHOD "ECKV"
#define ACPI_PPAG_METHOD "PPAG"
#define ACPI_WTAS_METHOD "WTAS"
+#define ACPI_WPFC_METHOD "WPFC"
#define ACPI_WIFI_DOMAIN (0x07)
@@ -54,6 +56,7 @@
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV2 * \
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
+#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */
/* revision 0 and 1 are identical, except for the semantics in the FW */
#define ACPI_GEO_NUM_BANDS_REV0 2
@@ -168,19 +171,12 @@ struct iwl_fw_runtime;
extern const guid_t iwl_guid;
extern const guid_t iwl_rfi_guid;
-void *iwl_acpi_get_object(struct device *dev, acpi_string method);
-
int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
const guid_t *guid, u8 *value);
int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
const guid_t *guid, u32 *value);
-union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size,
- int max_data_size,
- int *tbl_rev);
/**
* iwl_acpi_get_mcc - read MCC from ACPI, if available
*
@@ -232,12 +228,10 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
-#else /* CONFIG_ACPI */
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters);
-static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
-{
- return ERR_PTR(-ENOENT);
-}
+#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
int func, union acpi_object *args)
@@ -257,15 +251,6 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
return -ENOENT;
}
-static inline union acpi_object *
-iwl_acpi_get_wifi_pkg_range(struct device *dev,
- union acpi_object *data,
- int min_data_size, int max_data_size,
- int *tbl_rev)
-{
- return ERR_PTR(-ENOENT);
-}
-
static inline int iwl_acpi_get_mcc(struct device *dev, char *mcc)
{
return -ENOENT;
@@ -335,15 +320,11 @@ static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return false;
}
-#endif /* CONFIG_ACPI */
-
-static inline union acpi_object *
-iwl_acpi_get_wifi_pkg(struct device *dev,
- union acpi_object *data,
- int data_size, int *tbl_rev)
+static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
{
- return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
- tbl_rev);
}
+#endif /* CONFIG_ACPI */
+
#endif /* __iwl_fw_acpi__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
index 29e2816e7052..d9044ada6a43 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2020, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -18,7 +18,7 @@
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @macs: array of MAC id and colors which belong to the binding,
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding,
@@ -38,7 +38,7 @@ struct iwl_binding_cmd_v1 {
* ( BINDING_CONTEXT_CMD = 0x2b )
* @id_and_color: ID and color of the relevant Binding,
* &enum iwl_ctxt_id_and_color
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @macs: array of MAC id and colors which belong to the binding
* &enum iwl_ctxt_id_and_color
* @phy: PHY id and color which belongs to the binding
@@ -59,14 +59,6 @@ struct iwl_binding_cmd {
#define IWL_LMAC_24G_INDEX 0
#define IWL_LMAC_5G_INDEX 1
-static inline u32 iwl_mvm_get_lmac_id(const struct iwl_fw *fw,
- enum nl80211_band band){
- if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
- band == NL80211_BAND_2GHZ)
- return IWL_LMAC_24G_INDEX;
- return IWL_LMAC_5G_INDEX;
-}
-
/* The maximal number of fragments in the FW's schedule session */
#define IWL_MVM_MAX_QUOTA 128
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
index 111d96cbde6f..13cb0d53a1a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
@@ -139,11 +139,6 @@ enum iwl_legacy_cmds {
REMOVE_STA = 0x19,
/**
- * @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd
- */
- FW_GET_ITEM_CMD = 0x1a,
-
- /**
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
* &struct iwl_tx_cmd_gen3,
* response in &struct iwl_mvm_tx_resp or
@@ -534,12 +529,6 @@ enum iwl_legacy_cmds {
PROT_OFFLOAD_CONFIG_CMD = 0xd4,
/**
- * @OFFLOADS_QUERY_CMD:
- * No data in command, response in &struct iwl_wowlan_status
- */
- OFFLOADS_QUERY_CMD = 0xd5,
-
- /**
* @D0I3_END_CMD: End D0i3/D3 state, no command data
*/
D0I3_END_CMD = 0xed,
@@ -566,18 +555,22 @@ enum iwl_legacy_cmds {
WOWLAN_TKIP_PARAM = 0xe3,
/**
- * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd
+ * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2,
+ * &struct iwl_wowlan_kek_kck_material_cmd_v3 or
+ * &struct iwl_wowlan_kek_kck_material_cmd_v4
*/
WOWLAN_KEK_KCK_MATERIAL = 0xe4,
/**
- * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status
+ * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6,
+ * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or
+ * &struct iwl_wowlan_status_v12
*/
WOWLAN_GET_STATUSES = 0xe5,
/**
- * @SCAN_OFFLOAD_PROFILES_QUERY_CMD:
- * No command data, response is &struct iwl_scan_offload_profiles_query
+ * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: No command data, response is
+ * &struct iwl_scan_offload_profiles_query_v1
*/
SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
index 087354b3c308..4419631604b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -67,17 +67,12 @@ enum iwl_calib_cfg {
* Sent as part of the phy configuration command (v3) to configure specific FW
* defined PHY filters that can be applied to each antenna.
*
- * @filter_cfg_chain_a: filter config id for LMAC1 chain A
- * @filter_cfg_chain_b: filter config id for LMAC1 chain B
- * @filter_cfg_chain_c: filter config id for LMAC2 chain A
- * @filter_cfg_chain_d: filter config id for LMAC2 chain B
- * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id
+ * @filter_cfg_chains: filter config id for LMAC1 chain A, LMAC1 chain B,
+ * LMAC2 chain A, LMAC2 chain B (in that order)
+ * values: 0: no filter; 0xffffffff: reserved; otherwise: filter id
*/
struct iwl_phy_specific_cfg {
- __le32 filter_cfg_chain_a;
- __le32 filter_cfg_chain_b;
- __le32 filter_cfg_chain_c;
- __le32 filter_cfg_chain_d;
+ __le32 filter_cfg_chains[4];
} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
index 105ba7170c3f..1fa5678c1cd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014 Intel Corporation
+ * Copyright (C) 2012-2014, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -26,13 +26,18 @@ enum iwl_ctxt_id_and_color {
#define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\
((_color) << FW_CTXT_COLOR_POS))
-/* Possible actions on PHYs, MACs and Bindings */
+/**
+ * enum iwl_ctxt_action - Posssible actions on PHYs, MACs, Bindings and other
+ * @FW_CTXT_ACTION_INVALID: unused, invalid action
+ * @FW_CTXT_ACTION_ADD: add the context
+ * @FW_CTXT_ACTION_MODIFY: modify the context
+ * @FW_CTXT_ACTION_REMOVE: remove the context
+ */
enum iwl_ctxt_action {
- FW_CTXT_ACTION_STUB = 0,
+ FW_CTXT_ACTION_INVALID = 0,
FW_CTXT_ACTION_ADD,
FW_CTXT_ACTION_MODIFY,
FW_CTXT_ACTION_REMOVE,
- FW_CTXT_ACTION_NUM
}; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */
#endif /* __iwl_fw_api_context_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
index 8a613e150a02..72d461c47323 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -47,12 +47,14 @@ struct iwl_d3_manager_config {
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
* @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid
* @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid
+ * @IWL_D3_PROTO_OFFLOAD_BTM: BTM offload is enabled
*/
enum iwl_proto_offloads {
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
IWL_D3_PROTO_IPV4_VALID = BIT(2),
IWL_D3_PROTO_IPV6_VALID = BIT(3),
+ IWL_D3_PROTO_OFFLOAD_BTM = BIT(4),
};
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
@@ -394,6 +396,7 @@ struct iwl_wowlan_config_cmd {
#define WOWLAN_KEY_MAX_SIZE 32
#define WOWLAN_GTK_KEYS_NUM 2
#define WOWLAN_IGTK_KEYS_NUM 2
+#define WOWLAN_IGTK_MIN_INDEX 4
/*
* WOWLAN_TSC_RSC_PARAMS
@@ -610,6 +613,7 @@ struct iwl_wowlan_gtk_status_v3 {
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
+#define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0))
/**
* struct iwl_wowlan_igtk_status - IGTK status
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index 6f59381b9f9a..751b596ea1a5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -38,7 +38,9 @@ enum iwl_data_path_subcmd_ids {
WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD = 0x4,
/**
- * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd
+ * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd_v1,
+ * &struct iwl_he_sta_context_cmd_v2 or
+ * &struct iwl_he_sta_context_cmd_v3
*/
STA_HE_CTXT_CMD = 0x7,
@@ -447,7 +449,7 @@ struct iwl_sad_properties {
* @phy_id: PHY index
* @rlc: RLC properties, &struct iwl_rlc_properties
* @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties
- * @flags: flags, &enum iwl_rlc_flags
+ * @flags: flags (unused)
* @reserved: reserved
*/
struct iwl_rlc_config_cmd {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
index 12af94e166ed..b044990c7b87 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
*/
#ifndef __iwl_fw_api_location_h__
#define __iwl_fw_api_location_h__
@@ -35,8 +35,11 @@ enum iwl_location_subcmd_ids {
*/
TOF_RANGE_REQ_EXT_CMD = 0x3,
/**
- * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration,
- * uses &struct iwl_tof_responder_config_cmd
+ * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, one of
+ * &struct iwl_tof_responder_config_cmd_v6,
+ * &struct iwl_tof_responder_config_cmd_v7,
+ * &struct iwl_tof_responder_config_cmd_v8 or
+ * &struct iwl_tof_responder_config_cmd_v9
*/
TOF_RESPONDER_CONFIG_CMD = 0x4,
/**
@@ -69,8 +72,11 @@ enum iwl_location_subcmd_ids {
*/
TOF_MCSI_DEBUG_NOTIF = 0xFE,
/**
- * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using
- * &struct iwl_tof_range_rsp_ntfy
+ * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using one of
+ * &struct iwl_tof_range_rsp_ntfy_v5,
+ * &struct iwl_tof_range_rsp_ntfy_v6,
+ * &struct iwl_tof_range_rsp_ntfy_v7 or
+ * &struct iwl_tof_range_rsp_ntfy_v8
*/
TOF_RANGE_RESPONSE_NOTIF = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
index 74f2efbad34e..184db5a6f06f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
@@ -140,40 +140,60 @@ struct iwl_missed_vap_notif {
*
* @id_and_color: ID and color of the MAC
*/
-struct iwl_channel_switch_start_notif {
+struct iwl_channel_switch_start_notif_v1 {
__le32 id_and_color;
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
+/**
+ * struct iwl_channel_switch_start_notif - Channel switch start notification
+ *
+ * @link_id: FW link id
+ */
+struct iwl_channel_switch_start_notif {
+ __le32 link_id;
+} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_3 */
+
#define CS_ERR_COUNT_ERROR BIT(0)
#define CS_ERR_LONG_DELAY_AFTER_CS BIT(1)
#define CS_ERR_LONG_TX_BLOCK BIT(2)
#define CS_ERR_TX_BLOCK_TIMER_EXPIRED BIT(3)
/**
- * struct iwl_channel_switch_error_notif - Channel switch error notification
+ * struct iwl_channel_switch_error_notif_v1 - Channel switch error notification
*
* @mac_id: the mac for which the ucode sends the notification for
* @csa_err_mask: mask of channel switch error that can occur
*/
-struct iwl_channel_switch_error_notif {
+struct iwl_channel_switch_error_notif_v1 {
__le32 mac_id;
__le32 csa_err_mask;
} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_1 */
/**
+ * struct iwl_channel_switch_error_notif - Channel switch error notification
+ *
+ * @link_id: FW link id
+ * @csa_err_mask: mask of channel switch error that can occur
+ */
+struct iwl_channel_switch_error_notif {
+ __le32 link_id;
+ __le32 csa_err_mask;
+} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_2 */
+
+/**
* struct iwl_cancel_channel_switch_cmd - Cancel Channel Switch command
*
- * @mac_id: the mac that should cancel the channel switch
+ * @id: the id of the link or mac that should cancel the channel switch
*/
struct iwl_cancel_channel_switch_cmd {
- __le32 mac_id;
+ __le32 id;
} __packed; /* MAC_CANCEL_CHANNEL_SWITCH_S_VER_1 */
/**
* struct iwl_chan_switch_te_cmd - Channel Switch Time Event command
*
* @mac_id: MAC ID for channel switch
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @tsf: beacon tsf
* @cs_count: channel switch count from CSA/eCSA IE
* @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals
@@ -211,17 +231,30 @@ struct iwl_mac_low_latency_cmd {
* struct iwl_mac_client_data - configuration data for client MAC context
*
* @is_assoc: 1 for associated state, 0 otherwise
+ * @esr_transition_timeout: the timeout required by the AP for the
+ * eSR transition.
+ * Available only from version 2 of the command.
+ * This values comes from the EMLSR transition delay in the EML
+ * Capabilities subfield.
+ * @medium_sync_delay: the value as it appeasr in P802.11be_D2.2 Figure 9-1002j.
* @assoc_id: unique ID assigned by the AP during association
+ * @reserved1: alignment
* @data_policy: see &enum iwl_mac_data_policy
+ * @reserved2: alignment
* @ctwin: client traffic window in TU (period after TBTT when GO is present).
* 0 indicates that there is no CT window.
*/
struct iwl_mac_client_data {
- __le32 is_assoc;
- __le32 assoc_id;
- __le32 data_policy;
+ u8 is_assoc;
+ u8 esr_transition_timeout;
+ __le16 medium_sync_delay;
+
+ __le16 assoc_id;
+ __le16 reserved1;
+ __le16 data_policy;
+ __le16 reserved2;
__le32 ctwin;
-} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */
+} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_2 */
/**
* struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context
@@ -263,7 +296,7 @@ enum iwl_mac_config_filter_flags {
* ( MAC_CONTEXT_CONFIG_CMD = 0x8 )
*
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @mac_type: one of &enum iwl_mac_types
* @local_mld_addr: mld address
* @reserved_for_local_mld_addr: reserved
@@ -292,12 +325,12 @@ struct iwl_mac_config_cmd {
__le16 he_ap_support;
__le32 eht_support;
__le32 nic_not_ack_enabled;
- /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */
+ /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */
union {
struct iwl_mac_client_data client;
struct iwl_mac_p2p_dev_data p2p_dev;
};
-} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */
+} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */
/**
* enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being
@@ -390,7 +423,7 @@ enum iwl_link_ctx_flags {
* in MLD API
* ( LINK_CONFIG_CMD =0x9 )
*
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @link_id: the id of the link that this cmd configures
* @mac_id: interface ID. Relevant only if action is FW_CTXT_ACTION_ADD
* @phy_id: PHY index. Can be changed only if the link was inactive
@@ -430,6 +463,7 @@ enum iwl_link_ctx_flags {
* @reserved_for_ref_bssid_addr: reserved
* @bssid_index: index of the associated VAP
* @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame
+ * @spec_link_id: link_id as the AP knows it
* @reserved: alignment
* @ibss_bssid_addr: bssid for ibss
* @reserved_for_ibss_bssid_addr: reserved
@@ -469,7 +503,8 @@ struct iwl_link_config_cmd {
__le16 reserved_for_ref_bssid_addr;
u8 bssid_index;
u8 bss_color;
- u8 reserved[2];
+ u8 spec_link_id;
+ u8 reserved;
u8 ibss_bssid_addr[6];
__le16 reserved_for_ibss_bssid_addr;
__le32 reserved1[8];
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
index e3eda251c728..55882190251c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
@@ -295,7 +295,7 @@ struct iwl_ac_qos {
* struct iwl_mac_ctx_cmd - command structure to configure MAC contexts
* ( MAC_CONTEXT_CMD = 0x28 )
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @mac_type: one of &enum iwl_mac_types
* @tsf_id: TSF HW timer, one of &enum iwl_tsf_id
* @node_addr: MAC address
@@ -353,7 +353,7 @@ struct iwl_nonqos_seq_query_cmd {
} __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */
/**
- * struct iwl_missed_beacons_notif - information on missed beacons
+ * struct iwl_missed_beacons_notif_ver_3 - information on missed beacons
* ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
* @mac_id: interface ID
* @consec_missed_beacons_since_last_rx: number of consecutive missed
@@ -362,7 +362,7 @@ struct iwl_nonqos_seq_query_cmd {
* @num_expected_beacons: number of expected beacons
* @num_recvd_beacons: number of received beacons
*/
-struct iwl_missed_beacons_notif {
+struct iwl_missed_beacons_notif_ver_3 {
__le32 mac_id;
__le32 consec_missed_beacons_since_last_rx;
__le32 consec_missed_beacons;
@@ -371,6 +371,24 @@ struct iwl_missed_beacons_notif {
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
/**
+ * struct iwl_missed_beacons_notif - information on missed beacons
+ * ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
+ * @link_id: fw link ID
+ * @consec_missed_beacons_since_last_rx: number of consecutive missed
+ * beacons since last RX.
+ * @consec_missed_beacons: number of consecutive missed beacons
+ * @num_expected_beacons: number of expected beacons
+ * @num_recvd_beacons: number of received beacons
+ */
+struct iwl_missed_beacons_notif {
+ __le32 link_id;
+ __le32 consec_missed_beacons_since_last_rx;
+ __le32 consec_missed_beacons;
+ __le32 num_expected_beacons;
+ __le32 num_recvd_beacons;
+} __packed; /* MISSED_BEACON_NTFY_API_S_VER_4 */
+
+/**
* struct iwl_he_backoff_conf - used for backoff configuration
* Per each trigger-based AC, (set by MU EDCA Parameter set info-element)
* used for backoff configuration of TXF5..TXF8 trigger based.
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
index 91bfde6d5367..28bfabb399b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
@@ -17,7 +17,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_ACCESS_COMPLETE = 0x0,
/**
- * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd
+ * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd_v1,
+ * &struct iwl_lari_config_change_cmd_v2,
+ * &struct iwl_lari_config_change_cmd_v3,
+ * &struct iwl_lari_config_change_cmd_v4,
+ * &struct iwl_lari_config_change_cmd_v5 or
+ * &struct iwl_lari_config_change_cmd_v6
*/
LARI_CONFIG_CHANGE = 0x1,
@@ -29,12 +34,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
NVM_GET_INFO = 0x2,
/**
- * @TAS_CONFIG: &struct iwl_tas_config_cmd
+ * @TAS_CONFIG: &union iwl_tas_config_cmd
*/
TAS_CONFIG = 0x3,
/**
- * @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd
+ * @SAR_OFFSET_MAPPING_TABLE_CMD: &struct iwl_sar_offset_mapping_cmd
*/
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
@@ -317,7 +322,7 @@ struct iwl_mcc_update_resp_v3 {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */
/**
- * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD.
+ * struct iwl_mcc_update_resp_v4 - response to MCC_UPDATE_CMD.
* Contains the new channel control profile map, if changed, and the new MCC
* (mobile country code).
* The new MCC may be different than what was requested in MCC_UPDATE_CMD.
@@ -333,7 +338,7 @@ struct iwl_mcc_update_resp_v3 {
* @channels: channel control data map, DWORD for each channel. Only the first
* 16bits are used.
*/
-struct iwl_mcc_update_resp {
+struct iwl_mcc_update_resp_v4 {
__le32 status;
__le16 mcc;
__le16 cap;
@@ -346,6 +351,37 @@ struct iwl_mcc_update_resp {
} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_4 */
/**
+ * struct iwl_mcc_update_resp_v8 - response to MCC_UPDATE_CMD.
+ * Contains the new channel control profile map, if changed, and the new MCC
+ * (mobile country code).
+ * The new MCC may be different than what was requested in MCC_UPDATE_CMD.
+ * @status: see &enum iwl_mcc_update_status
+ * @mcc: the new applied MCC
+ * @padding: padding for 2 bytes.
+ * @cap: capabilities for all channels which matches the MCC
+ * @time: time elapsed from the MCC test start (in units of 30 seconds)
+ * @geo_info: geographic specific profile information
+ * see &enum iwl_geo_information.
+ * @source_id: the MCC source, see iwl_mcc_source
+ * @reserved: for four bytes alignment.
+ * @n_channels: number of channels in @channels_data.
+ * @channels: channel control data map, DWORD for each channel. Only the first
+ * 16bits are used.
+ */
+struct iwl_mcc_update_resp_v8 {
+ __le32 status;
+ __le16 mcc;
+ u8 padding[2];
+ __le32 cap;
+ __le16 time;
+ __le16 geo_info;
+ u8 source_id;
+ u8 reserved[3];
+ __le32 n_channels;
+ __le32 channels[];
+} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_8 */
+
+/**
* struct iwl_mcc_chub_notif - chub notifies of mcc change
* (MCC_CHUB_UPDATE_CMD = 0xc9)
* The Chub (Communication Hub, CommsHUB) is a HW component that connects to
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
index a0123f81f5d8..898bf351f6e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
@@ -28,7 +28,8 @@ enum iwl_prot_offload_subcmd_ids {
D3_END_NOTIFICATION = 0xFE,
/**
- * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif
+ * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or
+ * &struct iwl_stored_beacon_notif_v3
*/
STORED_BEACON_NTF = 0xFF,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
index 2f7d8558becd..8fe42cff1102 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -116,7 +116,7 @@ struct iwl_phy_context_cmd_tail {
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @apply_time: 0 means immediate apply and context switch.
* other value means apply new params after X usecs
* @tx_param_color: ???
@@ -138,7 +138,7 @@ struct iwl_phy_context_cmd_v1 {
* struct iwl_phy_context_cmd - config of the PHY context
* ( PHY_CONTEXT_CMD = 0x8 )
* @id_and_color: ID and color of the relevant Binding
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @lmac_id: the lmac id the phy context belongs to
* @ci: channel info
* @rxchain_info: ???
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
index b1b9c29859c1..5a3f30e5e06d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2019-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -29,12 +29,16 @@ enum iwl_phy_ops_subcmd_ids {
TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
/**
- * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd
+ * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd_v1,
+ * &struct iwl_geo_tx_power_profiles_cmd_v2,
+ * &struct iwl_geo_tx_power_profiles_cmd_v3,
+ * &struct iwl_geo_tx_power_profiles_cmd_v4 or
+ * &struct iwl_geo_tx_power_profiles_cmd_v5
*/
PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,
/**
- * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
+ * @PER_PLATFORM_ANT_GAIN_CMD: &union iwl_ppag_table_cmd
*/
PER_PLATFORM_ANT_GAIN_CMD = 0x07,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
index f92cac1da764..85d89f559f6c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h
@@ -537,7 +537,7 @@ union iwl_ppag_table_cmd {
struct iwl_sar_offset_mapping_cmd {
u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE]
[MCC_TO_SAR_OFFSET_TABLE_COL_SIZE];
- u16 reserved;
+ __le16 reserved;
} __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index c9a48fc5fac8..a1a272433b09 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -21,6 +21,7 @@
* @IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK: enable HE Dual Carrier Modulation
* for BPSK (MCS 0) with 2 spatial
* streams
+ * @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF
*/
enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0),
@@ -28,6 +29,7 @@ enum iwl_tlc_mng_cfg_flags {
IWL_TLC_MNG_CFG_FLAGS_HE_STBC_160MHZ_MSK = BIT(2),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3),
IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4),
+ IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6),
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
index fdd8b01f09e4..25e2e23dce3d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
@@ -292,7 +292,7 @@ enum iwl_rx_phy_he_data0 {
/* TSF overload low dword */
enum iwl_rx_phy_eht_data0 {
/* info type: EHT any */
- /* 1 bits reserved */
+ IWL_RX_PHY_DATA0_EHT_VALIDATE = BIT(0),
IWL_RX_PHY_DATA0_EHT_UPLINK = BIT(1),
IWL_RX_PHY_DATA0_EHT_BSS_COLOR_MASK = 0x000000fc,
IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK = 0x00000f00,
@@ -367,8 +367,8 @@ enum iwl_rx_phy_eht_data1 {
/* number of EHT-LTF symbols 0 - 1 EHT-LTF, 1 - 2 EHT-LTFs, 2 - 4 EHT-LTFs,
* 3 - 6 EHT-LTFs, 4 - 8 EHT-LTFs */
IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM = 0x000000e0,
- IWL_RX_PHY_DATA1_EHT_B0 = 0x00000100,
- IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC = 0x0000fe00,
+ IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0 = 0x00000100,
+ IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7 = 0x0000fe00,
};
/* goes into Metadata DW 7 */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
index ec96ba053a5c..93078f8cc08c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -727,8 +727,10 @@ enum iwl_umac_scan_general_params_flags2 {
* @iter_interval: interval between two scan iterations on one channel.
*/
struct iwl_scan_channel_cfg_umac {
+#define IWL_CHAN_CFG_FLAGS_BAND_POS 30
__le32 flags;
- /* Both versions are of the same size, so use a union without adjusting
+
+ /* All versions are of the same size, so use a union without adjusting
* the command size later
*/
union {
@@ -746,6 +748,12 @@ struct iwl_scan_channel_cfg_umac {
* SCAN_CHANNEL_CONFIG_API_S_VER_3
* SCAN_CHANNEL_CONFIG_API_S_VER_4
*/
+ struct {
+ u8 channel_num;
+ u8 psd_20;
+ u8 iter_count;
+ u8 iter_interval;
+ } v5; /* SCAN_CHANNEL_CONFIG_API_S_VER_5 */
};
} __packed;
@@ -982,7 +990,7 @@ struct iwl_scan_channel_params_v4 {
SCAN_CHANNEL_PARAMS_API_S_VER_5 */
/**
- * struct iwl_scan_channel_params_v6
+ * struct iwl_scan_channel_params_v7
* @flags: channel flags &enum iwl_scan_channel_flags
* @count: num of channels in scan request
* @n_aps_override: override the number of APs the FW uses to calculate dwell
@@ -992,7 +1000,7 @@ struct iwl_scan_channel_params_v4 {
* @channel_config: array of explicit channel configurations
* for 2.4Ghz and 5.2Ghz bands
*/
-struct iwl_scan_channel_params_v6 {
+struct iwl_scan_channel_params_v7 {
u8 flags;
u8 count;
u8 n_aps_override[2];
@@ -1003,7 +1011,8 @@ struct iwl_scan_channel_params_v6 {
* struct iwl_scan_general_params_v11
* @flags: &enum iwl_umac_scan_general_flags_v2
* @reserved: reserved for future
- * @scan_start_mac_id: report the scan start TSF time according to this mac TSF
+ * @scan_start_mac_or_link_id: report the scan start TSF time according to this
+ * mac (up to verion 11) or link (starting with version 12) TSF
* @active_dwell: dwell time for active scan per LMAC
* @adwell_default_2g: adaptive dwell default number of APs
* for 2.4GHz channel
@@ -1026,7 +1035,7 @@ struct iwl_scan_channel_params_v6 {
struct iwl_scan_general_params_v11 {
__le16 flags;
u8 reserved;
- u8 scan_start_mac_id;
+ u8 scan_start_mac_or_link_id;
u8 active_dwell[SCAN_TWO_LMACS];
u8 adwell_default_2g;
u8 adwell_default_5g;
@@ -1038,7 +1047,7 @@ struct iwl_scan_general_params_v11 {
__le32 scan_priority;
u8 passive_dwell[SCAN_TWO_LMACS];
u8 num_of_fragments[SCAN_TWO_LMACS];
-} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_11 and *_VER_10 */
+} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_12, *_VER_11 and *_VER_10 */
/**
* struct iwl_scan_periodic_parms_v1
@@ -1067,18 +1076,18 @@ struct iwl_scan_req_params_v12 {
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */
/**
- * struct iwl_scan_req_params_v15
+ * struct iwl_scan_req_params_v16
* @general_params: &struct iwl_scan_general_params_v11
- * @channel_params: &struct iwl_scan_channel_params_v6
+ * @channel_params: &struct iwl_scan_channel_params_v7
* @periodic_params: &struct iwl_scan_periodic_parms_v1
* @probe_params: &struct iwl_scan_probe_params_v4
*/
-struct iwl_scan_req_params_v15 {
+struct iwl_scan_req_params_v17 {
struct iwl_scan_general_params_v11 general_params;
- struct iwl_scan_channel_params_v6 channel_params;
+ struct iwl_scan_channel_params_v7 channel_params;
struct iwl_scan_periodic_parms_v1 periodic_params;
struct iwl_scan_probe_params_v4 probe_params;
-} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_15 and *_VER_14 */
+} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_17 - 14 */
/**
* struct iwl_scan_req_umac_v12
@@ -1093,16 +1102,16 @@ struct iwl_scan_req_umac_v12 {
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */
/**
- * struct iwl_scan_req_umac_v15
+ * struct iwl_scan_req_umac_v16
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
* @scan_params: scan parameters
*/
-struct iwl_scan_req_umac_v15 {
+struct iwl_scan_req_umac_v17 {
__le32 uid;
__le32 ooc_priority;
- struct iwl_scan_req_params_v15 scan_params;
-} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_15 and *_VER_14 */
+ struct iwl_scan_req_params_v17 scan_params;
+} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_17 - 14 */
/**
* struct iwl_umac_scan_abort
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
index 904cd78a9fa0..7cc706731d70 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -292,7 +292,7 @@ struct iwl_hs20_roc_req_tail {
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
- * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @action: action to perform, see &enum iwl_ctxt_action
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
@@ -377,7 +377,8 @@ enum iwl_mvm_session_prot_conf_id {
* struct iwl_mvm_session_prot_cmd - configure a session protection
* @id_and_color: the id and color of the mac for which this session protection
* is sent
- * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE
+ * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE,
+ * see &enum iwl_ctxt_action
* @conf_id: see &enum iwl_mvm_session_prot_conf_id
* @duration_tu: the duration of the whole protection in TUs.
* @repetition_count: not used
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
index 97edf5477ba7..842360b1e995 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_tx_h__
@@ -177,17 +177,6 @@ enum iwl_tx_offload_assist_flags_pos {
#define IWL_TX_CMD_OFFLD_MH_MASK 0x1f
#define IWL_TX_CMD_OFFLD_IP_HDR_MASK 0x3f
-enum iwl_tx_offload_assist_bz {
- IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS = 0x000003ff,
- IWL_TX_CMD_OFFLD_BZ_START_OFFS = 0x001ff800,
- IWL_TX_CMD_OFFLD_BZ_MH_LEN = 0x07c00000,
- IWL_TX_CMD_OFFLD_BZ_MH_PAD = 0x08000000,
- IWL_TX_CMD_OFFLD_BZ_AMSDU = 0x10000000,
- IWL_TX_CMD_OFFLD_BZ_ZERO2ONES = 0x20000000,
- IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM = 0x40000000,
- IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM = 0x80000000,
-};
-
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
* struct iwl_tx_cmd - TX command struct to FW
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index 55219974b92b..3ab6a68f1e9f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -1038,7 +1038,7 @@ iwl_dump_ini_prph_mac_iter(struct iwl_fw_runtime *fwrt,
range->range_data_size = reg->dev_addr.size;
for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
prph_val = iwl_read_prph(fwrt->trans, addr + i);
- if ((prph_val & ~0xf) == 0xa5a5a5a0)
+ if (iwl_trans_is_hw_error_value(prph_val))
return -EBUSY;
*val++ = cpu_to_le32(prph_val);
}
@@ -1562,7 +1562,7 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt,
prph_data = iwl_read_prph_no_grab(fwrt->trans, (i % 2) ?
DBGI_SRAM_TARGET_ACCESS_RDATA_MSB :
DBGI_SRAM_TARGET_ACCESS_RDATA_LSB);
- if ((prph_data & ~0xf) == 0xa5a5a5a0) {
+ if (iwl_trans_is_hw_error_value(prph_data)) {
iwl_trans_release_nic_access(fwrt->trans);
return -EBUSY;
}
@@ -2034,7 +2034,6 @@ static u32
iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt,
struct iwl_dump_ini_region_data *reg_data)
{
- u32 size = 0;
u32 ranges = 0;
u32 imr_enable = fwrt->trans->dbg.imr_data.imr_enable;
u32 imr_size = fwrt->trans->dbg.imr_data.imr_size;
@@ -2044,17 +2043,16 @@ iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt,
IWL_DEBUG_INFO(fwrt,
"WRT: Invalid imr data enable: %d, imr_size: %d, sram_size: %d\n",
imr_enable, imr_size, sram_size);
- return size;
+ return 0;
}
- size = imr_size;
ranges = iwl_dump_ini_imr_ranges(fwrt, reg_data);
- if (!size && !ranges) {
- IWL_ERR(fwrt, "WRT: imr_size :=%d, ranges :=%d\n", size, ranges);
+ if (!ranges) {
+ IWL_ERR(fwrt, "WRT: ranges :=%d\n", ranges);
return 0;
}
- size += sizeof(struct iwl_fw_ini_error_dump) +
+ imr_size += sizeof(struct iwl_fw_ini_error_dump) +
ranges * sizeof(struct iwl_fw_ini_error_dump_range);
- return size;
+ return imr_size;
}
/**
@@ -3156,6 +3154,51 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
return 0;
}
+int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt)
+{
+ struct iwl_mvm_marker marker = {
+ .dw_len = sizeof(struct iwl_mvm_marker) / 4,
+ .marker_id = MARKER_ID_SYNC_CLOCK,
+ };
+ struct iwl_host_cmd hcmd = {
+ .flags = CMD_ASYNC,
+ .id = WIDE_ID(LONG_GROUP, MARKER_CMD),
+ .dataflags = {},
+ };
+ struct iwl_mvm_marker_rsp *resp;
+ int cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw,
+ WIDE_ID(LONG_GROUP, MARKER_CMD),
+ IWL_FW_CMD_VER_UNKNOWN);
+ int ret;
+
+ if (cmd_ver == 1) {
+ /* the real timestamp is taken from the ftrace clock
+ * this is for finding the match between fw and kernel logs
+ */
+ marker.timestamp = cpu_to_le64(fwrt->timestamp.seq++);
+ } else if (cmd_ver == 2) {
+ marker.timestamp = cpu_to_le64(ktime_get_boottime_ns());
+ } else {
+ IWL_DEBUG_INFO(fwrt,
+ "Invalid version of Marker CMD. Ver = %d\n",
+ cmd_ver);
+ return -EINVAL;
+ }
+
+ hcmd.data[0] = &marker;
+ hcmd.len[0] = sizeof(marker);
+
+ ret = iwl_trans_send_cmd(fwrt->trans, &hcmd);
+
+ if (cmd_ver > 1 && hcmd.resp_pkt) {
+ resp = (void *)hcmd.resp_pkt->data;
+ IWL_DEBUG_INFO(fwrt, "FW GP2 time: %u\n",
+ le32_to_cpu(resp->gp2));
+ }
+
+ return ret;
+}
+
void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop)
@@ -3166,12 +3209,15 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
+ IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP)) {
+ if (stop)
+ iwl_fw_send_timestamp_marker_cmd(fwrt);
ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop);
- else if (stop)
+ } else if (stop) {
iwl_fw_dbg_stop_recording(fwrt->trans, params);
- else
+ } else {
ret = iwl_fw_dbg_restart_recording(fwrt->trans, params);
+ }
#ifdef CONFIG_IWLWIFI_DEBUGFS
if (!ret) {
if (stop)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
index be7806407de8..4227fbd2b977 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2019, 2021-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -227,6 +227,8 @@ static inline void iwl_fw_flush_dumps(struct iwl_fw_runtime *fwrt)
flush_delayed_work(&fwrt->dump.wks[i].wk);
}
+int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt);
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
{
@@ -327,4 +329,18 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt);
void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
u32 timepoint,
u32 timepoint_data);
+
+#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \
+ IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__)
+
+#define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \
+ ({ \
+ bool __cond = (_cond); \
+ \
+ if (unlikely(__cond)) \
+ IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \
+ \
+ unlikely(__cond); \
+ })
+
#endif /* __iwl_fw_dbg_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
index 607e07ed2477..3cdbc6ac7ae5 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c
@@ -123,28 +123,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
#define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \
FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
-static int iwl_fw_send_timestamp_marker_cmd(struct iwl_fw_runtime *fwrt)
-{
- struct iwl_mvm_marker marker = {
- .dw_len = sizeof(struct iwl_mvm_marker) / 4,
- .marker_id = MARKER_ID_SYNC_CLOCK,
-
- /* the real timestamp is taken from the ftrace clock
- * this is for finding the match between fw and kernel logs
- */
- .timestamp = cpu_to_le64(fwrt->timestamp.seq++),
- };
-
- struct iwl_host_cmd hcmd = {
- .id = MARKER_CMD,
- .flags = CMD_ASYNC,
- .data[0] = &marker,
- .len[0] = sizeof(marker),
- };
-
- return iwl_trans_send_cmd(fwrt->trans, &hcmd);
-}
-
static int iwl_dbgfs_enabled_severities_write(struct iwl_fw_runtime *fwrt,
char *buf, size_t count)
{
@@ -354,9 +332,18 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v)
const struct iwl_fw *fw = priv->fwrt->fw;
const struct iwl_fw_cmd_version *ver;
u32 cmd_id;
-
- if (!state->pos)
+ int has_capa;
+
+ if (!state->pos) {
+ seq_puts(seq, "fw_capa:\n");
+ has_capa = fw_has_capa(&fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT) ? 1 : 0;
+ seq_printf(seq,
+ " %d: %d\n",
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT,
+ has_capa);
seq_puts(seq, "fw_api_ver:\n");
+ }
ver = &fw->ucode_capa.cmd_versions[state->pos];
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
index f86f7b4baa18..5876f917e536 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -194,7 +194,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
/* check if there is a HW error */
val = iwl_trans_read_mem32(trans, base);
- if (((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50)) {
+ if (iwl_trans_is_hw_error_value(val)) {
int err;
IWL_ERR(trans, "HW error, resetting before reading\n");
@@ -467,6 +467,10 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt)
FSEQ_REG(CNVR_AUX_MISC_CHIP),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM),
FSEQ_REG(CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR),
+ FSEQ_REG(FSEQ_PREV_CNVIO_INIT_VERSION),
+ FSEQ_REG(FSEQ_WIFI_FSEQ_VERSION),
+ FSEQ_REG(FSEQ_BT_FSEQ_VERSION),
+ FSEQ_REG(FSEQ_CLASS_TP_VERSION),
};
if (!iwl_trans_grab_nic_access(trans))
@@ -507,11 +511,16 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt)
iwl_fwrt_dump_fseq_regs(fwrt);
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
pc_data = fwrt->trans->dbg.pc_data;
+
+ if (!iwl_trans_grab_nic_access(fwrt->trans))
+ return;
for (count = 0; count < fwrt->trans->dbg.num_pc;
count++, pc_data++)
IWL_ERR(fwrt, "%s: 0x%x\n",
pc_data->pc_name,
- pc_data->pc_address);
+ iwl_read_prph_no_grab(fwrt->trans,
+ pc_data->pc_address));
+ iwl_trans_release_nic_access(fwrt->trans);
}
if (fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h
index cddf09d6be1c..b36e9613a52c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/file.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h
@@ -323,6 +323,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t;
* is supported.
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used)
+ * @IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG: supports fragmented PNVM image
* @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting
* stabilization latency for SoCs.
* @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
@@ -398,6 +399,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
/* set 1 */
+ IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG = (__force iwl_ucode_tlv_capa_t)32,
IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37,
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
@@ -462,6 +464,10 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109,
IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT = (__force iwl_ucode_tlv_capa_t)110,
IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111,
+ IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT = (__force iwl_ucode_tlv_capa_t)112,
+ IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT = (__force iwl_ucode_tlv_capa_t)113,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT = (__force iwl_ucode_tlv_capa_t)114,
+ IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT = (__force iwl_ucode_tlv_capa_t)116,
#ifdef __CHECKER__
/* sparse says it cannot increment the previous enum member */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
index c6f2672fdc73..650e4bde9c17 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright(c) 2020-2022 Intel Corporation
+ * Copyright(c) 2020-2023 Intel Corporation
*/
#include "iwl-drv.h"
@@ -31,18 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
}
static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
- size_t len)
+ size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
u32 sha1 = 0;
u16 mac_type = 0, rf_id = 0;
- u8 *pnvm_data = NULL, *tmp;
bool hw_match = false;
- u32 size = 0;
- int ret;
IWL_DEBUG_FW(trans, "Handling PNVM section\n");
+ memset(pnvm_data, 0, sizeof(*pnvm_data));
+
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
@@ -55,8 +55,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
data += sizeof(*tlv);
@@ -75,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
IWL_DEBUG_FW(trans,
"Got IWL_UCODE_TLV_PNVM_VERSION %0x\n",
sha1);
+ pnvm_data->version = sha1;
break;
case IWL_UCODE_TLV_HW_TYPE:
if (tlv_len < 2 * sizeof(__le16)) {
@@ -112,26 +112,26 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
break;
}
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
- data_len);
-
- tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL);
- if (!tmp) {
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
IWL_DEBUG_FW(trans,
- "Couldn't allocate (more) pnvm_data\n");
-
- ret = -ENOMEM;
- goto out;
+ "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
}
- pnvm_data = tmp;
-
- memcpy(pnvm_data + size, section->data, data_len);
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n",
+ data_len);
- size += data_len;
+ pnvm_data->chunks[pnvm_data->n_chunks].data = section->data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
+ pnvm_data->n_chunks++;
break;
}
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
+ return -EINVAL;
+ break;
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New PNVM section started, stop parsing.\n");
@@ -152,26 +152,20 @@ done:
"HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
CSR_HW_REV_TYPE(trans->hw_rev),
CSR_HW_RFID_TYPE(trans->hw_rf_id));
- ret = -ENOENT;
- goto out;
+ return -ENOENT;
}
- if (!size) {
+ if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
- ret = -ENOENT;
- goto out;
+ return -ENOENT;
}
- IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
-
- ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
-out:
- kfree(pnvm_data);
- return ret;
+ return 0;
}
static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
- size_t len)
+ size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
@@ -212,7 +206,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data,
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
int ret;
- ret = iwl_pnvm_handle_section(trans, data, len);
+ ret = iwl_pnvm_handle_section(trans, data, len,
+ pnvm_data);
if (!ret)
return 0;
} else {
@@ -255,89 +250,136 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len)
return 0;
}
-int iwl_pnvm_load(struct iwl_trans *trans,
- struct iwl_notif_wait_data *notif_wait)
+static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
{
- u8 *data;
- size_t len;
struct pnvm_sku_package *package;
- struct iwl_notification_wait pnvm_wait;
- static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
- PNVM_INIT_COMPLETE_NTFY) };
- int ret;
-
- /* if the SKU_ID is empty, there's nothing to do */
- if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
- return 0;
-
- /*
- * If we already loaded (or tried to load) it before, we just
- * need to set it again.
- */
- if (trans->pnvm_loaded) {
- ret = iwl_trans_set_pnvm(trans, NULL, 0);
- if (ret)
- return ret;
- goto skip_parse;
- }
+ u8 *image = NULL;
/* First attempt to get the PNVM from BIOS */
- package = iwl_uefi_get_pnvm(trans, &len);
+ package = iwl_uefi_get_pnvm(trans_p, len);
if (!IS_ERR_OR_NULL(package)) {
- if (len >= sizeof(*package)) {
+ if (*len >= sizeof(*package)) {
/* we need only the data */
- len -= sizeof(*package);
- data = kmemdup(package->data, len, GFP_KERNEL);
- } else {
- data = NULL;
+ *len -= sizeof(*package);
+ image = kmemdup(package->data, *len, GFP_KERNEL);
}
-
/* free package regardless of whether kmemdup succeeded */
kfree(package);
-
- if (data)
- goto parse;
+ if (image)
+ return image;
}
/* If it's not available, try from the filesystem */
- ret = iwl_pnvm_get_from_fs(trans, &data, &len);
+ if (iwl_pnvm_get_from_fs(trans_p, &image, len))
+ return NULL;
+ return image;
+}
+
+static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_pnvm_image *pnvm_data = NULL;
+ u8 *data = NULL;
+ size_t length;
+ int ret;
+
+ /* failed to get/parse the image in the past, no use trying again */
+ if (trans->fail_to_parse_pnvm_image)
+ return;
+
+ if (trans->pnvm_loaded)
+ goto set;
+
+ data = iwl_get_pnvm_image(trans, &length);
+ if (!data) {
+ trans->fail_to_parse_pnvm_image = true;
+ return;
+ }
+
+ pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
+ if (!pnvm_data)
+ goto free;
+
+ ret = iwl_pnvm_parse(trans, data, length, pnvm_data);
if (ret) {
- /*
- * Pretend we've loaded it - at least we've tried and
- * couldn't load it at all, so there's no point in
- * trying again over and over.
- */
- trans->pnvm_loaded = true;
-
- goto skip_parse;
+ trans->fail_to_parse_pnvm_image = true;
+ goto free;
}
-parse:
- iwl_pnvm_parse(trans, data, len);
+ ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
+ if (ret)
+ goto free;
+ IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);
+set:
+ iwl_trans_set_pnvm(trans, capa);
+free:
kfree(data);
+ kfree(pnvm_data);
+}
-skip_parse:
- /* now try to get the reduce power table, if not loaded yet */
- if (!trans->reduce_power_loaded) {
- data = iwl_uefi_get_reduced_power(trans, &len);
- if (IS_ERR_OR_NULL(data)) {
- /*
- * Pretend we've loaded it - at least we've tried and
- * couldn't load it at all, so there's no point in
- * trying again over and over.
- */
- trans->reduce_power_loaded = true;
- } else {
- ret = iwl_trans_set_reduce_power(trans, data, len);
- if (ret)
- IWL_DEBUG_FW(trans,
- "Failed to set reduce power table %d\n",
- ret);
- kfree(data);
- }
+static void
+iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_pnvm_image *pnvm_data = NULL;
+ u8 *data = NULL;
+ size_t length;
+ int ret;
+
+ if (trans->failed_to_load_reduce_power_image)
+ return;
+
+ if (trans->reduce_power_loaded)
+ goto set;
+
+ data = iwl_uefi_get_reduced_power(trans, &length);
+ if (IS_ERR(data)) {
+ trans->failed_to_load_reduce_power_image = true;
+ return;
}
+ pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
+ if (!pnvm_data)
+ goto free;
+
+ ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data);
+ if (ret) {
+ trans->failed_to_load_reduce_power_image = true;
+ goto free;
+ }
+
+ ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa);
+ if (ret) {
+ IWL_DEBUG_FW(trans,
+ "Failed to load reduce power table %d\n",
+ ret);
+ trans->failed_to_load_reduce_power_image = true;
+ goto free;
+ }
+
+set:
+ iwl_trans_set_reduce_power(trans, capa);
+free:
+ kfree(data);
+ kfree(pnvm_data);
+}
+
+int iwl_pnvm_load(struct iwl_trans *trans,
+ struct iwl_notif_wait_data *notif_wait,
+ const struct iwl_ucode_capabilities *capa)
+{
+ struct iwl_notification_wait pnvm_wait;
+ static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
+ PNVM_INIT_COMPLETE_NTFY) };
+
+ /* if the SKU_ID is empty, there's nothing to do */
+ if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
+ return 0;
+
+ iwl_pnvm_load_pnvm_to_trans(trans, capa);
+ iwl_pnvm_load_reduce_power_to_trans(trans, capa);
+
iwl_init_notification_wait(notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, trans);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
index 203c367dd4de..1bac3466154c 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
@@ -1,13 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/******************************************************************************
- *
- * Copyright(c) 2020-2021 Intel Corporation
- *
- *****************************************************************************/
-
+/*
+ * Copyright(c) 2020-2023 Intel Corporation
+ */
#ifndef __IWL_PNVM_H__
#define __IWL_PNVM_H__
+#include "iwl-drv.h"
#include "fw/notif-wait.h"
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
@@ -15,24 +13,17 @@
#define MAX_PNVM_NAME 64
int iwl_pnvm_load(struct iwl_trans *trans,
- struct iwl_notif_wait_data *notif_wait);
+ struct iwl_notif_wait_data *notif_wait,
+ const struct iwl_ucode_capabilities *capa);
static inline
void iwl_pnvm_get_fs_name(struct iwl_trans *trans,
u8 *pnvm_name, size_t max_len)
{
- int pre_len;
-
- /*
- * The prefix unfortunately includes a hyphen at the end, so
- * don't add the dot here...
- */
- snprintf(pnvm_name, max_len, "%spnvm", trans->cfg->fw_name_pre);
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
- /* ...but replace the hyphen with the dot here. */
- pre_len = strlen(trans->cfg->fw_name_pre);
- if (pre_len < max_len && pre_len > 0)
- pnvm_name[pre_len - 1] = '.';
+ snprintf(pnvm_name, max_len, "%s.pnvm",
+ iwl_drv_get_fwname_pre(trans, _fw_name_pre));
}
#endif /* __IWL_PNVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index df689a9b7e2c..702586945533 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __iwl_fw_runtime_h__
#define __iwl_fw_runtime_h__
@@ -146,12 +146,14 @@ struct iwl_fw_runtime {
u32 umac_minor;
} fw_ver;
} dump;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
struct {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
struct delayed_work wk;
u32 delay;
+#endif
u64 seq;
} timestamp;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
bool tpc_enabled;
#endif /* CONFIG_IWLWIFI_DEBUGFS */
#ifdef CONFIG_ACPI
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
index 01afea33c38c..9877988db0d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
*/
#include "iwl-drv.h"
@@ -17,52 +17,109 @@
0xb2, 0xec, 0xf5, 0xa3, \
0x59, 0x4f, 0x4a, 0xea)
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+struct iwl_uefi_pnvm_mem_desc {
+ __le32 addr;
+ __le32 size;
+ const u8 data[];
+} __packed;
+
+static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *data_size)
{
- void *data;
- unsigned long package_size;
efi_status_t status;
+ void *data;
- *len = 0;
+ if (!data_size)
+ return ERR_PTR(-EINVAL);
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
return ERR_PTR(-ENODEV);
- /*
- * TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_PNVM_SIZE;
+ /* first call with NULL data to get the exact entry size */
+ *data_size = 0;
+ status = efi.get_variable(name, guid, NULL, data_size, NULL);
+ if (status != EFI_BUFFER_TOO_SMALL || !*data_size)
+ return ERR_PTR(-EIO);
- data = kmalloc(package_size, GFP_KERNEL);
+ data = kmalloc(*data_size, GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
- status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
+ status = efi.get_variable(name, guid, NULL, data_size, data);
if (status != EFI_SUCCESS) {
- IWL_DEBUG_FW(trans,
- "PNVM UEFI variable not found 0x%lx (len %lu)\n",
- status, package_size);
kfree(data);
return ERR_PTR(-ENOENT);
}
+ return data;
+}
+
+void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+{
+ unsigned long package_size;
+ void *data;
+
+ *len = 0;
+
+ data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "PNVM UEFI variable not found 0x%lx (len %lu)\n",
+ PTR_ERR(data), package_size);
+ return data;
+ }
+
IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size);
*len = package_size;
return data;
}
-static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
- const u8 *data, size_t len)
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
+{
+ const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data;
+ u32 data_len;
+
+ if (tlv_len < sizeof(*desc)) {
+ IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len);
+ return -EINVAL;
+ }
+
+ data_len = tlv_len - sizeof(*desc);
+
+ IWL_DEBUG_FW(trans,
+ "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n",
+ tlv_len, data_len);
+
+ if (le32_to_cpu(desc->size) != data_len) {
+ IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size);
+ return -EINVAL;
+ }
+
+ if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
+ IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n");
+ return -EINVAL;
+ }
+
+ IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len);
+
+ pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data;
+ pnvm_data->chunks[pnvm_data->n_chunks].len = data_len;
+ pnvm_data->n_chunks++;
+
+ return 0;
+}
+
+static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
- u8 *reduce_power_data = NULL, *tmp;
- u32 size = 0;
IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n");
+ memset(pnvm_data, 0, sizeof(*pnvm_data));
while (len >= sizeof(*tlv)) {
u32 tlv_len, tlv_type;
@@ -76,39 +133,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-EINVAL);
- goto out;
+ return -EINVAL;
}
data += sizeof(*tlv);
switch (tlv_type) {
- case IWL_UCODE_TLV_MEM_DESC: {
- IWL_DEBUG_FW(trans,
- "Got IWL_UCODE_TLV_MEM_DESC len %d\n",
- tlv_len);
-
- IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);
-
- tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
- if (!tmp) {
- IWL_DEBUG_FW(trans,
- "Couldn't allocate (more) reduce_power_data\n");
-
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOMEM);
- goto out;
- }
-
- reduce_power_data = tmp;
-
- memcpy(reduce_power_data + size, data, tlv_len);
-
- size += tlv_len;
-
+ case IWL_UCODE_TLV_MEM_DESC:
+ if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len,
+ pnvm_data))
+ return -EINVAL;
break;
- }
case IWL_UCODE_TLV_PNVM_SKU:
IWL_DEBUG_FW(trans,
"New REDUCE_POWER section started, stop parsing.\n");
@@ -124,27 +159,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
}
done:
- if (!size) {
+ if (!pnvm_data->n_chunks) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
- /* Better safe than sorry, but 'reduce_power_data' should
- * always be NULL if !size.
- */
- kfree(reduce_power_data);
- reduce_power_data = ERR_PTR(-ENOENT);
- goto out;
+ return -ENOENT;
}
-
- IWL_INFO(trans, "loaded REDUCE_POWER\n");
-
-out:
- return reduce_power_data;
+ return 0;
}
-static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
- const u8 *data, size_t len)
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
{
const struct iwl_ucode_tlv *tlv;
- void *sec_data;
IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");
@@ -160,7 +186,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
@@ -181,11 +207,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
- sec_data = iwl_uefi_reduce_power_section(trans,
- data,
- len);
- if (!IS_ERR(sec_data))
- return sec_data;
+ int ret = iwl_uefi_reduce_power_section(trans,
+ data, len,
+ pnvm_data);
+ if (!ret)
+ return 0;
} else {
IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
}
@@ -195,51 +221,45 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
}
}
- return ERR_PTR(-ENOENT);
+ return -ENOENT;
}
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
struct pnvm_sku_package *package;
- void *data = NULL;
unsigned long package_size;
- efi_status_t status;
+ u8 *data;
- *len = 0;
+ package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME,
+ &IWL_EFI_VAR_GUID, &package_size);
- if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
- return ERR_PTR(-ENODEV);
-
- /*
- * TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_REDUCE_POWER_SIZE;
-
- package = kmalloc(package_size, GFP_KERNEL);
- if (!package)
- return ERR_PTR(-ENOMEM);
-
- status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, package);
- if (status != EFI_SUCCESS) {
+ if (IS_ERR(package)) {
IWL_DEBUG_FW(trans,
"Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
- status, package_size);
+ PTR_ERR(package), package_size);
+ return ERR_CAST(package);
+ }
+
+ if (package_size < sizeof(*package)) {
+ IWL_DEBUG_FW(trans,
+ "Invalid Reduced Power UEFI variable len (%lu)\n",
+ package_size);
kfree(package);
- return ERR_PTR(-ENOENT);
+ return ERR_PTR(-EINVAL);
}
IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
package_size);
- *len = package_size;
IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
package->rev, package->total_size, package->n_skus);
- data = iwl_uefi_reduce_power_parse(trans, package->data,
- *len - sizeof(*package));
+ *len = package_size - sizeof(*package);
+ data = kmemdup(package->data, *len, GFP_KERNEL);
+ if (!data) {
+ kfree(package);
+ return ERR_PTR(-ENOMEM);
+ }
kfree(package);
@@ -264,31 +284,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
{
struct uefi_cnv_common_step_data *data;
unsigned long package_size;
- efi_status_t status;
int ret;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return;
- if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
- return;
+ data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
- /* TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_STEP_SIZE;
-
- data = kmalloc(package_size, GFP_KERNEL);
- if (!data)
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "STEP UEFI variable not found 0x%lx\n",
+ PTR_ERR(data));
return;
+ }
- status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
- if (status != EFI_SUCCESS) {
+ if (package_size < sizeof(*data)) {
IWL_DEBUG_FW(trans,
- "STEP UEFI variable not found 0x%lx\n", status);
- goto out_free;
+ "Invalid STEP table UEFI variable len (%lu)\n",
+ package_size);
+ kfree(data);
+ return;
}
IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n",
@@ -298,7 +314,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans)
if (ret < 0)
IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n");
-out_free:
kfree(data);
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table);
@@ -341,29 +356,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
{
struct uefi_cnv_wlan_sgom_data *data;
unsigned long package_size;
- efi_status_t status;
int ret;
- if (!fwrt->geo_enabled ||
- !efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
+ if (!fwrt->geo_enabled)
return;
- /* TODO: we hardcode a maximum length here, because reading
- * from the UEFI is not working. To implement this properly,
- * we have to call efivar_entry_size().
- */
- package_size = IWL_HARDCODED_SGOM_SIZE;
-
- data = kmalloc(package_size, GFP_KERNEL);
- if (!data)
+ data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
+ &package_size);
+ if (IS_ERR(data)) {
+ IWL_DEBUG_FW(trans,
+ "SGOM UEFI variable not found 0x%lx\n",
+ PTR_ERR(data));
return;
+ }
- status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID,
- NULL, &package_size, data);
- if (status != EFI_SUCCESS) {
+ if (package_size < sizeof(*data)) {
IWL_DEBUG_FW(trans,
- "SGOM UEFI variable not found 0x%lx\n", status);
- goto out_free;
+ "Invalid SGOM table UEFI variable len (%lu)\n",
+ package_size);
+ kfree(data);
+ return;
}
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
@@ -373,9 +385,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
if (ret < 0)
IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n");
-out_free:
kfree(data);
-
}
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
#endif /* CONFIG_ACPI */
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
index 17089bc74cf9..1369cc4855c3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright(c) 2021-2022 Intel Corporation
+ * Copyright(c) 2021-2023 Intel Corporation
*/
#ifndef __iwl_fw_uefi__
#define __iwl_fw_uefi__
@@ -10,16 +10,7 @@
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
#define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP"
-/*
- * TODO: we have these hardcoded values that the caller must pass,
- * because reading from the UEFI is not working. To implement this
- * properly, we have to change iwl_pnvm_get_from_uefi() to call
- * efivar_entry_size() and return the value to the caller instead.
- */
-#define IWL_HARDCODED_PNVM_SIZE 4096
-#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
-#define IWL_HARDCODED_SGOM_SIZE 339
-#define IWL_HARDCODED_STEP_SIZE 6
+#define IWL_SGOM_MAP_SIZE 339
struct pnvm_sku_package {
u8 rev;
@@ -31,7 +22,7 @@ struct pnvm_sku_package {
struct uefi_cnv_wlan_sgom_data {
u8 revision;
- u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1];
+ u8 offset_map[IWL_SGOM_MAP_SIZE - 1];
} __packed;
struct uefi_cnv_common_step_data {
@@ -50,24 +41,42 @@ struct uefi_cnv_common_step_data {
*/
#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
+int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
+int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data);
#else /* CONFIG_EFI */
-static inline
-void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
+static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
-static inline
-void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
+static inline int
+iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
+ const u8 *data, size_t len,
+ struct iwl_pnvm_image *pnvm_data)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline u8 *
+iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
{
return ERR_PTR(-EOPNOTSUPP);
}
-static inline
-void iwl_uefi_get_step_table(struct iwl_trans *trans)
+static inline void iwl_uefi_get_step_table(struct iwl_trans *trans)
+{
+}
+
+static inline int
+iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
+ u32 tlv_len, struct iwl_pnvm_image *pnvm_data)
{
+ return 0;
}
#endif /* CONFIG_EFI */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 411b7d4fcc9a..241a9e3f2a1a 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2005-2014, 2018-2021 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __IWL_CONFIG_H__
#define __IWL_CONFIG_H__
@@ -34,6 +35,7 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_22000,
IWL_DEVICE_FAMILY_AX210,
IWL_DEVICE_FAMILY_BZ,
+ IWL_DEVICE_FAMILY_SC,
};
/*
@@ -254,7 +256,6 @@ enum iwl_cfg_trans_ltr_delay {
* @xtal_latency: power up latency to get the xtal stabilized
* @extra_phy_cfg_flags: extra configuration flags to pass to the PHY
* @rf_id: need to read rf_id to determine the firmware image
- * @use_tfh: use TFH
* @gen2: 22000 and on transport operation
* @mq_rx_supported: multi-queue rx support
* @integrated: discrete or integrated
@@ -269,7 +270,6 @@ struct iwl_cfg_trans_params {
u32 xtal_latency;
u32 extra_phy_cfg_flags;
u32 rf_id:1,
- use_tfh:1,
gen2:1,
mq_rx_supported:1,
integrated:1,
@@ -307,7 +307,9 @@ struct iwl_fw_mon_regs {
* @name: Official name of the device
* @fw_name_pre: Firmware filename prefix. The api version and extension
* (.ucode) will be added to filename before loading from disk. The
- * filename is constructed as fw_name_pre<api>.ucode.
+ * filename is constructed as <fw_name_pre>-<api>.ucode.
+ * @fw_name_mac: MAC name for this config, the remaining pieces of the
+ * name will be generated dynamically
* @ucode_api_max: Highest version of uCode API supported by driver.
* @ucode_api_min: Lowest version of uCode API supported by driver.
* @max_inst_size: The maximal length of the fw inst section (only DVM)
@@ -361,6 +363,7 @@ struct iwl_cfg {
/* params specific to an individual device within a device family */
const char *name;
const char *fw_name_pre;
+ const char *fw_name_mac;
/* params likely to change within a device family */
const struct iwl_ht_params *ht_params;
const struct iwl_eeprom_params *eeprom_params;
@@ -388,7 +391,6 @@ struct iwl_cfg {
high_temp:1,
mac_addr_from_csr:10,
lp_xtal_workaround:1,
- disable_dummy_notification:1,
apmg_not_supported:1,
vht_mu_mimo_supported:1,
cdb:1,
@@ -416,17 +418,15 @@ struct iwl_cfg {
#define IWL_CFG_ANY (~0)
#define IWL_CFG_MAC_TYPE_PU 0x31
-#define IWL_CFG_MAC_TYPE_PNJ 0x32
#define IWL_CFG_MAC_TYPE_TH 0x32
#define IWL_CFG_MAC_TYPE_QU 0x33
#define IWL_CFG_MAC_TYPE_QUZ 0x35
-#define IWL_CFG_MAC_TYPE_QNJ 0x36
#define IWL_CFG_MAC_TYPE_SO 0x37
-#define IWL_CFG_MAC_TYPE_SNJ 0x42
#define IWL_CFG_MAC_TYPE_SOF 0x43
#define IWL_CFG_MAC_TYPE_MA 0x44
#define IWL_CFG_MAC_TYPE_BZ 0x46
#define IWL_CFG_MAC_TYPE_GL 0x47
+#define IWL_CFG_MAC_TYPE_SC 0x48
#define IWL_CFG_RF_TYPE_TH 0x105
#define IWL_CFG_RF_TYPE_TH1 0x108
@@ -438,6 +438,7 @@ struct iwl_cfg {
#define IWL_CFG_RF_TYPE_MR 0x110
#define IWL_CFG_RF_TYPE_MS 0x111
#define IWL_CFG_RF_TYPE_FM 0x112
+#define IWL_CFG_RF_TYPE_WH 0x113
#define IWL_CFG_RF_ID_TH 0x1
#define IWL_CFG_RF_ID_TH1 0x1
@@ -486,17 +487,16 @@ extern const struct iwl_cfg_trans_params iwl9000_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl9560_shared_clk_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_qnj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_ax200_trans_cfg;
-extern const struct iwl_cfg_trans_params iwl_snj_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_long_latency_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_so_long_latency_imr_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_ma_trans_cfg;
extern const struct iwl_cfg_trans_params iwl_bz_trans_cfg;
+extern const struct iwl_cfg_trans_params iwl_sc_trans_cfg;
extern const char iwl9162_name[];
extern const char iwl9260_name[];
extern const char iwl9260_1_name[];
@@ -535,6 +535,7 @@ extern const char iwl_ax221_name[];
extern const char iwl_ax231_name[];
extern const char iwl_ax411_name[];
extern const char iwl_bz_name[];
+extern const char iwl_sc_name[];
#if IS_ENABLED(CONFIG_IWLDVM)
extern const struct iwl_cfg iwl5300_agn_cfg;
extern const struct iwl_cfg iwl5100_agn_cfg;
@@ -580,6 +581,7 @@ extern const struct iwl_cfg iwl105_bgn_d_cfg;
extern const struct iwl_cfg iwl135_bgn_cfg;
#endif /* CONFIG_IWLDVM */
#if IS_ENABLED(CONFIG_IWLMVM)
+extern const struct iwl_ht_params iwl_22000_ht_params;
extern const struct iwl_cfg iwl7260_2ac_cfg;
extern const struct iwl_cfg iwl7260_2ac_cfg_high_temp;
extern const struct iwl_cfg iwl7260_2n_cfg;
@@ -604,7 +606,6 @@ extern const struct iwl_cfg iwl9260_2ac_cfg;
extern const struct iwl_cfg iwl9560_qu_b0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg;
-extern const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg;
extern const struct iwl_cfg iwl9560_2ac_cfg_soc;
extern const struct iwl_cfg iwl_qu_b0_hr1_b0;
extern const struct iwl_cfg iwl_qu_c0_hr1_b0;
@@ -623,57 +624,23 @@ extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
extern const struct iwl_cfg killer1650x_2ax_cfg;
extern const struct iwl_cfg killer1650w_2ax_cfg;
-extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg;
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0;
extern const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long;
-extern const struct iwl_cfg iwlax411_2ax_cfg_sosnj_gf4_a0;
-extern const struct iwl_cfg iwlax211_cfg_snj_gf_a0;
-extern const struct iwl_cfg iwl_cfg_snj_hr_b0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_jf_b0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_ms_a0;
-extern const struct iwl_cfg iwl_cfg_ma_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_ma_b0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_snj_a0_ms_a0;
+
+extern const struct iwl_cfg iwl_cfg_ma;
+
extern const struct iwl_cfg iwl_cfg_so_a0_hr_a0;
extern const struct iwl_cfg iwl_cfg_so_a0_ms_a0;
extern const struct iwl_cfg iwl_cfg_quz_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_a0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bz_a0_fm4_b0;
-extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_gl_b0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_fm_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_fm4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_gf_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_gf4_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_a0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_a0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_hr_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0;
-extern const struct iwl_cfg iwl_cfg_bnj_b0_fm4_b0;
+
+extern const struct iwl_cfg iwl_cfg_bz;
+extern const struct iwl_cfg iwl_cfg_gl;
+
+extern const struct iwl_cfg iwl_cfg_sc;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
index 3f7278014009..96bf353469b8 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
@@ -13,6 +13,8 @@
#define CSR_IML_SIZE_ADDR 0x128
#define CSR_IML_RESP_ADDR 0x12c
+#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2
+
/* Set bit for enabling automatic function boot */
#define CSR_AUTO_FUNC_BOOT_ENA BIT(1)
/* Set bit for initiating function boot */
@@ -96,9 +98,9 @@ struct iwl_prph_scratch_control {
} __packed; /* PERIPH_SCRATCH_CONTROL_S */
/*
- * struct iwl_prph_scratch_pnvm_cfg - ror config
+ * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch
* @pnvm_base_addr: PNVM start address
- * @pnvm_size: PNVM size in DWs
+ * @pnvm_size: the size of the PNVM image in bytes
* @reserved: reserved
*/
struct iwl_prph_scratch_pnvm_cfg {
@@ -107,6 +109,14 @@ struct iwl_prph_scratch_pnvm_cfg {
__le32 reserved;
} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */
+/**
+ * struct iwl_prph_scrath_mem_desc_addr_array
+ * @mem_descs: array of dram addresses.
+ * Each address is the beggining of a pnvm payload.
+ */
+struct iwl_prph_scrath_mem_desc_addr_array {
+ __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */
/*
* struct iwl_prph_scratch_hwm_cfg - hwm config
* @hwm_base_addr: hwm start address
@@ -132,7 +142,7 @@ struct iwl_prph_scratch_rbd_cfg {
/*
* struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table
* @base_addr: reduce power table address
- * @size: table size in dwords
+ * @size: the size of the entire power table image
*/
struct iwl_prph_scratch_uefi_cfg {
__le64 base_addr;
@@ -277,10 +287,18 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans,
const struct fw_img *fw);
void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive);
-int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len);
-int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len);
+int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa);
+void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+int
+iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa);
+void
+iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
u32 mbx_addr_0_step, u32 mbx_addr_1_step);
#endif /* __iwl_context_info_file_gen3_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
index 4354d5acac9f..1a1321db137c 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2020, 2022 Intel Corporation
*/
#ifndef __iwl_context_info_file_h__
#define __iwl_context_info_file_h__
@@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
int iwl_pcie_init_fw_sec(struct iwl_trans *trans,
const struct fw_img *fw,
struct iwl_context_info_dram *ctxt_dram);
+void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
+ size_t size,
+ dma_addr_t *phys);
int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
const void *data, u32 len,
struct iwl_dram_data *dram);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
index 898d5dcf1012..ef5baee6c9c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include <linux/firmware.h>
#include "iwl-drv.h"
@@ -586,8 +586,14 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt,
fw_mon_cfg = &fwrt->trans->dbg.fw_mon_cfg[alloc_id];
fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
- if (fw_mon->num_frags ||
- fw_mon_cfg->buf_location !=
+ if (fw_mon->num_frags) {
+ for (i = 0; i < fw_mon->num_frags; i++)
+ memset(fw_mon->frags[i].block, 0,
+ fw_mon->frags[i].size);
+ return 0;
+ }
+
+ if (fw_mon_cfg->buf_location !=
cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH))
return 0;
@@ -738,7 +744,8 @@ static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt,
if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
IWL_FW_INI_LOCATION_DRAM_PATH) {
- IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id);
+ IWL_DEBUG_FW(fwrt, "WRT: alloc_id %u location is not in DRAM_PATH\n",
+ alloc_id);
return -1;
}
@@ -794,11 +801,14 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
return;
- dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
- dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
+ memset(dram_info, 0, sizeof(*dram_info));
for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1;
i < IWL_FW_INI_ALLOCATION_NUM; i++) {
+ if (fwrt->trans->dbg.fw_mon_cfg[i].buf_location ==
+ IWL_FW_INI_LOCATION_INVALID)
+ continue;
+
ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info);
if (!ret)
dram_alloc = true;
@@ -808,11 +818,10 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
i, ret);
}
- if (dram_alloc)
- IWL_DEBUG_FW(fwrt, "block data after %08x\n",
- dram_info->first_word);
- else
- memset(frags->block, 0, sizeof(*dram_info));
+ if (dram_alloc) {
+ dram_info->first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
+ dram_info->second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
+ }
}
static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
@@ -1269,18 +1278,23 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
int ret, i;
u32 failed_alloc = 0;
- if (*ini_dest != IWL_FW_INI_LOCATION_INVALID)
- return;
-
- IWL_DEBUG_FW(fwrt,
- "WRT: Generating active triggers list, domain 0x%x\n",
- fwrt->trans->dbg.domains_bitmap);
+ if (*ini_dest == IWL_FW_INI_LOCATION_INVALID) {
+ IWL_DEBUG_FW(fwrt,
+ "WRT: Generating active triggers list, domain 0x%x\n",
+ fwrt->trans->dbg.domains_bitmap);
- for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) {
- struct iwl_dbg_tlv_time_point_data *tp =
- &fwrt->trans->dbg.time_point[i];
+ for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.time_point); i++) {
+ struct iwl_dbg_tlv_time_point_data *tp =
+ &fwrt->trans->dbg.time_point[i];
- iwl_dbg_tlv_gen_active_trig_list(fwrt, tp);
+ iwl_dbg_tlv_gen_active_trig_list(fwrt, tp);
+ }
+ } else if (*ini_dest != IWL_FW_INI_LOCATION_DRAM_PATH) {
+ /* For DRAM, go through the loop below to clear all the buffers
+ * properly on restart, otherwise garbage may be left there and
+ * leak into new debug dumps.
+ */
+ return;
}
*ini_dest = IWL_FW_INI_LOCATION_INVALID;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
index 8c478d6c0fae..ef58902ae88d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -158,12 +158,71 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
return 0;
}
+static inline char iwl_drv_get_step(int step)
+{
+ if (step == SILICON_Z_STEP)
+ return 'z';
+ return 'a' + step;
+}
+
+const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
+{
+ char mac_step, rf_step;
+ const char *rf, *cdb;
+
+ if (trans->cfg->fw_name_pre)
+ return trans->cfg->fw_name_pre;
+
+ if (WARN_ON(!trans->cfg->fw_name_mac))
+ return "unconfigured";
+
+ mac_step = iwl_drv_get_step(trans->hw_rev_step);
+
+ switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+ case IWL_CFG_RF_TYPE_HR1:
+ case IWL_CFG_RF_TYPE_HR2:
+ rf = "hr";
+ break;
+ case IWL_CFG_RF_TYPE_GF:
+ rf = "gf";
+ break;
+ case IWL_CFG_RF_TYPE_MR:
+ rf = "mr";
+ break;
+ case IWL_CFG_RF_TYPE_MS:
+ rf = "ms";
+ break;
+ case IWL_CFG_RF_TYPE_FM:
+ rf = "fm";
+ break;
+ case IWL_CFG_RF_TYPE_WH:
+ rf = "wh";
+ break;
+ default:
+ return "unknown-rf";
+ }
+
+ cdb = CSR_HW_RFID_IS_CDB(trans->hw_rf_id) ? "4" : "";
+
+ rf_step = iwl_drv_get_step(CSR_HW_RFID_STEP(trans->hw_rf_id));
+
+ scnprintf(buf, FW_NAME_PRE_BUFSIZE,
+ "iwlwifi-%s-%c0-%s%s-%c0",
+ trans->cfg->fw_name_mac, mac_step,
+ rf, cdb, rf_step);
+
+ return buf;
+}
+IWL_EXPORT_SYMBOL(iwl_drv_get_fwname_pre);
+
static void iwl_req_fw_callback(const struct firmware *ucode_raw,
void *context);
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
{
const struct iwl_cfg *cfg = drv->trans->cfg;
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
+ const char *fw_name_pre;
if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
(drv->trans->hw_rev_step != SILICON_B_STEP &&
@@ -174,6 +233,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
return -EINVAL;
}
+ fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre);
+
if (first)
drv->fw_index = cfg->ucode_api_max;
else
@@ -183,13 +244,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
IWL_ERR(drv, "no suitable firmware found!\n");
if (cfg->ucode_api_min == cfg->ucode_api_max) {
- IWL_ERR(drv, "%s%d is required\n", cfg->fw_name_pre,
+ IWL_ERR(drv, "%s-%d is required\n", fw_name_pre,
cfg->ucode_api_max);
} else {
- IWL_ERR(drv, "minimum version required: %s%d\n",
- cfg->fw_name_pre, cfg->ucode_api_min);
- IWL_ERR(drv, "maximum version supported: %s%d\n",
- cfg->fw_name_pre, cfg->ucode_api_max);
+ IWL_ERR(drv, "minimum version required: %s-%d\n",
+ fw_name_pre, cfg->ucode_api_min);
+ IWL_ERR(drv, "maximum version supported: %s-%d\n",
+ fw_name_pre, cfg->ucode_api_max);
}
IWL_ERR(drv,
@@ -197,8 +258,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
return -ENOENT;
}
- snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%d.ucode",
- cfg->fw_name_pre, drv->fw_index);
+ snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode",
+ fw_name_pre, drv->fw_index);
IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n",
drv->firmware_name);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 80073f973334..6c19989e4ab7 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2020-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2020-2021, 2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#ifndef __iwl_drv_h__
@@ -92,4 +92,8 @@ void iwl_drv_stop(struct iwl_drv *drv);
/* max retry for init flow */
#define IWL_MAX_INIT_RETRY 2
+#define FW_NAME_PRE_BUFSIZE 64
+struct iwl_trans;
+const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf);
+
#endif /* __iwl_drv_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
index bedd78a47f67..4e4a60ddf9b2 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fh_h__
@@ -71,7 +71,7 @@
static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
unsigned int chnl)
{
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
WARN_ON_ONCE(chnl >= 64);
return TFH_TFDQ_CBB_TABLE + 8 * chnl;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
index 396f2c997da6..c60f9466c5fd 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2022 Intel Corporation
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
#include <linux/delay.h>
@@ -72,6 +72,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
return value;
}
+ /* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
IWL_EXPORT_SYMBOL(iwl_read_direct32);
@@ -143,6 +144,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
return val;
}
+ /* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
IWL_EXPORT_SYMBOL(iwl_read_prph);
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 7dcb1c3ab728..8c23f57f5c89 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2005-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -173,34 +173,34 @@ enum iwl_nvm_channel_flags {
};
/**
- * enum iwl_reg_capa_flags - global flags applied for the whole regulatory
+ * enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory
* domain.
- * @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
+ * @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
* 2.4Ghz band is allowed.
- * @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
+ * @REG_CAPA_V1_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
* 5Ghz band is allowed.
- * @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ * @REG_CAPA_V1_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ * @REG_CAPA_V1_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
- * @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
- * @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
+ * @REG_CAPA_V1_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
+ * @REG_CAPA_V1_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
+ * @REG_CAPA_V1_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
* for this regulatory domain (valid only in 5Ghz).
- * @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed.
- * @REG_CAPA_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
+ * @REG_CAPA_V1_DC_HIGH_ENABLED: DC HIGH allowed.
+ * @REG_CAPA_V1_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/
-enum iwl_reg_capa_flags {
- REG_CAPA_BF_CCD_LOW_BAND = BIT(0),
- REG_CAPA_BF_CCD_HIGH_BAND = BIT(1),
- REG_CAPA_160MHZ_ALLOWED = BIT(2),
- REG_CAPA_80MHZ_ALLOWED = BIT(3),
- REG_CAPA_MCS_8_ALLOWED = BIT(4),
- REG_CAPA_MCS_9_ALLOWED = BIT(5),
- REG_CAPA_40MHZ_FORBIDDEN = BIT(7),
- REG_CAPA_DC_HIGH_ENABLED = BIT(9),
- REG_CAPA_11AX_DISABLED = BIT(10),
-};
+enum iwl_reg_capa_flags_v1 {
+ REG_CAPA_V1_BF_CCD_LOW_BAND = BIT(0),
+ REG_CAPA_V1_BF_CCD_HIGH_BAND = BIT(1),
+ REG_CAPA_V1_160MHZ_ALLOWED = BIT(2),
+ REG_CAPA_V1_80MHZ_ALLOWED = BIT(3),
+ REG_CAPA_V1_MCS_8_ALLOWED = BIT(4),
+ REG_CAPA_V1_MCS_9_ALLOWED = BIT(5),
+ REG_CAPA_V1_40MHZ_FORBIDDEN = BIT(7),
+ REG_CAPA_V1_DC_HIGH_ENABLED = BIT(9),
+ REG_CAPA_V1_11AX_DISABLED = BIT(10),
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_1 */
/**
* enum iwl_reg_capa_flags_v2 - global flags applied for the whole regulatory
@@ -234,7 +234,31 @@ enum iwl_reg_capa_flags_v2 {
REG_CAPA_V2_WEATHER_DISABLED = BIT(7),
REG_CAPA_V2_40MHZ_ALLOWED = BIT(8),
REG_CAPA_V2_11AX_DISABLED = BIT(10),
-};
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_2 */
+
+/**
+ * enum iwl_reg_capa_flags_v4 - global flags applied for the whole regulatory
+ * domain.
+ * @REG_CAPA_V4_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ * for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_V4_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ * for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_V4_MCS_12_ALLOWED: 11ac with MCS 12 is allowed.
+ * @REG_CAPA_V4_MCS_13_ALLOWED: 11ac with MCS 13 is allowed.
+ * @REG_CAPA_V4_11BE_DISABLED: 11be is forbidden for this regulatory domain.
+ * @REG_CAPA_V4_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
+ * @REG_CAPA_V4_320MHZ_ALLOWED: 11be channel with a width of 320Mhz is allowed
+ * for this regulatory domain (valid only in 5GHz).
+ */
+enum iwl_reg_capa_flags_v4 {
+ REG_CAPA_V4_160MHZ_ALLOWED = BIT(3),
+ REG_CAPA_V4_80MHZ_ALLOWED = BIT(4),
+ REG_CAPA_V4_MCS_12_ALLOWED = BIT(5),
+ REG_CAPA_V4_MCS_13_ALLOWED = BIT(6),
+ REG_CAPA_V4_11BE_DISABLED = BIT(8),
+ REG_CAPA_V4_11AX_DISABLED = BIT(13),
+ REG_CAPA_V4_320MHZ_ALLOWED = BIT(16),
+}; /* GEO_CHANNEL_CAPABILITIES_API_S_VER_4 */
/*
* API v2 for reg_capa_flags is relevant from version 6 and onwards of the
@@ -242,23 +266,33 @@ enum iwl_reg_capa_flags_v2 {
*/
#define REG_CAPA_V2_RESP_VER 6
+/* API v4 for reg_capa_flags is relevant from version 8 and onwards of the
+ * MCC update command response.
+ */
+#define REG_CAPA_V4_RESP_VER 8
+
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
*
* @allow_40mhz: 11n channel with a width of 40Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain.
* @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
- * for this regulatory domain (valid only in 5Ghz).
+ * for this regulatory domain (valid only in 5 and 6 Ghz).
+ * @allow_320mhz: 11be channel with a width of 320Mhz is allowed
+ * for this regulatory domain (valid only in 6 Ghz).
* @disable_11ax: 11ax is forbidden for this regulatory domain.
+ * @disable_11be: 11be is forbidden for this regulatory domain.
*/
struct iwl_reg_capa {
- u16 allow_40mhz;
- u16 allow_80mhz;
- u16 allow_160mhz;
- u16 disable_11ax;
+ bool allow_40mhz;
+ bool allow_80mhz;
+ bool allow_160mhz;
+ bool allow_320mhz;
+ bool disable_11ax;
+ bool disable_11be;
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
@@ -464,6 +498,9 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
IEEE80211_VHT_MAX_AMPDU_1024K <<
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+ if (!trans->cfg->ht_params->stbc)
+ vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK;
+
if (data->vht160_supported)
vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
IEEE80211_VHT_CAP_SHORT_GI_160;
@@ -479,7 +516,7 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
num_tx_ants = 1;
}
- if (num_tx_ants > 1)
+ if (trans->cfg->ht_params->stbc && num_tx_ants > 1)
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
else
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
@@ -643,8 +680,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = {
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
.phy_cap_info[1] =
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK |
- IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK,
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK,
.phy_cap_info[3] =
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
@@ -853,6 +889,10 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
const struct iwl_fw *fw)
{
bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);
+ bool no_320;
+
+ no_320 = !trans->trans_cfg->integrated &&
+ trans->pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB;
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
iftype_data->eht_cap.has_eht = false;
@@ -879,8 +919,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
break;
case NL80211_BAND_6GHZ:
- iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
- IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ if (!no_320) {
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[0] |=
+ IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[1] |=
+ IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK;
+ }
fallthrough;
case NL80211_BAND_5GHZ:
iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
@@ -975,6 +1019,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &=
~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP);
+ iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |=
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF;
}
if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
@@ -986,6 +1032,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
iftype_data->vendor_elems.data = iwl_vendor_caps;
iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps);
}
+
+ if (!trans->cfg->ht_params->stbc) {
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
+ ~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
+ iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &=
+ ~IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
+ }
}
static void iwl_init_he_hw_capab(struct iwl_trans *trans,
@@ -1521,27 +1574,41 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
if (!reg_capa.allow_160mhz)
flags |= NL80211_RRF_NO_160MHZ;
+
+ if (!reg_capa.allow_320mhz)
+ flags |= NL80211_RRF_NO_320MHZ;
}
+
if (reg_capa.disable_11ax)
flags |= NL80211_RRF_NO_HE;
+ if (reg_capa.disable_11be)
+ flags |= NL80211_RRF_NO_EHT;
+
return flags;
}
-static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver)
+static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
{
- struct iwl_reg_capa reg_capa;
-
- if (resp_ver >= REG_CAPA_V2_RESP_VER) {
+ struct iwl_reg_capa reg_capa = {};
+
+ if (resp_ver >= REG_CAPA_V4_RESP_VER) {
+ reg_capa.allow_40mhz = true;
+ reg_capa.allow_80mhz = flags & REG_CAPA_V4_80MHZ_ALLOWED;
+ reg_capa.allow_160mhz = flags & REG_CAPA_V4_160MHZ_ALLOWED;
+ reg_capa.allow_320mhz = flags & REG_CAPA_V4_320MHZ_ALLOWED;
+ reg_capa.disable_11ax = flags & REG_CAPA_V4_11AX_DISABLED;
+ reg_capa.disable_11be = flags & REG_CAPA_V4_11BE_DISABLED;
+ } else if (resp_ver >= REG_CAPA_V2_RESP_VER) {
reg_capa.allow_40mhz = flags & REG_CAPA_V2_40MHZ_ALLOWED;
reg_capa.allow_80mhz = flags & REG_CAPA_V2_80MHZ_ALLOWED;
reg_capa.allow_160mhz = flags & REG_CAPA_V2_160MHZ_ALLOWED;
reg_capa.disable_11ax = flags & REG_CAPA_V2_11AX_DISABLED;
} else {
- reg_capa.allow_40mhz = !(flags & REG_CAPA_40MHZ_FORBIDDEN);
- reg_capa.allow_80mhz = flags & REG_CAPA_80MHZ_ALLOWED;
- reg_capa.allow_160mhz = flags & REG_CAPA_160MHZ_ALLOWED;
- reg_capa.disable_11ax = flags & REG_CAPA_11AX_DISABLED;
+ reg_capa.allow_40mhz = !(flags & REG_CAPA_V1_40MHZ_FORBIDDEN);
+ reg_capa.allow_80mhz = flags & REG_CAPA_V1_80MHZ_ALLOWED;
+ reg_capa.allow_160mhz = flags & REG_CAPA_V1_160MHZ_ALLOWED;
+ reg_capa.disable_11ax = flags & REG_CAPA_V1_11AX_DISABLED;
}
return reg_capa;
}
@@ -1549,7 +1616,7 @@ static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver)
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc,
- u16 geo_info, u16 cap, u8 resp_ver)
+ u16 geo_info, u32 cap, u8 resp_ver)
{
int ch_idx;
u16 ch_flags;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
index e01f7751cf11..c79f72d54482 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2015, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2015, 2018-2022 Intel Corporation
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_nvm_parse_h__
@@ -50,7 +50,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc,
- u16 geo_info, u16 cap, u8 resp_ver);
+ u16 geo_info, u32 cap, u8 resp_ver);
/**
* struct iwl_nvm_section - describes an NVM section in memory.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
index 0dfe00eae05d..6dd381ff0f9e 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2005-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Intel Deutschland GmbH
*/
@@ -486,6 +486,10 @@ enum {
#define FSEQ_ALIVE_TOKEN 0xA340F0
#define FSEQ_CNVI_ID 0xA3408C
#define FSEQ_CNVR_ID 0xA34090
+#define FSEQ_PREV_CNVIO_INIT_VERSION 0xA34084
+#define FSEQ_WIFI_FSEQ_VERSION 0xA34040
+#define FSEQ_BT_FSEQ_VERSION 0xA34044
+#define FSEQ_CLASS_TP_VERSION 0xA34078
#define IWL_D3_SLEEP_STATUS_SUSPEND 0xD3
#define IWL_D3_SLEEP_STATUS_RESUME 0xD0
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index b1af9359cea5..4bd759432d44 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2021 Intel Corporation
+ * Copyright (C) 2019-2021, 2023 Intel Corporation
*/
#include <linux/kernel.h>
#include <linux/bsearch.h>
@@ -42,7 +42,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
trans->txqs.tfd.addr_size = 64;
trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
@@ -101,7 +101,7 @@ int iwl_trans_init(struct iwl_trans *trans)
/* Some things must not change even if the config does */
WARN_ON(trans->txqs.tfd.addr_size !=
- (trans->trans_cfg->use_tfh ? 64 : 36));
+ (trans->trans_cfg->gen2 ? 64 : 36));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 9f1228b5a384..d02943d0ea62 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -459,6 +459,24 @@ struct iwl_trans_rxq_dma_data {
u64 ur_bd_cb;
};
+/* maximal number of DRAM MAP entries supported by FW */
+#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64
+
+/**
+ * struct iwl_pnvm_image - contains info about the parsed pnvm image
+ * @chunks: array of pointers to pnvm payloads and their sizes
+ * @n_chunks: the number of the pnvm payloads.
+ * @version: the version of the loaded PNVM image
+ */
+struct iwl_pnvm_image {
+ struct {
+ const void *data;
+ u32 len;
+ } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+ u32 n_chunks;
+ u32 version;
+};
+
/**
* struct iwl_trans_ops - transport specific operations
*
@@ -541,8 +559,11 @@ struct iwl_trans_rxq_dma_data {
* Note that the transport must fill in the proper file headers.
* @debugfs_cleanup: used in the driver unload flow to make a proper cleanup
* of the trans debugfs
+ * @load_pnvm: save the pnvm data in DRAM
* @set_pnvm: set the pnvm data in the prph scratch buffer, inside the
* context info.
+ * @load_reduce_power: copy reduce power table to the corresponding DRAM memory
+ * @set_reduce_power: set reduce power table addresses in the sratch buffer
* @interrupts: disable/enable interrupts to transport
*/
struct iwl_trans_ops {
@@ -614,9 +635,17 @@ struct iwl_trans_ops {
void *sanitize_ctx);
void (*debugfs_cleanup)(struct iwl_trans *trans);
void (*sync_nmi)(struct iwl_trans *trans);
- int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
- int (*set_reduce_power)(struct iwl_trans *trans,
- const void *data, u32 len);
+ int (*load_pnvm)(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa);
+ void (*set_pnvm)(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+ int (*load_reduce_power)(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa);
+ void (*set_reduce_power)(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa);
+
void (*interrupts)(struct iwl_trans *trans, bool enable);
int (*imr_dma_data)(struct iwl_trans *trans,
u32 dst_addr, u64 src_addr,
@@ -705,6 +734,19 @@ struct iwl_dram_data {
};
/**
+ * @drams: array of several DRAM areas that contains the pnvm and power
+ * reduction table payloads.
+ * @n_regions: number of DRAM regions that were allocated
+ * @prph_scratch_mem_desc: points to a structure allocated in dram,
+ * designed to show FW where all the payloads are.
+ */
+struct iwl_dram_regions {
+ struct iwl_dram_data drams[IPC_DRAM_MAP_ENTRY_NUM_MAX];
+ struct iwl_dram_data prph_scratch_mem_desc;
+ u8 n_regions;
+};
+
+/**
* struct iwl_fw_mon - fw monitor per allocation id
* @num_frags: number of fragments
* @frags: an array of DRAM buffer fragments
@@ -1004,6 +1046,8 @@ struct iwl_trans_txqs {
* @hw_rev_step: The mac step of the HW
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
+ * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
+ * @failed_to_load_reduce_power_image: set to true if pnvm loading failed
* @wide_cmd_header: true when ucode supports wide command header format
* @wait_command_queue: wait queue for sync commands
* @num_rx_queues: number of RX queues allocated by the transport;
@@ -1023,6 +1067,8 @@ struct iwl_trans_txqs {
* @iwl_trans_txqs: transport tx queues data.
* @mbx_addr_0_step: step address data 0
* @mbx_addr_1_step: step address data 1
+ * @pcie_link_speed: current PCIe link speed (%PCI_EXP_LNKSTA_CLS_*),
+ * only valid for discrete (not integrated) NICs
*/
struct iwl_trans {
bool csme_own;
@@ -1051,7 +1097,9 @@ struct iwl_trans {
bool pm_support;
bool ltr_enabled;
u8 pnvm_loaded:1;
+ u8 fail_to_parse_pnvm_image:1;
u8 reduce_power_loaded:1;
+ u8 failed_to_load_reduce_power_image:1;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
@@ -1083,6 +1131,8 @@ struct iwl_trans {
u32 mbx_addr_0_step;
u32 mbx_addr_1_step;
+ u8 pcie_link_speed;
+
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[] __aligned(sizeof(void *));
@@ -1160,7 +1210,7 @@ static inline int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test,
{
might_sleep();
if (!trans->ops->d3_suspend)
- return 0;
+ return -EOPNOTSUPP;
return trans->ops->d3_suspend(trans, test, reset);
}
@@ -1171,7 +1221,7 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
{
might_sleep();
if (!trans->ops->d3_resume)
- return 0;
+ return -EOPNOTSUPP;
return trans->ops->d3_resume(trans, status, test, reset);
}
@@ -1515,33 +1565,34 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
u32 sw_err_bit);
-static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len)
+static inline int iwl_trans_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_data,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->ops->set_pnvm) {
- int ret = trans->ops->set_pnvm(trans, data, len);
-
- if (ret)
- return ret;
- }
-
- trans->pnvm_loaded = true;
-
- return 0;
+ return trans->ops->load_pnvm(trans, pnvm_data, capa);
}
-static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len)
+static inline void iwl_trans_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
{
- if (trans->ops->set_reduce_power) {
- int ret = trans->ops->set_reduce_power(trans, data, len);
+ if (trans->ops->set_pnvm)
+ trans->ops->set_pnvm(trans, capa);
+}
- if (ret)
- return ret;
- }
+static inline int iwl_trans_load_reduce_power
+ (struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa)
+{
+ return trans->ops->load_reduce_power(trans, payloads, capa);
+}
- trans->reduce_power_loaded = true;
- return 0;
+static inline void
+iwl_trans_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->ops->set_reduce_power)
+ trans->ops->set_reduce_power(trans, capa);
}
static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
@@ -1566,6 +1617,11 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
int iwl_trans_init(struct iwl_trans *trans);
void iwl_trans_free(struct iwl_trans *trans);
+static inline bool iwl_trans_is_hw_error_value(u32 val)
+{
+ return ((val & ~0xf) == 0xa5a5a5a0) || ((val & ~0xf) == 0x5a5a5a50);
+}
+
/*****************************************************
* driver (transport) register/unregister functions
******************************************************/
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c
index 0a29fb013005..54445f39fd55 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c
@@ -1791,9 +1791,8 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
if (iwl_mei_is_connected()) {
if (mei->amt_enabled)
iwl_mei_send_sap_msg(mei->cldev,
- SAP_MSG_NOTIF_WIFIDR_UP,
- false);
- ops->rfkill(priv, mei->link_prot_state);
+ SAP_MSG_NOTIF_WIFIDR_UP);
+ ops->rfkill(priv, mei->link_prot_state, false);
}
}
ret = 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
index ef50ccabcc73..458b97930059 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/binding.c
@@ -32,7 +32,7 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
size = sizeof(cmd);
- cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
+ cmd.lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm,
phyctxt->channel->band));
} else {
size = IWL_BINDING_CMD_SIZE_V1;
@@ -164,3 +164,11 @@ int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return ret;
}
+
+u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band)
+{
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CDB_SUPPORT) ||
+ band == NL80211_BAND_2GHZ)
+ return IWL_LMAC_24G_INDEX;
+ return IWL_LMAC_5G_INDEX;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index c604f9f39b24..243eccc68cb0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
- * Copyright (C) 2013-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2023 Intel Corporation
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __MVM_CONSTANTS_H
@@ -109,10 +109,6 @@
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 20
#define IWL_MVM_USE_NSSN_SYNC 0
-#define IWL_MVM_PHY_FILTER_CHAIN_A 0
-#define IWL_MVM_PHY_FILTER_CHAIN_B 0
-#define IWL_MVM_PHY_FILTER_CHAIN_C 0
-#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 6d1007f24b4a..f6488b4bbe68 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -1380,6 +1380,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
return __iwl_mvm_suspend(hw, wowlan, false);
}
+struct iwl_multicast_key_data {
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ u8 len;
+ u8 flags;
+ u8 id;
+ u8 ipn[6];
+};
+
/* converted data from the different status responses */
struct iwl_wowlan_status_data {
u64 replay_ctr;
@@ -1398,7 +1406,8 @@ struct iwl_wowlan_status_data {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 len;
u8 flags;
- } gtk;
+ u8 id;
+ } gtk[WOWLAN_GTK_KEYS_NUM];
struct {
/*
@@ -1428,12 +1437,7 @@ struct iwl_wowlan_status_data {
} tkip, aes;
} ptk;
- struct {
- u64 ipn;
- u8 key[WOWLAN_KEY_MAX_SIZE];
- u8 len;
- u8 flags;
- } igtk;
+ struct iwl_multicast_key_data igtk;
u8 *wake_packet;
};
@@ -1758,7 +1762,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
s8 new_key_id = -1;
if (status->num_of_gtk_rekeys)
- new_key_id = status->gtk.flags &
+ new_key_id = status->gtk[0].flags &
IWL_WOWLAN_GTK_IDX_MASK;
/* Don't install a new key's value to an old key */
@@ -1777,20 +1781,18 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
struct iwl_mvm_d3_gtk_iter_data {
struct iwl_mvm *mvm;
struct iwl_wowlan_status_data *status;
- void *last_gtk;
- u32 cipher;
- bool find_phase, unhandled_cipher;
+ u32 gtk_cipher, igtk_cipher;
+ bool unhandled_cipher, igtk_support;
int num_keys;
};
-static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *_data)
+static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
{
struct iwl_mvm_d3_gtk_iter_data *data = _data;
- struct iwl_wowlan_status_data *status = data->status;
if (data->unhandled_cipher)
return;
@@ -1805,51 +1807,230 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
case WLAN_CIPHER_SUITE_GCMP_256:
case WLAN_CIPHER_SUITE_TKIP:
/* we support these */
+ data->gtk_cipher = key->cipher;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ /* we support these */
+ if (data->igtk_support &&
+ (key->keyidx == 4 || key->keyidx == 5)) {
+ data->igtk_cipher = key->cipher;
+ } else {
+ data->unhandled_cipher = true;
+ return;
+ }
break;
default:
- /* everything else (even CMAC for MFP) - disconnect from AP */
+ /* everything else - disconnect from AP */
data->unhandled_cipher = true;
return;
}
data->num_keys++;
+}
- /*
- * pairwise key - update sequence counters only;
- * note that this assumes no TDLS sessions are active
- */
- if (sta) {
- if (data->find_phase)
- return;
+static void
+iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key,
+ struct ieee80211_key_seq *seq, u32 cipher)
+{
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ BUILD_BUG_ON(sizeof(seq->aes_gmac.pn) != sizeof(key->ipn));
+ memcpy(seq->aes_gmac.pn, key->ipn, sizeof(seq->aes_gmac.pn));
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ BUILD_BUG_ON(sizeof(seq->aes_cmac.pn) != sizeof(key->ipn));
+ memcpy(seq->aes_cmac.pn, key->ipn, sizeof(seq->aes_cmac.pn));
+ break;
+ }
+}
+
+static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key,
+ void *_data)
+{
+ struct iwl_mvm_d3_gtk_iter_data *data = _data;
+ struct iwl_wowlan_status_data *status = data->status;
+ s8 keyidx;
+
+ if (data->unhandled_cipher)
+ return;
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- case WLAN_CIPHER_SUITE_GCMP_256:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ /* ignore WEP completely, nothing to do */
+ return;
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (sta) {
atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);
iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
+ return;
+ }
+ fallthrough;
+ case WLAN_CIPHER_SUITE_TKIP:
+ if (sta) {
atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);
iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
- break;
+ return;
}
+ keyidx = key->keyidx;
+ /* The current key is always sent by the FW, even if it wasn't
+ * rekeyed during D3.
+ * We remove an existing key if it has the same index as
+ * a new key
+ */
+ if (status->num_of_gtk_rekeys &&
+ ((status->gtk[0].len && keyidx == status->gtk[0].id) ||
+ (status->gtk[1].len && keyidx == status->gtk[1].id))) {
+ ieee80211_remove_key(key);
+ } else {
+ iwl_mvm_set_key_rx_seq(key, data->status, false);
+ }
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ if (key->keyidx == 4 || key->keyidx == 5) {
+ /* remove rekeyed key */
+ if (status->num_of_gtk_rekeys) {
+ ieee80211_remove_key(key);
+ } else {
+ struct ieee80211_key_seq seq;
- /* that's it for this key */
- return;
+ iwl_mvm_d3_set_igtk_bigtk_ipn(&status->igtk,
+ &seq,
+ key->cipher);
+ ieee80211_set_key_rx_seq(key, 0, &seq);
+ }
+ }
}
+}
- if (data->find_phase) {
- data->last_gtk = key;
- data->cipher = key->cipher;
- return;
+static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
+ struct ieee80211_vif *vif,
+ struct iwl_mvm *mvm, u32 gtk_cipher)
+{
+ int i;
+ struct ieee80211_key_conf *key;
+ struct {
+ struct ieee80211_key_conf conf;
+ u8 key[32];
+ } conf = {
+ .conf.cipher = gtk_cipher,
+ };
+
+ BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
+ BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
+ BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key));
+
+ switch (gtk_cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_GCMP:
+ conf.conf.keylen = WLAN_KEY_LEN_CCMP;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ conf.conf.keylen = WLAN_KEY_LEN_TKIP;
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(status->gtk); i++) {
+ if (!status->gtk[i].len)
+ continue;
+
+ conf.conf.keyidx = status->gtk[i].id;
+ IWL_DEBUG_WOWLAN(mvm,
+ "Received from FW GTK cipher %d, key index %d\n",
+ conf.conf.cipher, conf.conf.keyidx);
+ memcpy(conf.conf.key, status->gtk[i].key,
+ sizeof(status->gtk[i].key));
+
+ key = ieee80211_gtk_rekey_add(vif, &conf.conf);
+ if (IS_ERR(key))
+ return false;
+ iwl_mvm_set_key_rx_seq_idx(key, status, i);
}
- if (data->status->num_of_gtk_rekeys)
- ieee80211_remove_key(key);
+ return true;
+}
+
+static bool
+iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
+ struct ieee80211_vif *vif, u32 cipher,
+ struct iwl_multicast_key_data *key_data)
+{
+ struct ieee80211_key_conf *key_config;
+ struct {
+ struct ieee80211_key_conf conf;
+ u8 key[WOWLAN_KEY_MAX_SIZE];
+ } conf = {
+ .conf.cipher = cipher,
+ .conf.keyidx = key_data->id,
+ };
+ struct ieee80211_key_seq seq;
+
+ if (!key_data->len)
+ return true;
+
+ iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher);
+
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;
+ break;
+ default:
+ WARN_ON(1);
+ }
+ BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));
+ memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
+
+ key_config = ieee80211_gtk_rekey_add(vif, &conf.conf);
+ if (IS_ERR(key_config))
+ return false;
+ ieee80211_set_key_rx_seq(key_config, 0, &seq);
+ return true;
+}
+
+static int iwl_mvm_lookup_wowlan_status_ver(struct iwl_mvm *mvm)
+{
+ u8 notif_ver;
+
+ if (!fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL))
+ return 6;
+
+ /* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
+ notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
+ WOWLAN_GET_STATUSES, 0);
+ if (!notif_ver)
+ notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ WOWLAN_GET_STATUSES, 7);
- if (data->last_gtk == key)
- iwl_mvm_set_key_rx_seq(key, data->status, false);
+ return notif_ver;
}
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
@@ -1871,71 +2052,41 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
if (status->wakeup_reasons & disconnection_reasons)
return false;
+ if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 ||
+ iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,
+ WOWLAN_INFO_NOTIFICATION,
+ 0))
+ gtkdata.igtk_support = true;
+
/* find last GTK that we used initially, if any */
- gtkdata.find_phase = true;
ieee80211_iter_keys(mvm->hw, vif,
- iwl_mvm_d3_update_keys, &gtkdata);
+ iwl_mvm_d3_find_last_keys, &gtkdata);
/* not trying to keep connections with MFP/unhandled ciphers */
if (gtkdata.unhandled_cipher)
return false;
if (!gtkdata.num_keys)
goto out;
- if (!gtkdata.last_gtk)
- return false;
/*
* invalidate all other GTKs that might still exist and update
* the one that we used
*/
- gtkdata.find_phase = false;
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_d3_update_keys, &gtkdata);
- IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
- status->num_of_gtk_rekeys);
if (status->num_of_gtk_rekeys) {
- struct ieee80211_key_conf *key;
- struct {
- struct ieee80211_key_conf conf;
- u8 key[32];
- } conf = {
- .conf.cipher = gtkdata.cipher,
- .conf.keyidx =
- status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK,
- };
- __be64 replay_ctr;
+ __be64 replay_ctr = cpu_to_be64(status->replay_ctr);
- IWL_DEBUG_WOWLAN(mvm,
- "Received from FW GTK cipher %d, key index %d\n",
- conf.conf.cipher, conf.conf.keyidx);
-
- BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
- BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
- BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key));
+ IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
+ status->num_of_gtk_rekeys);
- memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key));
-
- switch (gtkdata.cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_GCMP:
- conf.conf.keylen = WLAN_KEY_LEN_CCMP;
- break;
- case WLAN_CIPHER_SUITE_GCMP_256:
- conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- conf.conf.keylen = WLAN_KEY_LEN_TKIP;
- break;
- }
-
- key = ieee80211_gtk_rekey_add(vif, &conf.conf);
- if (IS_ERR(key))
+ if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher))
return false;
- iwl_mvm_set_key_rx_seq(key, status, true);
- replay_ctr = cpu_to_be64(status->replay_ctr);
+ if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,
+ gtkdata.igtk_cipher,
+ &status->igtk))
+ return false;
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
@@ -1955,60 +2106,70 @@ out:
static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_gtk_status_v2 *data)
{
- BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
+ BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data->key));
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
sizeof(data->tkip_mic_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
- status->gtk.len = data->key_len;
- status->gtk.flags = data->key_flags;
+ status->gtk[0].len = data->key_len;
+ status->gtk[0].flags = data->key_flags;
- memcpy(status->gtk.key, data->key, sizeof(data->key));
+ memcpy(status->gtk[0].key, data->key, sizeof(data->key));
/* if it's as long as the TKIP encryption key, copy MIC key */
- if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
- memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ if (status->gtk[0].len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
data->tkip_mic_key, sizeof(data->tkip_mic_key));
}
static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_gtk_status_v3 *data)
{
- /* The parts we need are identical in v2 and v3 */
-#define CHECK(_f) do { \
- BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \
- offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \
- BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\
- offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \
-} while (0)
+ int data_idx, status_idx = 0;
- CHECK(key);
- CHECK(key_len);
- CHECK(key_flags);
- CHECK(tkip_mic_key);
-#undef CHECK
+ BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data[0].key));
+ BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
+ sizeof(data[0].tkip_mic_key) >
+ sizeof(status->gtk[0].key));
+ BUILD_BUG_ON(ARRAY_SIZE(status->gtk) < WOWLAN_GTK_KEYS_NUM);
+ for (data_idx = 0; data_idx < ARRAY_SIZE(status->gtk); data_idx++) {
+ if (!(data[data_idx].key_len))
+ continue;
+ status->gtk[status_idx].len = data[data_idx].key_len;
+ status->gtk[status_idx].flags = data[data_idx].key_flags;
+ status->gtk[status_idx].id = status->gtk[status_idx].flags &
+ IWL_WOWLAN_GTK_IDX_MASK;
- iwl_mvm_convert_gtk_v2(status, (void *)data);
+ memcpy(status->gtk[status_idx].key, data[data_idx].key,
+ sizeof(data[data_idx].key));
+
+ /* if it's as long as the TKIP encryption key, copy MIC key */
+ if (status->gtk[status_idx].len ==
+ NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+ memcpy(status->gtk[status_idx].key +
+ NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ data[data_idx].tkip_mic_key,
+ sizeof(data[data_idx].tkip_mic_key));
+ status_idx++;
+ }
}
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_igtk_status *data)
{
- const u8 *ipn = data->ipn;
-
BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));
+ if (!data->key_len)
+ return;
+
status->igtk.len = data->key_len;
status->igtk.flags = data->key_flags;
+ status->igtk.id = u32_get_bits(data->key_flags,
+ IWL_WOWLAN_IGTK_BIGTK_IDX_MASK)
+ + WOWLAN_IGTK_MIN_INDEX;
memcpy(status->igtk.key, data->key, sizeof(data->key));
-
- status->igtk.ipn = ((u64)ipn[5] << 0) |
- ((u64)ipn[4] << 8) |
- ((u64)ipn[3] << 16) |
- ((u64)ipn[2] << 24) |
- ((u64)ipn[1] << 32) |
- ((u64)ipn[0] << 40);
+ memcpy(status->igtk.ipn, data->ipn, sizeof(data->ipn));
}
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
@@ -2031,7 +2192,7 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
}
iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, &data->gtk[0]);
+ iwl_mvm_convert_gtk_v3(status, data->gtk);
iwl_mvm_convert_igtk(status, &data->igtk[0]);
status->replay_ctr = le64_to_cpu(data->replay_ctr);
@@ -2139,14 +2300,9 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */
- notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
- WOWLAN_GET_STATUSES, 0);
- if (!notif_ver)
- notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
- WOWLAN_GET_STATUSES, 7);
+ notif_ver = iwl_mvm_lookup_wowlan_status_ver(mvm);
- if (!fw_has_api(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
+ if (notif_ver < 7) {
struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
@@ -2154,29 +2310,29 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
goto out_free_resp;
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
sizeof(v6->gtk.tkip_mic_key) >
- sizeof(status->gtk.key));
+ sizeof(status->gtk[0].key));
/* copy GTK info to the right place */
- memcpy(status->gtk.key, v6->gtk.decrypt_key,
+ memcpy(status->gtk[0].key, v6->gtk.decrypt_key,
sizeof(v6->gtk.decrypt_key));
- memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+ memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
v6->gtk.tkip_mic_key,
sizeof(v6->gtk.tkip_mic_key));
iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
/* hardcode the key length to 16 since v6 only supports 16 */
- status->gtk.len = 16;
+ status->gtk[0].len = 16;
/*
* The key index only uses 2 bits (values 0 to 3) and
* we always set bit 7 which means this is the
* currently used key.
*/
- status->gtk.flags = v6->gtk.key_index | BIT(7);
+ status->gtk[0].flags = v6->gtk.key_index | BIT(7);
} else if (notif_ver == 7) {
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
@@ -2210,7 +2366,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
goto out_free_resp;
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
- iwl_mvm_convert_gtk_v3(status, &v12->gtk[0]);
+ iwl_mvm_convert_gtk_v3(status, v12->gtk);
iwl_mvm_convert_igtk(status, &v12->igtk[0]);
status->tid_tear_down = v12->tid_tear_down;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
index 3613b1fdc5d9..cb4ecad6103f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -554,7 +554,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
char buf[20];
int len;
- len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
+ len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_ap_addr);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -567,7 +567,7 @@ static ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
bool ret;
mutex_lock(&mvm->mutex);
- ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
+ ret = mac_pton(buf, mvmvif->uapsd_misbehaving_ap_addr);
mutex_unlock(&mvm->mutex);
return ret ? count : -EINVAL;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 84a488538427..cf27f106d4d5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -15,6 +15,7 @@
#include "iwl-io.h"
#include "debugfs.h"
#include "iwl-modparams.h"
+#include "iwl-drv.h"
#include "fw/error-dump.h"
#include "fw/api/phy-ctxt.h"
@@ -391,13 +392,14 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
+static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
+ char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ieee80211_sta *sta = file->private_data;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;
- struct iwl_mvm *mvm = lq_sta->pers.drv;
+ struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw;
static const size_t bufsz = 2048;
char *buff;
int desc = 0;
@@ -407,8 +409,6 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
if (!buff)
return -ENOMEM;
- mutex_lock(&mvm->mutex);
-
desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
lq_sta->pers.sta_id);
desc += scnprintf(buff + desc, bufsz - desc,
@@ -429,18 +429,19 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
lq_sta->last_rate_n_flags);
if (desc < bufsz - 1)
buff[desc++] = '\n';
- mutex_unlock(&mvm->mutex);
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
kfree(buff);
return ret;
}
-static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
+static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
char *buf, size_t count,
loff_t *ppos)
{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
int i;
u16 amsdu_len;
@@ -448,36 +449,39 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
return -EINVAL;
/* only change from debug set <-> debug unset */
- if (amsdu_len && mvmsta->orig_amsdu_len)
+ if (amsdu_len && mvm_link_sta->orig_amsdu_len)
return -EBUSY;
if (amsdu_len) {
- mvmsta->orig_amsdu_len = sta->cur->max_amsdu_len;
- sta->deflink.agg.max_amsdu_len = amsdu_len;
- sta->deflink.agg.max_amsdu_len = amsdu_len;
- for (i = 0; i < ARRAY_SIZE(sta->deflink.agg.max_tid_amsdu_len); i++)
- sta->deflink.agg.max_tid_amsdu_len[i] = amsdu_len;
+ mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len;
+ link_sta->agg.max_amsdu_len = amsdu_len;
+ link_sta->agg.max_amsdu_len = amsdu_len;
+ for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++)
+ link_sta->agg.max_tid_amsdu_len[i] = amsdu_len;
} else {
- sta->deflink.agg.max_amsdu_len = mvmsta->orig_amsdu_len;
- mvmsta->orig_amsdu_len = 0;
+ link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len;
+ mvm_link_sta->orig_amsdu_len = 0;
}
+ ieee80211_sta_recalc_aggregates(link_sta->sta);
+
return count;
}
-static ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
+static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta,
+ struct iwl_mvm_sta *mvmsta,
+ struct iwl_mvm *mvm,
+ struct iwl_mvm_link_sta *mvm_link_sta,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ieee80211_sta *sta = file->private_data;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
char buf[32];
int pos;
- pos = scnprintf(buf, sizeof(buf), "current %d ", sta->cur->max_amsdu_len);
+ pos = scnprintf(buf, sizeof(buf), "current %d ",
+ link_sta->agg.max_amsdu_len);
pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
- mvmsta->orig_amsdu_len);
+ mvm_link_sta->orig_amsdu_len);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -712,6 +716,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
struct iwl_mvm *mvm = file->private_data;
char *buff, *pos, *endpos;
static const size_t bufsz = 1024;
+ char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
int ret;
buff = kmalloc(bufsz, GFP_KERNEL);
@@ -722,7 +727,7 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
endpos = pos + bufsz;
pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
- mvm->trans->cfg->fw_name_pre);
+ iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre));
pos += scnprintf(pos, endpos - pos, "FW: %s\n",
mvm->fwrt.fw->human_readable);
pos += scnprintf(pos, endpos - pos, "Device: %s\n",
@@ -1596,17 +1601,127 @@ static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
-#define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \
- _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
-#define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \
- _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
+static ssize_t
+_iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *,
+ struct iwl_mvm_sta *,
+ struct iwl_mvm *,
+ struct iwl_mvm_link_sta *,
+ char *,
+ size_t, loff_t *),
+ struct file *file,
+ char *buf, size_t buf_size, loff_t *ppos)
+{
+ struct ieee80211_link_sta *link_sta = file->private_data;
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
+ struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
+ struct iwl_mvm_link_sta *mvm_link_sta;
+ ssize_t ret;
-#define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do { \
- debugfs_create_file(alias, mode, parent, sta, \
- &iwl_dbgfs_##name##_ops); \
- } while (0)
-#define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
- MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
+ mutex_lock(&mvm->mutex);
+
+ mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (WARN_ON(!mvm_link_sta)) {
+ mutex_unlock(&mvm->mutex);
+ return -ENODEV;
+ }
+
+ ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos);
+
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+static ssize_t
+_iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *,
+ struct iwl_mvm_sta *,
+ struct iwl_mvm *,
+ struct iwl_mvm_link_sta *,
+ char __user *,
+ size_t, loff_t *),
+ struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct ieee80211_link_sta *link_sta = file->private_data;
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
+ struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
+ struct iwl_mvm_link_sta *mvm_link_sta;
+ ssize_t ret;
+
+ mutex_lock(&mvm->mutex);
+
+ mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
+ lockdep_is_held(&mvm->mutex));
+ if (WARN_ON(!mvm_link_sta)) {
+ mutex_unlock(&mvm->mutex);
+ return -ENODEV;
+ }
+
+ ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos);
+
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+#define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen) \
+static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \
+ const char __user *user_buf, \
+ size_t count, loff_t *ppos) \
+{ \
+ char buf[buflen] = {}; \
+ size_t buf_size = min(count, sizeof(buf) - 1); \
+ \
+ if (copy_from_user(buf, user_buf, sizeof(buf))) \
+ return -EFAULT; \
+ \
+ return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \
+ file, \
+ buf, buf_size, ppos); \
+} \
+
+#define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file, \
+ char __user *user_buf, \
+ size_t count, loff_t *ppos) \
+{ \
+ return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read, \
+ file, \
+ user_buf, count, ppos); \
+} \
+
+#define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz) \
+MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .write = _iwl_dbgfs_link_sta_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name) \
+MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .read = _iwl_dbgfs_link_sta_##name##_read, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz) \
+MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name) \
+MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz) \
+static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = { \
+ .read = _iwl_dbgfs_link_sta_##name##_read, \
+ .write = _iwl_dbgfs_link_sta_##name##_write, \
+ .open = simple_open, \
+ .llseek = generic_file_llseek, \
+}
+
+#define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode) \
+ debugfs_create_file(alias, mode, parent, link_sta, \
+ &iwl_dbgfs_link_sta_##name##_ops)
+#define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \
+ MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode)
static ssize_t
iwl_dbgfs_prph_reg_read(struct file *file,
@@ -1891,7 +2006,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
MVM_DEBUGFS_READ_FILE_OPS(stations);
-MVM_DEBUGFS_READ_FILE_OPS(rs_data);
+MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data);
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
@@ -1921,7 +2036,7 @@ MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
#endif
-MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
+MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
@@ -2068,17 +2183,18 @@ static const struct file_operations iwl_dbgfs_mem_ops = {
.llseek = default_llseek,
};
-void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct dentry *dir)
+void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
if (iwl_mvm_has_tlc_offload(mvm)) {
- MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
+ MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400);
}
- MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
+
+ MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600);
}
void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
index 652a603c4500..233ae81884a0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -72,15 +72,24 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* the TK is already configured for this station, so it
* shouldn't be set again here.
*/
- if (vif->cfg.assoc &&
- !memcmp(addr, vif->bss_conf.bssid, ETH_ALEN)) {
+ if (vif->cfg.assoc) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
struct ieee80211_sta *sta;
+ u8 sta_id;
rcu_read_lock();
- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
- if (!IS_ERR_OR_NULL(sta) && sta->mfp)
- expected_tk_len = 0;
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ if (memcmp(addr, link_conf->bssid, ETH_ALEN))
+ continue;
+
+ sta_id = mvmvif->link[link_id]->ap_sta_id;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+ if (!IS_ERR_OR_NULL(sta) && sta->mfp)
+ expected_tk_len = 0;
+ break;
+ }
rcu_read_unlock();
}
@@ -518,25 +527,30 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_ftm_put_target_common(mvm, peer, target);
- if (vif->cfg.assoc &&
- !memcmp(peer->addr, vif->bss_conf.bssid, ETH_ALEN)) {
+ if (vif->cfg.assoc) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_sta *sta;
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
rcu_read_lock();
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN))
+ continue;
+
+ target->sta_id = mvmvif->link[link_id]->ap_sta_id;
+ sta = rcu_dereference(mvm->fw_id_to_mac_id[target->sta_id]);
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
+ rcu_read_unlock();
+ return PTR_ERR_OR_ZERO(sta);
+ }
- sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id]);
- if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
- rcu_read_unlock();
- return PTR_ERR_OR_ZERO(sta);
+ if (sta->mfp && (peer->ftm.trigger_based ||
+ peer->ftm.non_trigger_based))
+ FTM_PUT_FLAG(PMF);
+ break;
}
-
- if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based))
- FTM_PUT_FLAG(PMF);
-
rcu_read_unlock();
-
- target->sta_id = mvmvif->deflink.ap_sta_id;
} else {
target->sta_id = IWL_MVM_INVALID_STA;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
index 1b6fb73ddfc7..b49781d1a07a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
@@ -104,7 +104,8 @@ iwl_mvm_ftm_responder_set_ndp(struct iwl_mvm *mvm,
static int
iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ struct ieee80211_bss_conf *link_conf)
{
u32 cmd_id = WIDE_ID(LOCATION_GROUP, TOF_RESPONDER_CONFIG_CMD);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -119,7 +120,7 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
IWL_TOF_RESPONDER_CMD_VALID_BSSID |
IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
- .sta_id = mvmvif->deflink.bcast_sta.sta_id,
+ .sta_id = mvmvif->link[link_conf->link_id]->bcast_sta.sta_id,
};
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 6);
int err;
@@ -386,7 +387,8 @@ int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,
return -EINVAL;
}
-int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_ftm_responder_params *params;
@@ -395,11 +397,11 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret;
- params = vif->bss_conf.ftmr_params;
+ params = bss_conf->ftmr_params;
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
+ if (WARN_ON_ONCE(!bss_conf->ftm_responder))
return -EINVAL;
if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
@@ -409,7 +411,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
}
rcu_read_lock();
- pctx = rcu_dereference(vif->bss_conf.chanctx_conf);
+ pctx = rcu_dereference(bss_conf->chanctx_conf);
/* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
* about changes in the ctx after releasing the lock because the driver
* is still protected by the mutex. */
@@ -424,7 +426,7 @@ int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (ret)
return ret;
- ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
+ ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def, bss_conf);
if (ret)
return ret;
@@ -446,13 +448,14 @@ void iwl_mvm_ftm_responder_clear(struct iwl_mvm *mvm,
}
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf)
{
- if (!vif->bss_conf.ftm_responder)
+ if (!bss_conf->ftm_responder)
return;
iwl_mvm_ftm_responder_clear(mvm, vif);
- iwl_mvm_ftm_start_responder(mvm, vif);
+ iwl_mvm_ftm_start_responder(mvm, vif, bss_conf);
}
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 205c09bc9863..1f5db65a088d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -433,7 +433,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
/* if reached this point, Alive notification was received */
iwl_mei_alive_notif(true);
- ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait);
+ ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait,
+ &mvm->fw->ucode_capa);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
@@ -477,40 +478,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return 0;
}
-#ifdef CONFIG_ACPI
-static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
- struct iwl_phy_specific_cfg *phy_filters)
-{
- /*
- * TODO: read specific phy config from BIOS
- * ACPI table for this feature has not been defined yet,
- * so for now we use hardcoded values.
- */
-
- if (IWL_MVM_PHY_FILTER_CHAIN_A) {
- phy_filters->filter_cfg_chain_a =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_B) {
- phy_filters->filter_cfg_chain_b =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_C) {
- phy_filters->filter_cfg_chain_c =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_D) {
- phy_filters->filter_cfg_chain_d =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
- }
-}
-#else /* CONFIG_ACPI */
-
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
struct iwl_phy_specific_cfg *phy_filters)
{
-}
+#ifdef CONFIG_ACPI
+ *phy_filters = mvm->phy_filters;
#endif /* CONFIG_ACPI */
+}
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
@@ -559,7 +533,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
u32 cmd_id = PHY_CONFIGURATION_CMD;
struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
- struct iwl_phy_specific_cfg phy_filters = {};
u8 cmd_ver;
size_t cmd_size;
@@ -590,11 +563,8 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
IWL_FW_CMD_VER_UNKNOWN);
- if (cmd_ver == 3) {
- iwl_mvm_phy_filter_init(mvm, &phy_filters);
- memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
- sizeof(struct iwl_phy_specific_cfg));
- }
+ if (cmd_ver >= 3)
+ iwl_mvm_phy_filter_init(mvm, &phy_cfg_cmd.phy_specific_cfg);
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
@@ -1104,7 +1074,26 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
},
},
-
+ { .ident = "Acer",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ },
+ },
+ { .ident = "ASUS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ },
+ },
+ { .ident = "MSI",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
+ },
+ },
+ { .ident = "Honor",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HONOR"),
+ },
+ },
/* keep last */
{}
};
@@ -1162,7 +1151,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
if (ret == 0)
return;
- if (!dmi_check_system(dmi_tas_approved_list)) {
+ if (!iwl_mvm_is_vendor_in_approved_list()) {
IWL_DEBUG_RADIO(mvm,
"System vendor '%s' is not in the approved list, disabling TAS in US and Canada.\n",
dmi_get_system_info(DMI_SYS_VENDOR));
@@ -1176,6 +1165,10 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
"Unable to add US/Canada to TAS block list, disabling TAS\n");
return;
}
+ } else {
+ IWL_DEBUG_RADIO(mvm,
+ "System vendor '%s' is in the approved list.\n",
+ dmi_get_system_info(DMI_SYS_VENDOR));
}
/* v4 is the same size as v3, so no need to differentiate here */
@@ -1356,6 +1349,8 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
/* we don't fail if the table is not available */
}
}
+
+ iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters);
}
#else /* CONFIG_ACPI */
@@ -1571,6 +1566,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
+ iwl_mvm_lari_cfg(mvm);
+
/* Init RSS configuration */
ret = iwl_configure_rxq(&mvm->fwrt);
if (ret)
@@ -1591,6 +1588,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
+ for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++)
+ RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL);
+
memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map));
mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
@@ -1610,7 +1610,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
* internal aux station for all aux activities that don't
* requires a dedicated data queue.
*/
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
/*
* In old version the aux station uses mac id like other
* station and not lmac id
@@ -1678,7 +1678,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
- iwl_mvm_lari_cfg(mvm);
/*
* RTNL is not taken during Ct-kill, but we don't need to scan/Tx
* anyway, so don't init MCC.
@@ -1699,9 +1698,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
- iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr,
- IWL_TIME_SYNC_PROTOCOL_TM |
- IWL_TIME_SYNC_PROTOCOL_FTM);
+
+ if (mvm->time_sync.active)
+ iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr,
+ IWL_TIME_SYNC_PROTOCOL_TM |
+ IWL_TIME_SYNC_PROTOCOL_FTM);
}
if (!mvm->ptp_data.ptp_clock)
@@ -1777,7 +1778,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL);
}
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
/*
* Add auxiliary station for scanning.
* Newer versions of this command implies that the fw uses
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 3814915cb1a6..ace82e2c5bd9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -63,6 +63,9 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvmvif);
if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)
return -EINVAL;
+
+ rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id],
+ link_conf);
}
/* Update SF - Disable if needed. if this fails, SF might still be on
@@ -73,6 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
cmd.mac_id = cpu_to_le32(mvmvif->id);
+ cmd.spec_link_id = link_conf->link_id;
/* P2P-Device already has a valid PHY context during add */
phyctxt = link_info->phy_ctxt;
if (phyctxt)
@@ -85,6 +89,8 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
+ cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
+
return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD);
}
@@ -114,24 +120,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (!link_info->phy_ctxt)
return 0;
- /* check there aren't too many active links */
- if (!link_info->active && active) {
- int i, count = 0;
-
- /* link with phy_ctxt is active in FW */
- for_each_mvm_vif_valid_link(mvmvif, i)
- if (mvmvif->link[i]->phy_ctxt)
- count++;
-
- if (vif->type == NL80211_IFTYPE_AP) {
- if (count > mvm->fw->ucode_capa.num_beacons)
- return -EOPNOTSUPP;
- /* this should be per HW or such */
- } else if (count >= IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM) {
- return -EOPNOTSUPP;
- }
- }
-
/* Catch early if driver tries to activate or deactivate a link
* twice.
*/
@@ -163,10 +151,6 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
memcpy(cmd.ibss_bssid_addr, link_conf->bssid, ETH_ALEN);
- /* TODO: set a value to cmd.listen_lmac when system requiremens
- * will define it
- */
-
iwl_mvm_set_fw_basic_rates(mvm, vif, link_conf,
&cmd.cck_rates, &cmd.ofdm_rates);
@@ -179,7 +163,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
&cmd.protection_flags,
ht_flag, LINK_PROT_FLG_TGG_PROTECT);
- iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, &cmd.ac[0],
+ iwl_mvm_set_fw_qos_params(mvm, vif, link_conf, cmd.ac,
&cmd.qos_flags);
@@ -204,7 +188,7 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* TODO how to set ndp_fdbk_buff_th_exp? */
- if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif,
+ if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif->link[link_id],
&cmd.trig_based_txf[0])) {
flags |= LINK_FLG_MU_EDCA_CW;
flags_mask |= LINK_FLG_MU_EDCA_CW;
@@ -241,6 +225,8 @@ send_cmd:
cmd.modify_mask = cpu_to_le32(changes);
cmd.flags = cpu_to_le32(flags);
cmd.flags_mask = cpu_to_le32(flags_mask);
+ cmd.spec_link_id = link_conf->link_id;
+ cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac);
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_MODIFY);
if (!ret && (changes & LINK_CONTEXT_MODIFY_ACTIVE))
@@ -262,9 +248,12 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID))
return -EINVAL;
+ RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id],
+ NULL);
cmd.link_id = cpu_to_le32(link_info->fw_link_id);
iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id);
link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
+ cmd.spec_link_id = link_conf->link_id;
ret = iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_REMOVE);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index cc90f2884cff..7369a45f7f2b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -470,19 +470,24 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_ac_qos *ac, __le32 *qos_flags)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link =
+ mvmvif->link[link_conf->link_id];
int i;
+ if (!mvm_link)
+ return;
+
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u8 txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, i);
u8 ucode_ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
ac[ucode_ac].cw_min =
- cpu_to_le16(mvmvif->deflink.queue_params[i].cw_min);
+ cpu_to_le16(mvm_link->queue_params[i].cw_min);
ac[ucode_ac].cw_max =
- cpu_to_le16(mvmvif->deflink.queue_params[i].cw_max);
+ cpu_to_le16(mvm_link->queue_params[i].cw_max);
ac[ucode_ac].edca_txop =
- cpu_to_le16(mvmvif->deflink.queue_params[i].txop * 32);
- ac[ucode_ac].aifsn = mvmvif->deflink.queue_params[i].aifs;
+ cpu_to_le16(mvm_link->queue_params[i].txop * 32);
+ ac[ucode_ac].aifsn = mvm_link->queue_params[i].aifs;
ac[ucode_ac].fifos_mask = BIT(txf);
}
@@ -558,7 +563,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
cmd->filter_flags = 0;
- iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, &cmd->ac[0],
+ iwl_mvm_set_fw_qos_params(mvm, vif, &vif->bss_conf, cmd->ac,
&cmd->qos_flags);
/* The fw does not distinguish between ht and fat */
@@ -629,17 +634,17 @@ __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
}
-__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
- __le32 twt_policy = cpu_to_le32(0);
+ u32 twt_policy = 0;
if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT)
- twt_policy |= cpu_to_le32(TWT_SUPPORTED);
+ twt_policy |= TWT_SUPPORTED;
if (vif->bss_conf.twt_protected)
- twt_policy |= cpu_to_le32(PROTECTED_TWT_SUPPORTED);
+ twt_policy |= PROTECTED_TWT_SUPPORTED;
if (vif->bss_conf.twt_broadcast)
- twt_policy |= cpu_to_le32(BROADCAST_TWT_SUPPORTED);
+ twt_policy |= BROADCAST_TWT_SUPPORTED;
return twt_policy;
}
@@ -711,7 +716,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX);
ctxt_sta->data_policy |=
- iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
+ cpu_to_le32(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
}
@@ -888,7 +893,7 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
u8 rate;
u32 i;
- if (link_id == IEEE80211_LINK_UNSPECIFIED && vif->valid_links) {
+ if (link_id == IEEE80211_LINK_UNSPECIFIED && ieee80211_vif_is_mld(vif)) {
for (i = 0; i < ARRAY_SIZE(mvmvif->link); i++) {
if (!mvmvif->link[i])
continue;
@@ -1111,6 +1116,10 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
beacon_cmd.flags = cpu_to_le16(flags);
beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
+
+ if (WARN_ON(!mvmvif->link[link_conf->link_id]))
+ return -EINVAL;
+
if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
beacon_cmd.link_id =
cpu_to_le32(mvmvif->link[link_conf->link_id]->fw_link_id);
@@ -1555,21 +1564,38 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx;
u32 rx_missed_bcon, rx_missed_bcon_since_rx;
struct ieee80211_vif *vif;
- u32 id = le32_to_cpu(mb->mac_id);
+ /* Id can be mac/link id depending on the notification version */
+ u32 id = le32_to_cpu(mb->link_id);
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
u32 mac_type;
+ u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+ MISSED_BEACONS_NOTIFICATION,
+ 0);
+
+ rcu_read_lock();
+
+ /* before version four the ID in the notification refers to mac ID */
+ if (notif_ver < 4) {
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
+ } else {
+ struct ieee80211_bss_conf *bss_conf =
+ iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true);
+
+ if (!bss_conf)
+ goto out;
+
+ vif = bss_conf->vif;
+ }
IWL_DEBUG_INFO(mvm,
- "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n",
- le32_to_cpu(mb->mac_id),
+ "missed bcn %s_id=%u, consecutive=%u (%u, %u, %u)\n",
+ notif_ver < 4 ? "mac" : "link",
+ id,
le32_to_cpu(mb->consec_missed_beacons),
le32_to_cpu(mb->consec_missed_beacons_since_last_rx),
le32_to_cpu(mb->num_recvd_beacons),
le32_to_cpu(mb->num_expected_beacons));
- rcu_read_lock();
-
- vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true);
if (!vif)
goto out;
@@ -1730,20 +1756,47 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
struct ieee80211_vif *csa_vif, *vif;
- struct iwl_mvm_vif *mvmvif;
- u32 id_n_color, csa_id, mac_id;
+ struct iwl_mvm_vif *mvmvif, *csa_mvmvif;
+ u32 id_n_color, csa_id;
+ /* save mac_id or link_id to use later to cancel csa if needed */
+ u32 id;
+ u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
+ CHANNEL_SWITCH_START_NOTIF, 0);
+ bool csa_active;
- id_n_color = le32_to_cpu(notif->id_and_color);
- mac_id = id_n_color & FW_CTXT_ID_MSK;
+ rcu_read_lock();
- if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER))
- return;
+ if (notif_ver < 3) {
+ struct iwl_channel_switch_start_notif_v1 *notif = (void *)pkt->data;
+ u32 mac_id;
+
+ id_n_color = le32_to_cpu(notif->id_and_color);
+ mac_id = id_n_color & FW_CTXT_ID_MSK;
+
+ vif = iwl_mvm_rcu_dereference_vif_id(mvm, mac_id, true);
+ if (!vif)
+ goto out_unlock;
+
+ id = mac_id;
+ csa_active = vif->bss_conf.csa_active;
+ } else {
+ struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
+ u32 link_id = le32_to_cpu(notif->link_id);
+ struct ieee80211_bss_conf *bss_conf =
+ iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true);
+
+ if (!bss_conf)
+ goto out_unlock;
+
+ id = link_id;
+ vif = bss_conf->vif;
+ csa_active = bss_conf->csa_active;
+ }
- rcu_read_lock();
- vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ if (notif_ver >= 3)
+ id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -1752,7 +1805,8 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
csa_vif != vif))
goto out_unlock;
- csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color);
+ csa_mvmvif = iwl_mvm_vif_from_mac80211(csa_vif);
+ csa_id = FW_CMD_ID_AND_COLOR(csa_mvmvif->id, csa_mvmvif->color);
if (WARN(csa_id != id_n_color,
"channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)",
csa_id, id_n_color))
@@ -1777,9 +1831,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
*/
if (iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
CHANNEL_SWITCH_ERROR_NOTIF,
- 0) && !vif->bss_conf.csa_active) {
+ 0) && !csa_active) {
IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n");
- iwl_mvm_cancel_channel_switch(mvm, vif, mac_id);
+ iwl_mvm_cancel_channel_switch(mvm, vif, id);
break;
}
@@ -1802,7 +1856,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_channel_switch_error_notif *notif = (void *)pkt->data;
struct ieee80211_vif *vif;
- u32 id = le32_to_cpu(notif->mac_id);
+ u32 id = le32_to_cpu(notif->link_id);
u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask);
rcu_read_lock();
@@ -1812,7 +1866,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
return;
}
- IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n",
+ IWL_DEBUG_INFO(mvm, "FW reports CSA error: id=%u, csa_err_mask=%u\n",
id, csa_err_mask);
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
CS_ERR_LONG_DELAY_AFTER_CS |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 17f788a5ff6b..ce7905faa08f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -108,7 +108,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
struct ieee80211_regdomain *regd = NULL;
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mcc_update_resp *resp;
+ struct iwl_mcc_update_resp_v8 *resp;
u8 resp_ver;
IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
@@ -138,7 +138,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
resp->channels,
__le16_to_cpu(resp->mcc),
__le16_to_cpu(resp->geo_info),
- __le16_to_cpu(resp->cap), resp_ver);
+ le32_to_cpu(resp->cap), resp_ver);
/* Store the return source id */
src_id = resp->source_id;
if (IS_ERR_OR_NULL(regd)) {
@@ -245,12 +245,21 @@ static const u8 tm_if_types_ext_capa_sta[] = {
/* Additional interface types for which extended capabilities are
* specified separately
*/
+
+#define IWL_MVM_EMLSR_CAPA (IEEE80211_EML_CAP_EMLSR_SUPP | \
+ IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US << \
+ __bf_shf(IEEE80211_EML_CAP_EMLSR_PADDING_DELAY) | \
+ IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US << \
+ __bf_shf(IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY))
+
static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
{
.iftype = NL80211_IFTYPE_STATION,
.extended_capabilities = he_if_types_ext_capa_sta,
.extended_capabilities_mask = he_if_types_ext_capa_sta,
.extended_capabilities_len = sizeof(he_if_types_ext_capa_sta),
+ /* relevant only if EHT is supported */
+ .eml_capabilities = IWL_MVM_EMLSR_CAPA,
},
{
.iftype = NL80211_IFTYPE_STATION,
@@ -258,7 +267,7 @@ static const struct wiphy_iftype_ext_capab add_iftypes_ext_capa[] = {
.extended_capabilities_mask = tm_if_types_ext_capa_sta,
.extended_capabilities_len = sizeof(tm_if_types_ext_capa_sta),
/* relevant only if EHT is supported */
- .eml_capabilities = IEEE80211_EML_CAP_EMLSR_SUPP,
+ .eml_capabilities = IWL_MVM_EMLSR_CAPA,
},
};
@@ -1029,6 +1038,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
mvmvif->link[link_id]->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
mvmvif->link[link_id]->phy_ctxt = NULL;
mvmvif->link[link_id]->active = 0;
+ mvmvif->link[link_id]->igtk = NULL;
}
probe_data = rcu_dereference_protected(mvmvif->deflink.probe_resp_data,
@@ -1233,7 +1243,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
/* async_handlers_wk is now blocked */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12)
+ if (!iwl_mvm_has_new_station_api(mvm->fw))
iwl_mvm_rm_aux_sta(mvm);
iwl_mvm_stop_device(mvm);
@@ -1478,21 +1488,37 @@ iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef)
return (control_start - data_start) / 80;
}
-/*
- * Returns true if addding the interface is done
- * (either with success or failure)
- *
- * FIXME: remove this again and merge it in
- */
-static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
- struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- int *ret)
+static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
lockdep_assert_held(&mvm->mutex);
+ ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
+ if (ret) {
+ IWL_ERR(mvm, "Failed to allocate bcast sta\n");
+ return ret;
+ }
+
+ /* Only queue for this station is the mcast queue,
+ * which shouldn't be in TFD mask anyway
+ */
+ return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0,
+ vif->type,
+ IWL_STA_MULTICAST);
+}
+
+static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+
mvmvif->mvm = mvm;
/* the first link always points to the default one */
@@ -1510,12 +1536,18 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
mvmvif->deflink.beacon_stats.num_beacons;
/* Allocate resources for the MAC context, and add it to the fw */
- *ret = iwl_mvm_mac_ctxt_init(mvm, vif);
- if (*ret)
- return true;
+ ret = iwl_mvm_mac_ctxt_init(mvm, vif);
+ if (ret)
+ goto out;
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
+ /* Currently not much to do for NAN */
+ if (vif->type == NL80211_IFTYPE_NAN) {
+ ret = 0;
+ goto out;
+ }
+
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211
@@ -1530,50 +1562,12 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm,
if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
iwl_mvm_vif_dbgfs_register(mvm, vif);
- return true;
+ ret = 0;
+ goto out;
}
mvmvif->features |= hw->netdev_features;
- return false;
-}
-
-static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
- if (ret) {
- IWL_ERR(mvm, "Failed to allocate bcast sta\n");
- return ret;
- }
-
- /*
- * Only queue for this station is the mcast queue,
- * which shouldn't be in TFD mask anyway
- */
- return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0,
- vif->type,
- IWL_STA_MULTICAST);
-}
-
-static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- int ret;
-
- mutex_lock(&mvm->mutex);
-
- /* Common for MLD and non-MLD API */
- if (iwl_mvm_mac_add_interface_common(mvm, hw, vif, &ret))
- goto out;
-
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret)
goto out_unlock;
@@ -2246,7 +2240,7 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
* is enabled or not
*/
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
+ const struct iwl_mvm_vif_link_info *link_info,
struct iwl_he_backoff_conf *trig_based_txf)
{
int i;
@@ -2254,11 +2248,11 @@ bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
bool mu_edca_enabled = true;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
- &mvmvif->deflink.queue_params[i].mu_edca_param_rec;
+ const struct ieee80211_he_mu_edca_param_ac_rec *mu_edca =
+ &link_info->queue_params[i].mu_edca_param_rec;
u8 ac = iwl_mvm_mac80211_ac_to_ucode_ac(i);
- if (!mvmvif->deflink.queue_params[i].mu_edca) {
+ if (!link_info->queue_params[i].mu_edca) {
mu_edca_enabled = false;
break;
}
@@ -2285,8 +2279,7 @@ bool iwl_mvm_is_nic_ack_enabled(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
* so take it from one of them.
*/
sband = mvm->hw->wiphy->bands[NL80211_BAND_2GHZ];
- own_he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ own_he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
return (own_he_cap && (own_he_cap->he_cap_elem.mac_cap_info[2] &
IEEE80211_HE_MAC_CAP2_ACK_EN));
@@ -2405,7 +2398,7 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
rcu_read_unlock();
- if (iwl_mvm_set_fw_mu_edca_params(mvm, mvmvif,
+ if (iwl_mvm_set_fw_mu_edca_params(mvm, &mvmvif->deflink,
&sta_ctxt_cmd.trig_based_txf[0]))
flags |= STA_CTXT_HE_MU_EDCA_CW;
@@ -2898,7 +2891,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
- iwl_mvm_ftm_restart_responder(mvm, vif);
+ iwl_mvm_ftm_restart_responder(mvm, vif, &vif->bss_conf);
goto out_unlock;
@@ -3040,7 +3033,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
IWL_WARN(mvm, "Failed updating beacon data\n");
if (changes & BSS_CHANGED_FTM_RESPONDER) {
- int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif, &vif->bss_conf);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
@@ -3054,7 +3047,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u64 changes)
{
- struct iwl_mvm_bss_info_changed_ops callbacks = {
+ static const struct iwl_mvm_bss_info_changed_ops callbacks = {
.bss_info_changed_sta = iwl_mvm_bss_info_changed_station,
.bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss,
};
@@ -3067,7 +3060,7 @@ void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- struct iwl_mvm_bss_info_changed_ops *callbacks,
+ const struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -3468,8 +3461,7 @@ static void iwl_mvm_reset_cca_40mhz_workaround(struct iwl_mvm *mvm,
sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
if (he_cap) {
/* we know that ours is writable */
@@ -3564,7 +3556,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
- struct iwl_mvm_sta_state_ops callbacks = {
+ static const struct iwl_mvm_sta_state_ops callbacks = {
.add_sta = iwl_mvm_add_sta,
.update_sta = iwl_mvm_update_sta,
.rm_sta = iwl_mvm_rm_sta,
@@ -3669,7 +3661,7 @@ static int
iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_link_sta *link_sta;
@@ -3713,7 +3705,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -3770,7 +3762,7 @@ static int
iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -3805,11 +3797,10 @@ static int
iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- int ret;
lockdep_assert_held(&mvm->mutex);
@@ -3828,10 +3819,7 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
mvmvif->authorized = 0;
/* disable beacon filtering */
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
- WARN_ON(ret &&
- !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
- &mvm->status));
+ iwl_mvm_disable_beacon_filter(mvm, vif, 0);
}
return 0;
@@ -3843,11 +3831,12 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state,
- struct iwl_mvm_sta_state_ops *callbacks)
+ const struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_link_sta *link_sta;
unsigned int link_id;
int ret;
@@ -3889,7 +3878,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
/* this would be a mac80211 bug ... but don't crash */
- for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ for_each_sta_active_link(vif, sta, link_sta, link_id) {
if (WARN_ON_ONCE(!mvmvif->link[link_id]->phy_ctxt)) {
mutex_unlock(&mvm->mutex);
return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
@@ -4533,7 +4522,7 @@ static int iwl_mvm_add_aux_sta_for_hs20(struct iwl_mvm *mvm, u32 lmac_id)
return -EINVAL;
}
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12) {
+ if (iwl_mvm_has_new_station_api(mvm->fw)) {
ret = iwl_mvm_add_aux_sta(mvm, lmac_id);
WARN(ret, "Failed to allocate aux station");
}
@@ -4573,7 +4562,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
int duration,
enum ieee80211_roc_type type)
{
- struct iwl_mvm_roc_ops ops = {
+ static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20,
.switch_phy_ctxt = iwl_mvm_roc_switch_binding,
};
@@ -4585,7 +4574,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
- struct iwl_mvm_roc_ops *ops)
+ const struct iwl_mvm_roc_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -4608,7 +4597,7 @@ int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- lmac_id = iwl_mvm_get_lmac_id(mvm->fw, channel->band);
+ lmac_id = iwl_mvm_get_lmac_id(mvm, channel->band);
/* Use aux roc framework (HS20) */
ret = ops->add_aux_sta_for_hs20(mvm, lmac_id);
@@ -5092,7 +5081,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
static int
iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
int ret;
@@ -5151,7 +5140,7 @@ out:
static int
iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
struct ieee80211_vif_chanctx_switch *vifs,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
int ret;
@@ -5194,7 +5183,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
- struct iwl_mvm_switch_vif_chanctx_ops *ops)
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
@@ -5223,7 +5212,7 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
- struct iwl_mvm_switch_vif_chanctx_ops ops = {
+ static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx,
};
@@ -5664,6 +5653,30 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
}
+void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int i;
+
+ mutex_lock(&mvm->mutex);
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
+ struct iwl_mvm_sta *mvmsta;
+ struct ieee80211_sta *tmp;
+
+ tmp = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+ lockdep_is_held(&mvm->mutex));
+ if (tmp != sta)
+ continue;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (iwl_mvm_flush_sta(mvm, mvmsta, false))
+ IWL_ERR(mvm, "flush request fail\n");
+ }
+ mutex_unlock(&mvm->mutex);
+}
+
int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
@@ -6154,10 +6167,6 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- if (iwl_mvm_has_new_tx_csum(mvm))
- return iwl_mvm_tx_csum_bz(mvm, head, true) ==
- iwl_mvm_tx_csum_bz(mvm, skb, true);
-
/* For now don't aggregate IPv6 in AMSDU */
if (skb->protocol != htons(ETH_P_IP))
return false;
@@ -6220,6 +6229,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
.flush = iwl_mvm_mac_flush,
+ .flush_sta = iwl_mvm_mac_flush_sta,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -6277,7 +6287,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate,
#ifdef CONFIG_IWLWIFI_DEBUGFS
- .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
+ .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
#endif
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
index 8853821b3716..2c9f2f71b083 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#include <linux/kernel.h>
#include <net/mac80211.h>
@@ -42,7 +42,7 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
* Of course the same can be done during add as well, but we must do
* it during remove, since we don't have the mvmvif->ap_sta pointer.
*/
- if (!sta && (keyconf->link_id >= 0 || !vif->valid_links))
+ if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif)))
return BIT(link_info->ap_sta_id);
/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
@@ -51,10 +51,10 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
}
-static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *keyconf)
+u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u32 flags = 0;
@@ -164,13 +164,9 @@ static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
}
-int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *keyconf)
+int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
+ struct ieee80211_key_conf *keyconf)
{
- u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
- u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
struct iwl_sec_key_cmd cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
@@ -179,9 +175,14 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
.u.add.key_flags = cpu_to_le32(key_flags),
.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
};
+ int max_key_len = sizeof(cmd.u.add.key);
int ret;
- if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key)))
+ if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+ keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
+ max_key_len -= IWL_SEC_WEP_KEY_OFFSET;
+
+ if (WARN_ON(keyconf->keylen > max_key_len))
return -EINVAL;
if (WARN_ON(!sta_mask))
@@ -223,6 +224,58 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
return ret;
}
+int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf)
+{
+ u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
+ u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link = NULL;
+ int ret;
+
+ if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
+ unsigned int link_id = 0;
+
+ /* set to -1 for non-MLO right now */
+ if (keyconf->link_id >= 0)
+ link_id = keyconf->link_id;
+
+ mvm_link = mvmvif->link[link_id];
+ if (WARN_ON(!mvm_link))
+ return -EINVAL;
+
+ if (mvm_link->igtk) {
+ IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n",
+ mvm_link->igtk->keyidx);
+ ret = iwl_mvm_sec_key_del(mvm, vif, sta,
+ mvm_link->igtk);
+ if (ret)
+ IWL_ERR(mvm,
+ "failed to remove old IGTK (ret=%d)\n",
+ ret);
+ }
+
+ WARN_ON(mvm_link->igtk);
+ }
+
+ ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
+ if (ret)
+ return ret;
+
+ if (mvm_link)
+ mvm_link->igtk = keyconf;
+
+ /* We don't really need this, but need it to be not invalid,
+ * and if we switch links multiple times it might go to be
+ * invalid when removed.
+ */
+ keyconf->hw_key_idx = 0;
+
+ return 0;
+}
+
static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -231,11 +284,31 @@ static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
{
u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
if (WARN_ON(!sta_mask))
return -EINVAL;
+ if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
+ struct iwl_mvm_vif_link_info *mvm_link;
+ unsigned int link_id = 0;
+
+ /* set to -1 for non-MLO right now */
+ if (keyconf->link_id >= 0)
+ link_id = keyconf->link_id;
+
+ mvm_link = mvmvif->link[link_id];
+ if (WARN_ON(!mvm_link))
+ return -EINVAL;
+
+ if (mvm_link->igtk == keyconf) {
+ /* no longer in HW - mark for later */
+ mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
+ mvm_link->igtk = NULL;
+ }
+ }
+
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
flags);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
index 1717fb52dc12..f313a8d771e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022 - 2023 Intel Corporation
*/
#include "mvm.h"
@@ -50,7 +50,7 @@ static void iwl_mvm_mld_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
* the association response successfully, so just skip all that
* and enable both when we have MLO.
*/
- if (vif->valid_links) {
+ if (ieee80211_vif_is_mld(vif)) {
iwl_mvm_mld_set_he_support(mvm, vif, cmd);
cmd->eht_support = cpu_to_le32(1);
return;
@@ -96,6 +96,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
u32 action, bool force_assoc_off)
{
struct iwl_mac_config_cmd cmd = {};
+ u16 esr_transition_timeout;
WARN_ON(vif->type != NL80211_IFTYPE_STATION);
@@ -115,16 +116,16 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
if (vif->cfg.assoc && !force_assoc_off) {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- cmd.client.is_assoc = cpu_to_le32(1);
+ cmd.client.is_assoc = 1;
if (!mvmvif->authorized &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
cmd.client.data_policy |=
- cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
+ cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE);
} else {
- cmd.client.is_assoc = cpu_to_le32(0);
+ cmd.client.is_assoc = 0;
/* Allow beacons to pass through as long as we are not
* associated, or we do not have dtim period information.
@@ -132,14 +133,25 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON);
}
- cmd.client.assoc_id = cpu_to_le32(vif->cfg.aid);
+ cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid);
+ if (ieee80211_vif_is_mld(vif)) {
+ esr_transition_timeout =
+ u16_get_bits(vif->cfg.eml_cap,
+ IEEE80211_EML_CAP_TRANSITION_TIMEOUT);
+
+ cmd.client.esr_transition_timeout =
+ min_t(u16, IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU,
+ esr_transition_timeout);
+ cmd.client.medium_sync_delay =
+ cpu_to_le16(vif->cfg.eml_med_sync_delay);
+ }
if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p)
cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ);
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax)
cmd.client.data_policy |=
- iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif);
+ cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif));
return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 7fb66c570959..8b6c641772ee 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
*/
#include "mvm.h"
@@ -215,6 +215,53 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}
+static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
+{
+ unsigned int n_active = 0;
+ int i;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ struct ieee80211_bss_conf *link_conf;
+
+ link_conf = link_conf_dereference_protected(vif, i);
+ if (link_conf &&
+ rcu_access_pointer(link_conf->chanctx_conf))
+ n_active++;
+ }
+
+ return n_active;
+}
+
+static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int link_id, ret = 0;
+
+ mvmvif->esr_active = true;
+
+ /* Disable SMPS overrideing by user */
+ vif->driver_flags |= IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
+
+ iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
+ IEEE80211_SMPS_OFF);
+
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
+
+ if (!link->phy_ctxt)
+ continue;
+
+ ret = iwl_mvm_phy_send_rlc(mvm, link->phy_ctxt, 2, 2);
+ if (ret)
+ break;
+
+ link->phy_ctxt->rlc_disabled = true;
+ }
+
+ return ret;
+}
+
static int
__iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -224,10 +271,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
{
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id = link_conf->link_id;
int ret;
+ /* if the assigned one was not counted yet, count it now */
+ if (!rcu_access_pointer(link_conf->chanctx_conf))
+ n_active++;
+
+ if (n_active > iwl_mvm_max_active_links(mvm, vif))
+ return -EOPNOTSUPP;
+
if (WARN_ON_ONCE(!mvmvif->link[link_id]))
return -EINVAL;
@@ -243,6 +298,15 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
}
}
+ if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
+ mvmvif->link[link_id]->listen_lmac = true;
+ ret = iwl_mvm_esr_mode_active(mvm, vif);
+ if (ret) {
+ IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret);
+ return ret;
+ }
+ }
+
mvmvif->link[link_id]->phy_ctxt = phy_ctxt;
if (switching_chanctx) {
@@ -326,14 +390,62 @@ static int iwl_mvm_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
return ret;
}
+static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ int link_id, ret = 0;
+
+ mvmvif->esr_active = false;
+
+ vif->driver_flags &= ~IEEE80211_VIF_DISABLE_SMPS_OVERRIDE;
+
+ iwl_mvm_update_smps_on_active_links(mvm, vif, IWL_MVM_SMPS_REQ_FW,
+ IEEE80211_SMPS_AUTOMATIC);
+
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct iwl_mvm_phy_ctxt *phy_ctxt;
+ u8 static_chains, dynamic_chains;
+
+ mvmvif->link[link_id]->listen_lmac = false;
+
+ rcu_read_lock();
+
+ chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
+ phy_ctxt = mvmvif->link[link_id]->phy_ctxt;
+
+ if (!chanctx_conf || !phy_ctxt) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ phy_ctxt->rlc_disabled = false;
+ static_chains = chanctx_conf->rx_chains_static;
+ dynamic_chains = chanctx_conf->rx_chains_dynamic;
+
+ rcu_read_unlock();
+
+ ret = iwl_mvm_phy_send_rlc(mvm, phy_ctxt, static_chains,
+ dynamic_chains);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
static void
__iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_chanctx_conf *ctx,
bool switching_chanctx)
+
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
unsigned int link_id = link_conf->link_id;
/* shouldn't happen, but verify link_id is valid before accessing */
@@ -352,6 +464,14 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
mvmvif->ap_ibss_active = false;
}
+ if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
+ int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
+
+ if (ret)
+ IWL_ERR(mvm, "failed to deactivate ESR mode (%d)\n",
+ ret);
+ }
+
if (vif->type == NL80211_IFTYPE_MONITOR)
iwl_mvm_mld_rm_snif_sta(mvm, vif);
@@ -422,7 +542,7 @@ static int iwl_mvm_mld_start_ap_ibss(struct ieee80211_hw *hw,
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
- iwl_mvm_ftm_restart_responder(mvm, vif);
+ iwl_mvm_ftm_restart_responder(mvm, vif, link_conf);
goto out_unlock;
@@ -492,7 +612,7 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state)
{
- struct iwl_mvm_sta_state_ops callbacks = {
+ static const struct iwl_mvm_sta_state_ops callbacks = {
.add_sta = iwl_mvm_mld_add_sta,
.update_sta = iwl_mvm_mld_update_sta,
.rm_sta = iwl_mvm_mld_rm_sta,
@@ -697,7 +817,11 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (link_conf->he_support)
link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS;
- if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
+ if (changes & BSS_CHANGED_ERP_SLOT)
+ link_changes |= LINK_CONTEXT_MODIFY_RATES_INFO;
+
+ if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_SLOT |
+ BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH | BSS_CHANGED_QOS |
BSS_CHANGED_HE_BSS_COLOR) &&
iwl_mvm_link_changed(mvm, vif, link_conf,
@@ -711,7 +835,7 @@ iwl_mvm_mld_link_info_changed_ap_ibss(struct iwl_mvm *mvm,
/* FIXME: need to decide if we need FTM responder per link */
if (changes & BSS_CHANGED_FTM_RESPONDER) {
- int ret = iwl_mvm_ftm_start_responder(mvm, vif);
+ int ret = iwl_mvm_ftm_start_responder(mvm, vif, link_conf);
if (ret)
IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n",
@@ -779,7 +903,7 @@ iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode)
{
- struct iwl_mvm_switch_vif_chanctx_ops ops = {
+ static const struct iwl_mvm_switch_vif_chanctx_ops ops = {
.__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx,
.__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx,
};
@@ -816,8 +940,12 @@ iwl_mvm_mld_mac_conf_tx(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];
- mvmvif->deflink.queue_params[ac] = *params;
+ if (!mvm_link)
+ return -EINVAL;
+
+ mvm_link->queue_params[ac] = *params;
/* No need to update right away, we'll get BSS_CHANGED_QOS
* The exception is P2P_DEVICE interface which needs immediate update.
@@ -871,7 +999,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type)
{
- struct iwl_mvm_roc_ops ops = {
+ static const struct iwl_mvm_roc_ops ops = {
.add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta,
.switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx,
};
@@ -886,33 +1014,16 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
{
struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
+ unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 removed = old_links & ~new_links;
u16 added = new_links & ~old_links;
int err, i;
- if (hweight16(new_links) > 2) {
+ if (hweight16(new_links) > 1 &&
+ n_active > iwl_mvm_max_active_links(mvm, vif))
return -EOPNOTSUPP;
- } else if (hweight16(new_links) > 1) {
- unsigned int n_active = 0;
-
- for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
- struct ieee80211_bss_conf *link_conf;
-
- link_conf = link_conf_dereference_protected(vif, i);
- if (link_conf &&
- rcu_access_pointer(link_conf->chanctx_conf))
- n_active++;
- }
-
- if (vif->type == NL80211_IFTYPE_AP) {
- if (n_active > mvm->fw->ucode_capa.num_beacons)
- return -EOPNOTSUPP;
- } else if (n_active > 1) {
- return -EOPNOTSUPP;
- }
- }
for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
int r;
@@ -956,9 +1067,7 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
goto out_err;
kfree(mvmvif->link[i]);
mvmvif->link[i] = NULL;
- }
-
- if (added & BIT(i)) {
+ } else if (added & BIT(i)) {
struct ieee80211_bss_conf *link_conf;
link_conf = link_conf_dereference_protected(vif, i);
@@ -975,6 +1084,9 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
}
}
+ if (err)
+ goto out_err;
+
err = 0;
if (new_links == 0) {
mvmvif->link[0] = &mvmvif->deflink;
@@ -1037,6 +1149,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
.mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
.flush = iwl_mvm_mac_flush,
+ .flush_sta = iwl_mvm_mac_flush_sta,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -1093,7 +1206,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
.abort_pmsr = iwl_mvm_abort_pmsr,
#ifdef CONFIG_IWLWIFI_DEBUGFS
- .sta_add_debugfs = iwl_mvm_sta_add_debugfs,
+ .link_sta_add_debugfs = iwl_mvm_link_sta_add_debugfs,
#endif
.set_hw_timestamp = iwl_mvm_set_hw_timestamp,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
index 85a4ce8449ad..524852cf5cd2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2022 Intel Corporation
+ * Copyright (C) 2022-2023 Intel Corporation
*/
#include "mvm.h"
#include "time-sync.h"
@@ -71,6 +71,11 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm,
cmd.station_type = cpu_to_le32(sta->type);
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) &&
+ sta->type == STATION_TYPE_BCAST_MGMT)
+ cmd.mfp = cpu_to_le32(1);
+
if (addr) {
memcpy(cmd.peer_mld_address, addr, ETH_ALEN);
memcpy(cmd.peer_link_address, addr, ETH_ALEN);
@@ -128,11 +133,11 @@ static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm,
/*
* Adds an internal sta to the FW table with its queues
*/
-static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
- struct iwl_mvm_int_sta *sta,
- const u8 *addr, int link_id,
- u16 *queue, u8 tid,
- unsigned int *_wdg_timeout)
+int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta,
+ const u8 *addr, int link_id,
+ u16 *queue, u8 tid,
+ unsigned int *_wdg_timeout)
{
int ret, txq;
unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout :
@@ -364,6 +369,9 @@ int iwl_mvm_mld_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
+ if (WARN_ON(!link))
+ return -EIO;
+
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
@@ -393,6 +401,9 @@ int iwl_mvm_mld_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex);
+ if (WARN_ON(!link))
+ return -EIO;
+
return iwl_mvm_mld_rm_int_sta(mvm, &link->mcast_sta, true, 0,
&link->cab_queue);
}
@@ -442,6 +453,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC)
cmd.assoc_id = cpu_to_le32(sta->aid);
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) &&
+ (sta->mfp || mvm_sta->sta_state < IEEE80211_STA_AUTHORIZED))
+ cmd.mfp = cpu_to_le32(1);
+
switch (link_sta->rx_nss) {
case 1:
cmd.mimo = cpu_to_le32(0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 9e5008e0e47f..b18c91c5dd5d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -104,6 +104,7 @@ struct iwl_mvm_phy_ctxt {
/* track for RLC config command */
u32 center_freq1;
+ bool rlc_disabled;
};
struct iwl_mvm_time_event_data {
@@ -300,6 +301,8 @@ struct iwl_probe_resp_data {
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked
* @queue_params: QoS params for this MAC
* @mgmt_queue: queue number for unbufferable management frames
+ * @igtk: the current IGTK programmed into the firmware
+ * @listen_lmac: indicates this link is allocated to the listen LMAC
*/
struct iwl_mvm_vif_link_info {
u8 bssid[ETH_ALEN];
@@ -317,8 +320,11 @@ struct iwl_mvm_vif_link_info {
enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ];
struct iwl_probe_resp_data __rcu *probe_resp_data;
+ struct ieee80211_key_conf *igtk;
+
bool he_ru_2mhz_block;
bool active;
+ bool listen_lmac;
u16 cab_queue;
/* Assigned while mac80211 has the link in a channel context,
@@ -370,6 +376,7 @@ struct iwl_mvm_vif {
bool ap_ibss_active;
bool pm_enabled;
bool monitor_active;
+ bool esr_active;
u8 low_latency: 6;
u8 low_latency_actual: 1;
@@ -415,7 +422,7 @@ struct iwl_mvm_vif {
#endif
/* FW identified misbehaving AP */
- u8 uapsd_misbehaving_bssid[ETH_ALEN];
+ u8 uapsd_misbehaving_ap_addr[ETH_ALEN] __aligned(2);
struct delayed_work uapsd_nonagg_detected_wk;
bool csa_countdown;
@@ -1003,6 +1010,8 @@ struct iwl_mvm {
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
+ struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_MVM_FW_MAX_LINK_ID + 1];
+
/* -1 for always, 0 for never, >0 for that many times */
s8 fw_restart;
u8 *error_recovery_buf;
@@ -1174,6 +1183,10 @@ struct iwl_mvm {
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
+#ifdef CONFIG_ACPI
+ struct iwl_phy_specific_cfg phy_filters;
+#endif
+
unsigned long last_6ghz_passive_scan_jiffies;
unsigned long last_reset_or_resume_time_jiffies;
@@ -1302,6 +1315,19 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex));
}
+static inline struct ieee80211_bss_conf *
+iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu)
+{
+ if (WARN_ON(link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf)))
+ return NULL;
+
+ if (rcu)
+ return rcu_dereference(mvm->link_id_to_link_conf[link_id]);
+
+ return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id],
+ lockdep_is_held(&mvm->mutex));
+}
+
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
@@ -1415,10 +1441,16 @@ static inline bool iwl_mvm_has_mld_api(const struct iwl_fw *fw)
IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT);
}
+static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw)
+{
+ return iwl_mvm_has_mld_api(fw) ||
+ iwl_fw_lookup_cmd_ver(fw, ADD_STA, 0) >= 12;
+}
+
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{
/* TODO - replace with TLV once defined */
- return mvm->trans->trans_cfg->use_tfh;
+ return mvm->trans->trans_cfg->gen2;
}
static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
@@ -1516,17 +1548,30 @@ static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CTDP_SUPPORT);
}
-static inline bool iwl_mvm_has_new_tx_csum(struct iwl_mvm *mvm)
+static inline bool iwl_mvm_is_esr_supported(struct iwl_trans *trans)
+{
+ if ((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM) &&
+ !CSR_HW_RFID_IS_CDB(trans->hw_rf_id))
+ /* Step A doesn't support eSR */
+ return CSR_HW_RFID_STEP(trans->hw_rf_id);
+
+ return false;
+}
+
+static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
- if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ)
- return false;
+ struct iwl_trans *trans = mvm->fwrt.trans;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ return mvm->fw->ucode_capa.num_beacons;
- if (mvm->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
- CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
- mvm->trans->hw_rev_step <= SILICON_B_STEP)
- return false;
+ if (iwl_mvm_is_esr_supported(trans) ||
+ (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
+ CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))
+ return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM;
- return true;
+ return 1;
}
extern const u8 iwl_mvm_ac_to_tx_fifo[];
@@ -1606,7 +1651,6 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
unsigned int tid);
-u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu);
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_mvm_get_tx_fail_reason(u32 status);
@@ -1741,6 +1785,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
+int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
+ u8 chains_static, u8 chains_dynamic);
/* MAC (virtual interface) programming */
@@ -1758,7 +1804,7 @@ void iwl_mvm_set_fw_qos_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct iwl_ac_qos *ac, __le32 *qos_flags);
bool iwl_mvm_set_fw_mu_edca_params(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
+ const struct iwl_mvm_vif_link_info *link_info,
struct iwl_he_backoff_conf *trig_based_txf);
void iwl_mvm_set_fw_dtim_tbtt(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
@@ -1774,8 +1820,8 @@ void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm,
int iwl_mvm_get_mac_type(struct ieee80211_vif *vif);
__le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
-__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif);
int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off);
@@ -1826,6 +1872,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band);
/* Links */
int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1873,7 +1920,7 @@ void
iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
- struct iwl_mvm_bss_info_changed_ops *callbacks,
+ const struct iwl_mvm_bss_info_changed_ops *callbacks,
u64 changes);
void
iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm,
@@ -1907,7 +1954,7 @@ struct iwl_mvm_roc_ops {
int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_channel *channel, int duration,
enum ieee80211_roc_type type,
- struct iwl_mvm_roc_ops *ops);
+ const struct iwl_mvm_roc_ops *ops);
int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
/*Session Protection */
@@ -2204,7 +2251,7 @@ static inline void iwl_mvm_vendor_cmds_register(struct iwl_mvm *mvm) {}
#endif
/* Location Aware Regulatory */
-struct iwl_mcc_update_resp *
+struct iwl_mcc_update_resp_v8 *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
enum iwl_mcc_source src_id);
int iwl_mvm_init_mcc(struct iwl_mvm *mvm);
@@ -2224,9 +2271,11 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif);
/* FTM responder */
-int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf);
void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf);
void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb);
int iwl_mvm_ftm_resp_remove_pasn_sta(struct iwl_mvm *mvm,
@@ -2322,10 +2371,10 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm);
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm);
#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct dentry *dir);
+void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ struct dentry *dir);
#endif
/* new MLD related APIs */
@@ -2346,6 +2395,12 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
u32 old_sta_mask,
u32 new_sta_mask);
+int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
+ struct ieee80211_key_conf *keyconf);
+u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *keyconf);
bool iwl_rfi_supported(struct iwl_mvm *mvm);
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm,
@@ -2406,7 +2461,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw,
struct ieee80211_vif_chanctx_switch *vifs,
int n_vifs,
enum ieee80211_chanctx_switch_mode mode,
- struct iwl_mvm_switch_vif_chanctx_ops *ops);
+ const struct iwl_mvm_switch_vif_chanctx_ops *ops);
/* Channel info utils */
static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm)
@@ -2604,6 +2659,8 @@ void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
struct ieee80211_prep_tx_info *info);
void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
+void iwl_mvm_mac_flush_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta);
int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index fdf60afb0f3f..f67ab8ee18c2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -404,7 +404,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
return ret < 0 ? ret : 0;
}
-struct iwl_mcc_update_resp *
+struct iwl_mcc_update_resp_v8 *
iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
enum iwl_mcc_source src_id)
{
@@ -412,7 +412,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
.source_id = (u8)src_id,
};
- struct iwl_mcc_update_resp *resp_cp;
+ struct iwl_mcc_update_resp_v8 *resp_cp;
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = MCC_UPDATE_CMD,
@@ -420,7 +420,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
.data = { &mcc_update_cmd },
};
- int ret;
+ int ret, resp_ver;
u32 status;
int resp_len, n_channels;
u16 mcc;
@@ -439,24 +439,60 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
pkt = cmd.resp_pkt;
+ resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+ MCC_UPDATE_CMD, 0);
+
/* Extract MCC response */
- if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
- struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
+ if (resp_ver >= 8) {
+ struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (void *)pkt->data;
+
+ n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
+ if (iwl_rx_packet_payload_len(pkt) !=
+ struct_size(mcc_resp_v8, channels, n_channels)) {
+ resp_cp = ERR_PTR(-EINVAL);
+ goto exit;
+ }
+ resp_len = struct_size(resp_cp, channels, n_channels);
+ resp_cp = kzalloc(resp_len, GFP_KERNEL);
+ if (!resp_cp) {
+ resp_cp = ERR_PTR(-ENOMEM);
+ goto exit;
+ }
+ resp_cp->status = mcc_resp_v8->status;
+ resp_cp->mcc = mcc_resp_v8->mcc;
+ resp_cp->cap = mcc_resp_v8->cap;
+ resp_cp->source_id = mcc_resp_v8->source_id;
+ resp_cp->time = mcc_resp_v8->time;
+ resp_cp->geo_info = mcc_resp_v8->geo_info;
+ resp_cp->n_channels = mcc_resp_v8->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v8->channels,
+ n_channels * sizeof(__le32));
+ } else if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
+ struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (void *)pkt->data;
- n_channels = __le32_to_cpu(mcc_resp->n_channels);
+ n_channels = __le32_to_cpu(mcc_resp_v4->n_channels);
if (iwl_rx_packet_payload_len(pkt) !=
- struct_size(mcc_resp, channels, n_channels)) {
+ struct_size(mcc_resp_v4, channels, n_channels)) {
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
- resp_len = sizeof(struct iwl_mcc_update_resp) +
- n_channels * sizeof(__le32);
- resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
+ resp_len = struct_size(resp_cp, channels, n_channels);
+ resp_cp = kzalloc(resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
goto exit;
}
+
+ resp_cp->status = mcc_resp_v4->status;
+ resp_cp->mcc = mcc_resp_v4->mcc;
+ resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap));
+ resp_cp->source_id = mcc_resp_v4->source_id;
+ resp_cp->time = mcc_resp_v4->time;
+ resp_cp->geo_info = mcc_resp_v4->geo_info;
+ resp_cp->n_channels = mcc_resp_v4->n_channels;
+ memcpy(resp_cp->channels, mcc_resp_v4->channels,
+ n_channels * sizeof(__le32));
} else {
struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
@@ -466,8 +502,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_cp = ERR_PTR(-EINVAL);
goto exit;
}
- resp_len = sizeof(struct iwl_mcc_update_resp) +
- n_channels * sizeof(__le32);
+ resp_len = struct_size(resp_cp, channels, n_channels);
resp_cp = kzalloc(resp_len, GFP_KERNEL);
if (!resp_cp) {
resp_cp = ERR_PTR(-ENOMEM);
@@ -476,7 +511,7 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
resp_cp->status = mcc_resp_v3->status;
resp_cp->mcc = mcc_resp_v3->mcc;
- resp_cp->cap = cpu_to_le16(mcc_resp_v3->cap);
+ resp_cp->cap = cpu_to_le32(mcc_resp_v3->cap);
resp_cp->source_id = mcc_resp_v3->source_id;
resp_cp->time = mcc_resp_v3->time;
resp_cp->geo_info = mcc_resp_v3->geo_info;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
index a8bd0f5f795c..dfb16ca5b438 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c
@@ -198,6 +198,10 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_OFFLOAD_BTM_SUPPORT))
+ enabled |= IWL_D3_PROTO_OFFLOAD_BTM;
+
if (!disable_offloading)
common->enabled = cpu_to_le32(enabled);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 32625bfacaae..5336a4afde4d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -192,8 +192,7 @@ static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm,
WARN_ON(!(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40));
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
+ he_cap = ieee80211_get_he_iftype_cap_vif(sband, vif);
if (he_cap) {
/* we know that ours is writable */
@@ -449,7 +448,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(ADD_STA_KEY),
HCMD_NAME(ADD_STA),
HCMD_NAME(REMOVE_STA),
- HCMD_NAME(FW_GET_ITEM_CMD),
HCMD_NAME(TX_CMD),
HCMD_NAME(SCD_QUEUE_CFG),
HCMD_NAME(TXPATH_FLUSH),
@@ -512,7 +510,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(REPLY_BEACON_FILTERING_CMD),
HCMD_NAME(D3_CONFIG_CMD),
HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD),
- HCMD_NAME(OFFLOADS_QUERY_CMD),
HCMD_NAME(MATCH_FOUND_NOTIFICATION),
HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION),
HCMD_NAME(WOWLAN_PATTERNS),
@@ -1604,7 +1601,9 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
if (rx_h->cmd_id != WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd))
continue;
- if (unlikely(pkt_len < rx_h->min_size))
+ if (IWL_FW_CHECK(mvm, pkt_len < rx_h->min_size,
+ "unexpected notification 0x%04x size %d, need %d\n",
+ rx_h->cmd_id, pkt_len, rx_h->min_size))
return;
if (rx_h->context == RX_HANDLER_SYNC) {
@@ -1743,8 +1742,11 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
else
set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
- if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
+ if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) {
+ local_bh_disable();
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
+ local_bh_enable();
+ }
}
out:
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 3ab6fb83a175..a5b432bc9e2f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -151,7 +151,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
- cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm->fw,
+ cmd->lmac_id = cpu_to_le32(iwl_mvm_get_lmac_id(mvm,
chandef->chan->band));
/* Set the channel info data */
@@ -163,15 +163,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
chains_static, chains_dynamic);
}
-static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm,
- struct iwl_mvm_phy_ctxt *ctxt,
- u8 chains_static, u8 chains_dynamic)
+int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
+ u8 chains_static, u8 chains_dynamic)
{
struct iwl_rlc_config_cmd cmd = {
.phy_id = cpu_to_le32(ctxt->id),
};
- if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP, RLC_CONFIG_CMD), 0) < 2)
+ if (ctxt->rlc_disabled)
+ return 0;
+
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, WIDE_ID(DATA_PATH_GROUP,
+ RLC_CONFIG_CMD), 0) < 2)
return 0;
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE !=
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index ac1dae52556f..9131b5f1bc76 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -237,8 +237,8 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
- ETH_ALEN))
+ if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr))
return false;
/*
@@ -327,12 +327,11 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
if (WARN_ON(!dtimper_tu))
return;
- /* configure skip over dtim up to 306TU - 314 msec */
- skip = max_t(u8, 1, 306 / dtimper_tu);
+ /* configure skip over dtim up to 900 TU DTIM interval */
+ skip = max_t(u8, 1, 900 / dtimper_tu);
}
- /* the firmware really expects "look at every X DTIMs", so add 1 */
- cmd->skip_dtim_periods = 1 + skip;
+ cmd->skip_dtim_periods = skip;
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
}
@@ -502,9 +501,9 @@ void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (memcmp(vif->bss_conf.bssid, mvmvif->uapsd_misbehaving_bssid,
- ETH_ALEN))
- eth_zero_addr(mvmvif->uapsd_misbehaving_bssid);
+ if (!ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr))
+ eth_zero_addr(mvmvif->uapsd_misbehaving_ap_addr);
}
static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
@@ -512,14 +511,23 @@ static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
{
u8 *ap_sta_id = _data;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_bss_conf *link_conf;
+ unsigned int link_id;
- /* The ap_sta_id is not expected to change during current association
- * so no explicit protection is needed
- */
- if (mvmvif->deflink.ap_sta_id == *ap_sta_id)
- memcpy(mvmvif->uapsd_misbehaving_bssid,
- vif->bss_conf.bssid,
- ETH_ALEN);
+ rcu_read_lock();
+ for_each_vif_active_link(vif, link_conf, link_id) {
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
+
+ /* The ap_sta_id is not expected to change during current
+ * association so no explicit protection is needed
+ */
+ if (link_info->ap_sta_id == *ap_sta_id) {
+ ether_addr_copy(mvmvif->uapsd_misbehaving_ap_addr,
+ vif->cfg.ap_addr);
+ break;
+ }
+ }
+ rcu_read_unlock();
}
void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
@@ -647,30 +655,32 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
return;
/* enable PM on bss if bss stand alone */
- if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
+ if (bss_mvmvif && vifs->bss_active && !vifs->p2p_active &&
+ !vifs->ap_active) {
bss_mvmvif->pm_enabled = true;
return;
}
/* enable PM on p2p if p2p stand alone */
- if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
+ if (p2p_mvmvif && vifs->p2p_active && !vifs->bss_active &&
+ !vifs->ap_active) {
p2p_mvmvif->pm_enabled = true;
return;
}
- if (vifs->bss_active && vifs->p2p_active)
+ if (p2p_mvmvif && bss_mvmvif && vifs->bss_active && vifs->p2p_active)
client_same_channel =
iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
- if (vifs->bss_active && vifs->ap_active)
+ if (bss_mvmvif && ap_mvmvif && vifs->bss_active && vifs->ap_active)
ap_same_channel =
iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);
/* clients are not stand alone: enable PM if DCM */
if (!(client_same_channel || ap_same_channel)) {
- if (vifs->bss_active)
+ if (bss_mvmvif && vifs->bss_active)
bss_mvmvif->pm_enabled = true;
- if (vifs->p2p_active)
+ if (p2p_mvmvif && vifs->p2p_active)
p2p_mvmvif->pm_enabled = true;
return;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index c3a00bfbeef2..6cba8a353b53 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "rs.h"
#include "fw-api.h"
@@ -63,12 +63,11 @@ static u8 rs_fw_sgi_cw_support(struct ieee80211_link_sta *link_sta)
static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband)
+ const struct ieee80211_sta_he_cap *sband_he_cap)
{
struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
- const struct ieee80211_sta_he_cap *sband_he_cap;
bool vht_ena = vht_cap->vht_supported;
u16 flags = 0;
@@ -94,8 +93,6 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
- sband_he_cap = ieee80211_get_he_iftype_cap(sband,
- ieee80211_vif_type_p2p(vif));
if (sband_he_cap &&
!(sband_he_cap->he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
@@ -197,16 +194,14 @@ static u16 rs_fw_he_ieee80211_mcs_to_rs_mcs(u16 mcs)
static void
rs_fw_he_set_enabled_rates(const struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
u16 mcs_80 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
- u16 tx_mcs_80 =
- le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_80);
- u16 tx_mcs_160 =
- le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
+ u16 tx_mcs_80 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_80);
+ u16 tx_mcs_160 = le16_to_cpu(sband_he_cap->he_mcs_nss_supp.tx_mcs_160);
int i;
u8 nss = link_sta->rx_nss;
@@ -289,7 +284,8 @@ rs_fw_rs_mcs2eht_mcs(enum IWL_TLC_MCS_PER_BW bw,
static void
rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
const struct ieee80211_link_sta *link_sta,
- struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
+ const struct ieee80211_sta_eht_cap *sband_eht_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
/* peer RX mcs capa */
@@ -297,7 +293,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
&link_sta->eht_cap.eht_mcs_nss_supp;
/* our TX mcs capa */
const struct ieee80211_eht_mcs_nss_supp *eht_tx_mcs =
- &sband->iftype_data->eht_cap.eht_mcs_nss_supp;
+ &sband_eht_cap->eht_mcs_nss_supp;
enum IWL_TLC_MCS_PER_BW bw;
struct ieee80211_eht_mcs_nss_supp_20mhz_only mcs_rx_20;
@@ -316,7 +312,7 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
}
/* nic is 20Mhz only */
- if (!(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[0] &
+ if (!(sband_he_cap->he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
mcs_tx_20 = eht_tx_mcs->only_20mhz;
} else {
@@ -370,6 +366,8 @@ rs_fw_eht_set_enabled_rates(struct ieee80211_vif *vif,
static void rs_fw_set_supp_rates(struct ieee80211_vif *vif,
struct ieee80211_link_sta *link_sta,
struct ieee80211_supported_band *sband,
+ const struct ieee80211_sta_he_cap *sband_he_cap,
+ const struct ieee80211_sta_eht_cap *sband_eht_cap,
struct iwl_tlc_config_cmd_v4 *cmd)
{
int i;
@@ -388,12 +386,13 @@ static void rs_fw_set_supp_rates(struct ieee80211_vif *vif,
cmd->mode = IWL_TLC_MNG_MODE_NON_HT;
/* HT/VHT rates */
- if (link_sta->eht_cap.has_eht) {
+ if (link_sta->eht_cap.has_eht && sband_he_cap && sband_eht_cap) {
cmd->mode = IWL_TLC_MNG_MODE_EHT;
- rs_fw_eht_set_enabled_rates(vif, link_sta, sband, cmd);
- } else if (he_cap->has_he) {
+ rs_fw_eht_set_enabled_rates(vif, link_sta, sband_he_cap,
+ sband_eht_cap, cmd);
+ } else if (he_cap->has_he && sband_he_cap) {
cmd->mode = IWL_TLC_MNG_MODE_HE;
- rs_fw_he_set_enabled_rates(link_sta, sband, cmd);
+ rs_fw_he_set_enabled_rates(link_sta, sband_he_cap, cmd);
} else if (vht_cap->vht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_VHT;
rs_fw_vht_set_enabled_rates(link_sta, vht_cap, cmd);
@@ -479,7 +478,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate);
}
- if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvmsta->orig_amsdu_len) {
+ if (flags & IWL_TLC_NOTIF_FLAG_AMSDU && !mvm_link_sta->orig_amsdu_len) {
u16 size = le32_to_cpu(notif->amsdu_size);
int i;
@@ -489,7 +488,7 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
* so also check with orig_amsdu_len which holds the
* original data before debugfs changed the value
*/
- WARN_ON(mvmsta->orig_amsdu_len < size);
+ WARN_ON(mvm_link_sta->orig_amsdu_len < size);
goto out;
}
@@ -524,6 +523,7 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
{
const struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
const struct ieee80211_sta_ht_cap *ht_cap = &link_sta->ht_cap;
+ const struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
if (WARN_ON_ONCE(!link_conf->chandef.chan))
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
@@ -538,8 +538,18 @@ u16 rs_fw_get_max_amsdu_len(struct ieee80211_sta *sta,
default:
return IEEE80211_MAX_MPDU_LEN_VHT_3895;
}
- } else
- if (vht_cap->vht_supported) {
+ } else if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ &&
+ eht_cap->has_eht) {
+ switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0],
+ IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) {
+ case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454:
+ return IEEE80211_MAX_MPDU_LEN_VHT_11454;
+ case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991:
+ return IEEE80211_MAX_MPDU_LEN_VHT_7991;
+ default:
+ return IEEE80211_MAX_MPDU_LEN_VHT_3895;
+ }
+ } else if (vht_cap->vht_supported) {
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
return IEEE80211_MAX_MPDU_LEN_VHT_11454;
@@ -576,13 +586,17 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
u16 max_amsdu_len = rs_fw_get_max_amsdu_len(sta, link_conf, link_sta);
+ const struct ieee80211_sta_he_cap *sband_he_cap =
+ ieee80211_get_he_iftype_cap_vif(sband, vif);
+ const struct ieee80211_sta_eht_cap *sband_eht_cap =
+ ieee80211_get_eht_iftype_cap_vif(sband, vif);
struct iwl_mvm_link_sta *mvm_link_sta;
struct iwl_lq_sta_rs_fw *lq_sta;
struct iwl_tlc_config_cmd_v4 cfg_cmd = {
.max_ch_width = mvmsta->authorized ?
rs_fw_bw_from_sta_bw(link_sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ,
.flags = cpu_to_le16(rs_fw_get_config_flags(mvm, vif, link_sta,
- sband)),
+ sband_he_cap)),
.chains = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm)),
.sgi_ch_width_supp = rs_fw_sgi_cw_support(link_sta),
.max_mpdu_len = iwl_mvm_is_csum_supported(mvm) ?
@@ -592,6 +606,21 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
int cmd_ver;
int ret;
+ /* Enable external EHT LTF only for GL device and if there's
+ * mutual support by AP and client
+ */
+ if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL &&
+ sband_eht_cap &&
+ sband_eht_cap->eht_cap_elem.phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
+ link_sta->eht_cap.has_eht &&
+ link_sta->eht_cap.eht_cap_elem.phy_cap_info[5] &
+ IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) {
+ IWL_DEBUG_RATE(mvm, "Set support for Extra EHT LTF\n");
+ cfg_cmd.flags |=
+ cpu_to_le16(IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK);
+ }
+
rcu_read_lock();
mvm_link_sta = rcu_dereference(mvmsta->link[link_id]);
if (WARN_ON_ONCE(!mvm_link_sta)) {
@@ -609,7 +638,9 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm,
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- rs_fw_set_supp_rates(vif, link_sta, sband, &cfg_cmd);
+ rs_fw_set_supp_rates(vif, link_sta, sband,
+ sband_he_cap, sband_eht_cap,
+ &cfg_cmd);
/*
* since TLC offload works with one mode we can assume
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index 280b48a7136b..2025c07055e6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*
- * Copyright(c) 2005 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
+ * Copyright(c) 2005 - 2014, 2018 - 2023 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*****************************************************************************/
@@ -1070,10 +1070,13 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
rate->bw = RATE_MCS_CHAN_WIDTH_20;
- WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX ||
- rate->index > IWL_RATE_MCS_9_INDEX);
+ if (WARN_ON_ONCE(rate->index < IWL_RATE_MCS_0_INDEX))
+ rate->index = rs_ht_to_legacy[IWL_RATE_MCS_0_INDEX];
+ else if (WARN_ON_ONCE(rate->index > IWL_RATE_MCS_9_INDEX))
+ rate->index = rs_ht_to_legacy[IWL_RATE_MCS_9_INDEX];
+ else
+ rate->index = rs_ht_to_legacy[rate->index];
- rate->index = rs_ht_to_legacy[rate->index];
rate->ldpc = false;
} else {
/* Downgrade to SISO with same MCS if in MIMO */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index b38b24246675..542c192698a4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -213,8 +213,12 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
};
u16 thr;
- if (ieee80211_is_data_qos(hdr->frame_control))
- ac = tid_to_mac80211_ac[ieee80211_get_tid(hdr)];
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ u8 tid = ieee80211_get_tid(hdr);
+
+ if (tid < IWL_MAX_TID_COUNT)
+ ac = tid_to_mac80211_ac[tid];
+ }
mvmsta = iwl_mvm_sta_from_mac80211(sta);
mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 6226e4e54a51..8d1e44fd9de7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -279,7 +279,8 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
struct ieee80211_hdr *hdr,
struct iwl_rx_mpdu_desc *desc,
- u32 status)
+ u32 status,
+ struct ieee80211_rx_status *stats)
{
struct iwl_mvm_sta *mvmsta;
struct iwl_mvm_vif *mvmvif;
@@ -308,8 +309,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
/* good cases */
if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
- !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)))
+ !(status & IWL_RX_MPDU_STATUS_REPLAY_ERROR))) {
+ stats->flag |= RX_FLAG_DECRYPTED;
return 0;
+ }
if (!sta)
return -1;
@@ -378,7 +381,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (unlikely(ieee80211_is_mgmt(hdr->frame_control) &&
!ieee80211_has_protected(hdr->frame_control)))
- return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status);
+ return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status, stats);
if (!ieee80211_has_protected(hdr->frame_control) ||
(status & IWL_RX_MPDU_STATUS_SEC_MASK) ==
@@ -484,7 +487,7 @@ static void iwl_mvm_rx_csum(struct iwl_mvm *mvm,
}
/*
- * returns true if a packet is a duplicate and should be dropped.
+ * returns true if a packet is a duplicate or invalid tid and should be dropped.
* Updates AMSDU PN tracking info
*/
static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
@@ -513,11 +516,14 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
return false;
}
- if (ieee80211_is_data_qos(hdr->frame_control))
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
/* frame has qos control */
tid = ieee80211_get_tid(hdr);
- else
+ if (tid >= IWL_MAX_TID_COUNT)
+ return true;
+ } else {
tid = IWL_MAX_TID_COUNT;
+ }
/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
sub_frame_idx = desc->amsdu_info &
@@ -985,10 +991,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1);
rcu_read_unlock();
- if (WARN(tid != baid_data->tid ||
- !(sta_mask & baid_data->sta_mask),
- "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
- baid, baid_data->sta_mask, baid_data->tid, sta_mask, tid))
+ if (IWL_FW_CHECK(mvm,
+ tid != baid_data->tid ||
+ !(sta_mask & baid_data->sta_mask),
+ "baid 0x%x is mapped to sta_mask:0x%x tid:%d, but was received for sta_mask:0x%x tid:%d\n",
+ baid, baid_data->sta_mask, baid_data->tid,
+ sta_mask, tid))
return false;
nssn = reorder & IWL_RX_MPDU_REORDER_NSSN_MASK;
@@ -1773,6 +1781,15 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR);
}
+ if (fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_SNIFF_VALIDATE_SUPPORT)) {
+ usig->common |=
+ cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED);
+ usig->common |=
+ LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_VALIDATE,
+ IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK);
+ }
+
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_SPATIAL_REUSE);
eht->data[0] |= LE32_DEC_ENC(data0,
IWL_RX_PHY_DATA0_ETH_SPATIAL_REUSE_MASK,
@@ -1782,9 +1799,9 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm,
eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT);
eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0,
+ eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0);
- eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC,
+ eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7,
IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1);
iwl_mvm_decode_eht_ru(mvm, rx_status, eht);
@@ -2633,6 +2650,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
phy_data.with_data = false;
+ phy_data.rx_vec[0] = desc->rx_vec[0];
+ phy_data.rx_vec[1] = desc->rx_vec[1];
if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
RX_NO_DATA_NOTIF, 0) < 2) {
@@ -2651,7 +2670,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
sizeof(struct iwl_rx_no_data_ver_3)))
/* invalid len for ver 3 */
return;
- memcpy(phy_data.rx_vec, desc->rx_vec, sizeof(phy_data.rx_vec));
+ phy_data.rx_vec[2] = desc->rx_vec[2];
+ phy_data.rx_vec[3] = desc->rx_vec[3];
} else {
if (format == RATE_MCS_EHT_MSK)
/* no support for EHT before version 3 API */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 175615755d9d..c1d9ce753468 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -647,7 +647,7 @@ static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm *mvm,
NL80211_BAND_2GHZ,
no_cck);
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
@@ -1084,7 +1084,7 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
- WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12);
+ WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@@ -1135,7 +1135,7 @@ static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,
memcpy(&cfg->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
/* This function should not be called when using ADD_STA ver >=12 */
- WARN_ON_ONCE(iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12);
+ WARN_ON_ONCE(iwl_mvm_has_new_station_api(mvm->fw));
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
@@ -1250,7 +1250,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
memset(&cfg, 0, sizeof(cfg));
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) < 12) {
+ if (!iwl_mvm_has_new_station_api(mvm->fw)) {
cfg.bcast_sta_id = mvm->aux_sta.sta_id;
} else if (iwl_fw_lookup_cmd_ver(mvm->fw, SCAN_CFG_CMD, 0) < 5) {
/*
@@ -1627,11 +1627,11 @@ iwl_mvm_umac_scan_cfg_channels_v4(struct iwl_mvm *mvm,
}
static void
-iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm,
+iwl_mvm_umac_scan_cfg_channels_v7(struct iwl_mvm *mvm,
struct ieee80211_channel **channels,
- struct iwl_scan_channel_params_v6 *cp,
+ struct iwl_scan_channel_params_v7 *cp,
int n_channels, u32 flags,
- enum nl80211_iftype vif_type)
+ enum nl80211_iftype vif_type, u32 version)
{
int i;
@@ -1641,14 +1641,19 @@ iwl_mvm_umac_scan_cfg_channels_v6(struct iwl_mvm *mvm,
u32 n_aps_flag =
iwl_mvm_scan_ch_n_aps_flag(vif_type,
channels[i]->hw_value);
+ u8 iwl_band = iwl_mvm_phy_band_from_nl80211(band);
cfg->flags = cpu_to_le32(flags | n_aps_flag);
cfg->v2.channel_num = channels[i]->hw_value;
- cfg->v2.band = iwl_mvm_phy_band_from_nl80211(band);
if (cfg80211_channel_is_psc(channels[i]))
cfg->flags = 0;
cfg->v2.iter_count = 1;
cfg->v2.iter_interval = 0;
+ if (version < 17)
+ cfg->v2.band = iwl_band;
+ else
+ cfg->flags |= cpu_to_le32((iwl_band <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS));
}
}
@@ -1723,14 +1728,15 @@ iwl_mvm_umac_scan_fill_6g_chan_list(struct iwl_mvm *mvm,
pp->bssid_num = idex_b;
}
-/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v6 */
+/* TODO: this function can be merged with iwl_mvm_scan_umac_fill_ch_p_v7 */
static u32
-iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
+iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
u32 n_channels,
struct iwl_scan_probe_params_v4 *pp,
- struct iwl_scan_channel_params_v6 *cp,
- enum nl80211_iftype vif_type)
+ struct iwl_scan_channel_params_v7 *cp,
+ enum nl80211_iftype vif_type,
+ u32 version)
{
int i;
struct cfg80211_scan_6ghz_params *scan_6ghz_params =
@@ -1745,6 +1751,7 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries;
bool force_passive, found = false, allow_passive = true,
unsolicited_probe_on_chan = false, psc_no_listen = false;
+ s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
/*
* Avoid performing passive scan on non PSC channels unless the
@@ -1756,9 +1763,14 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
continue;
cfg->v1.channel_num = params->channels[i]->hw_value;
- cfg->v2.band = 2;
- cfg->v2.iter_count = 1;
- cfg->v2.iter_interval = 0;
+ if (version < 17)
+ cfg->v2.band = PHY_BAND_6;
+ else
+ cfg->flags |= cpu_to_le32(PHY_BAND_6 <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS);
+
+ cfg->v5.iter_count = 1;
+ cfg->v5.iter_interval = 0;
/*
* The optimize the scan time, i.e., reduce the scan dwell time
@@ -1769,9 +1781,22 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
*/
n_used_bssid_entries = 3;
for (j = 0; j < params->n_6ghz_params; j++) {
+ s8 tmp_psd_20;
+
if (!(scan_6ghz_params[j].channel_idx == i))
continue;
+ /* Use the highest PSD value allowed as advertised by
+ * APs for this channel
+ */
+ tmp_psd_20 = scan_6ghz_params[j].psd_20;
+ if (tmp_psd_20 !=
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED &&
+ (psd_20 ==
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED ||
+ psd_20 < tmp_psd_20))
+ psd_20 = tmp_psd_20;
+
found = false;
unsolicited_probe_on_chan |=
scan_6ghz_params[j].unsolicited_probe;
@@ -1875,6 +1900,9 @@ iwl_mvm_umac_scan_cfg_channels_v6_6g(struct iwl_mvm *mvm,
flags |= bssid_bitmap | (s_ssid_bitmap << 16);
cfg->flags |= cpu_to_le32(flags);
+ if (version >= 17)
+ cfg->v5.psd_20 = psd_20;
+
ch_cnt++;
}
@@ -2292,11 +2320,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
}
static void
-iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
+iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
struct iwl_scan_general_params_v11 *gp,
- u16 gen_flags, u8 gen_flags2)
+ u16 gen_flags, u8 gen_flags2,
+ u32 version)
{
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
@@ -2313,7 +2342,23 @@ iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
- gp->scan_start_mac_id = scan_vif->id;
+ if (version < 12) {
+ gp->scan_start_mac_or_link_id = scan_vif->id;
+ } else {
+ struct iwl_mvm_vif_link_info *link_info;
+ u8 link_id = 0;
+
+ /* Use one of the active link (if any). In the future it would
+ * be possible that the link ID would be part of the scan
+ * request coming from upper layers so we would need to use it.
+ */
+ if (vif->active_links)
+ link_id = ffs(vif->active_links) - 1;
+
+ link_info = scan_vif->link[link_id];
+ if (!WARN_ON(!link_info))
+ gp->scan_start_mac_or_link_id = link_info->fw_link_id;
+ }
}
static void
@@ -2352,21 +2397,22 @@ iwl_mvm_scan_umac_fill_ch_p_v4(struct iwl_mvm *mvm,
}
static void
-iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
+iwl_mvm_scan_umac_fill_ch_p_v7(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
struct ieee80211_vif *vif,
- struct iwl_scan_channel_params_v6 *cp,
- u32 channel_cfg_flags)
+ struct iwl_scan_channel_params_v7 *cp,
+ u32 channel_cfg_flags,
+ u32 version)
{
cp->flags = iwl_mvm_scan_umac_chan_flags_v2(mvm, params, vif);
cp->count = params->n_channels;
cp->n_aps_override[0] = IWL_SCAN_ADWELL_N_APS_GO_FRIENDLY;
cp->n_aps_override[1] = IWL_SCAN_ADWELL_N_APS_SOCIAL_CHS;
- iwl_mvm_umac_scan_cfg_channels_v6(mvm, params->channels, cp,
+ iwl_mvm_umac_scan_cfg_channels_v7(mvm, params->channels, cp,
params->n_channels,
channel_cfg_flags,
- vif->type);
+ vif->type, version);
if (params->enable_6ghz_passive) {
struct ieee80211_supported_band *sband =
@@ -2383,11 +2429,19 @@ iwl_mvm_scan_umac_fill_ch_p_v6(struct iwl_mvm *mvm,
if (!cfg80211_channel_is_psc(channel))
continue;
- cfg->flags = 0;
- cfg->v2.channel_num = channel->hw_value;
- cfg->v2.band = PHY_BAND_6;
- cfg->v2.iter_count = 1;
- cfg->v2.iter_interval = 0;
+ cfg->v5.channel_num = channel->hw_value;
+ cfg->v5.iter_count = 1;
+ cfg->v5.iter_interval = 0;
+
+ if (version < 17) {
+ cfg->flags = 0;
+ cfg->v2.band = PHY_BAND_6;
+ } else {
+ cfg->flags = cpu_to_le32(PHY_BAND_6 <<
+ IWL_CHAN_CFG_FLAGS_BAND_POS);
+ cfg->v5.psd_20 =
+ IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
+ }
cp->count++;
}
}
@@ -2408,9 +2462,9 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cmd->uid = cpu_to_le32(uid);
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
- iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
+ iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,
&scan_p->general_params,
- gen_flags, 0);
+ gen_flags, 0, 12);
ret = iwl_mvm_fill_scan_sched_params(params,
scan_p->periodic_params.schedule,
@@ -2430,9 +2484,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
struct iwl_mvm_scan_params *params,
int type, int uid, u32 version)
{
- struct iwl_scan_req_umac_v15 *cmd = mvm->scan_cmd;
- struct iwl_scan_req_params_v15 *scan_p = &cmd->scan_params;
- struct iwl_scan_channel_params_v6 *cp = &scan_p->channel_params;
+ struct iwl_scan_req_umac_v17 *cmd = mvm->scan_cmd;
+ struct iwl_scan_req_params_v17 *scan_p = &cmd->scan_params;
+ struct iwl_scan_channel_params_v7 *cp = &scan_p->channel_params;
struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params;
int ret;
u16 gen_flags;
@@ -2451,9 +2505,9 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
else
gen_flags2 = 0;
- iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
+ iwl_mvm_scan_umac_fill_general_p_v12(mvm, params, vif,
&scan_p->general_params,
- gen_flags, gen_flags2);
+ gen_flags, gen_flags2, version);
ret = iwl_mvm_fill_scan_sched_params(params,
scan_p->periodic_params.schedule,
@@ -2462,11 +2516,13 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
return ret;
if (!params->scan_6ghz) {
- iwl_mvm_scan_umac_fill_probe_p_v4(params, &scan_p->probe_params,
- &bitmap_ssid);
- iwl_mvm_scan_umac_fill_ch_p_v6(mvm, params, vif,
- &scan_p->channel_params, bitmap_ssid);
-
+ iwl_mvm_scan_umac_fill_probe_p_v4(params,
+ &scan_p->probe_params,
+ &bitmap_ssid);
+ iwl_mvm_scan_umac_fill_ch_p_v7(mvm, params, vif,
+ &scan_p->channel_params,
+ bitmap_ssid,
+ version);
return 0;
} else {
pb->preq = params->preq;
@@ -2478,9 +2534,10 @@ static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
iwl_mvm_umac_scan_fill_6g_chan_list(mvm, params, pb);
- cp->count = iwl_mvm_umac_scan_cfg_channels_v6_6g(mvm, params,
+ cp->count = iwl_mvm_umac_scan_cfg_channels_v7_6g(mvm, params,
params->n_channels,
- pb, cp, vif->type);
+ pb, cp, vif->type,
+ version);
if (!cp->count) {
mvm->scan_uid_status[uid] = 0;
return -EINVAL;
@@ -2507,6 +2564,20 @@ static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15);
}
+static int iwl_mvm_scan_umac_v16(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_mvm_scan_params *params, int type,
+ int uid)
+{
+ return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 16);
+}
+
+static int iwl_mvm_scan_umac_v17(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_mvm_scan_params *params, int type,
+ int uid)
+{
+ return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 17);
+}
+
static int iwl_mvm_num_scans(struct iwl_mvm *mvm)
{
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
@@ -2622,6 +2693,8 @@ struct iwl_scan_umac_handler {
static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
/* set the newest version first to shorten the list traverse time */
+ IWL_SCAN_UMAC_HANDLER(17),
+ IWL_SCAN_UMAC_HANDLER(16),
IWL_SCAN_UMAC_HANDLER(15),
IWL_SCAN_UMAC_HANDLER(14),
IWL_SCAN_UMAC_HANDLER(12),
@@ -3210,7 +3283,9 @@ static size_t iwl_scan_req_umac_get_size(u8 scan_ver)
return sizeof(struct iwl_scan_req_umac_v12);
case 14:
case 15:
- return sizeof(struct iwl_scan_req_umac_v15);
+ case 16:
+ case 17:
+ return sizeof(struct iwl_scan_req_umac_v17);
}
return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
index 98f330fcf678..30d4233595e8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2013-2014, 2018-2019, 2022 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2019, 2022-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
*/
#include "mvm.h"
@@ -180,9 +180,6 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
};
int ret = 0;
- if (mvm->cfg->disable_dummy_notification)
- sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF);
-
/*
* If an associated AP sta changed its antenna configuration, the state
* will remain FULL_ON but SF parameters need to be reconsidered.
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 75e90a57a331..7706feb77224 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -60,22 +60,27 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
if (WARN_ON(!link_sta))
return 0;
- if (link_sta->ht_cap.ht_supported)
+ /* Note that we always use only legacy & highest supported PPDUs, so
+ * of Draft P802.11be D.30 Table 10-12a--Fields used for calculating
+ * the maximum A-MPDU size of various PPDU types in different bands,
+ * we only need to worry about the highest supported PPDU type here.
+ */
+
+ if (link_sta->ht_cap.ht_supported) {
+ agg_size = link_sta->ht_cap.ampdu_factor;
mpdu_dens = link_sta->ht_cap.ampdu_density;
+ }
- if (link_conf->chandef.chan->band ==
- NL80211_BAND_6GHZ) {
+ if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
+ /* overwrite HT values on 6 GHz */
mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
} else if (link_sta->vht_cap.vht_supported) {
- agg_size = link_sta->vht_cap.cap &
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
- agg_size >>=
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
- } else if (link_sta->ht_cap.ht_supported) {
- agg_size = link_sta->ht_cap.ampdu_factor;
+ /* if VHT supported overwrite HT value */
+ agg_size = u32_get_bits(link_sta->vht_cap.cap,
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
}
/* D6.0 10.12.2 A-MPDU length limit rules
@@ -91,10 +96,13 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3],
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
+ if (link_sta->eht_cap.has_eht)
+ agg_size += u8_get_bits(link_sta->eht_cap.eht_cap_elem.mac_cap_info[1],
+ IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK);
+
/* Limit to max A-MPDU supported by FW */
- if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
- agg_size = (STA_FLG_MAX_AGG_SIZE_4M >>
- STA_FLG_MAX_AGG_SIZE_SHIFT);
+ agg_size = min_t(u32, agg_size,
+ STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT);
*_agg_size = agg_size;
return mpdu_dens;
@@ -1679,7 +1687,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = sta->sta_id;
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12 &&
+ if (iwl_mvm_has_new_station_api(mvm->fw) &&
sta->type == IWL_STA_AUX_ACTIVITY)
cmd.mac_id_n_color = cpu_to_le32(mac_id);
else
@@ -1859,6 +1867,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK);
+ if (ret)
+ goto err;
update_fw:
ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
@@ -2070,13 +2080,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cancel_delayed_work(&mvm->tdls_cs.dwork);
}
- /*
- * Make sure that the tx response code sees the station as -EBUSY and
- * calls the drain worker.
- */
- spin_lock_bh(&mvm_sta->lock);
- spin_unlock_bh(&mvm_sta->lock);
-
return false;
}
@@ -2884,7 +2887,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
}
if (iwl_mvm_has_new_rx_api(mvm) && start) {
- u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
+ u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
/* sparse doesn't like the __align() so don't check */
#ifndef __CHECKER__
@@ -4308,16 +4311,27 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u16 queue;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_key_conf *keyconf;
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ bool mld = iwl_mvm_has_mld_api(mvm->fw);
+ u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK;
ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
- NL80211_IFTYPE_UNSPECIFIED,
- IWL_STA_LINK);
+ NL80211_IFTYPE_UNSPECIFIED, type);
if (ret)
return ret;
- ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color,
- addr, sta, &queue,
- IWL_MVM_TX_FIFO_BE);
+ if (mld)
+ ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr,
+ mvmvif->deflink.fw_link_id,
+ &queue,
+ IWL_MAX_TID_COUNT,
+ &wdg_timeout);
+ else
+ ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id,
+ mvmvif->color, addr, sta,
+ &queue,
+ IWL_MVM_TX_FIFO_BE);
if (ret)
goto out;
@@ -4330,9 +4344,23 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
keyconf->cipher = cipher;
memcpy(keyconf->key, key, key_len);
keyconf->keylen = key_len;
+ keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE;
+
+ if (mld) {
+ /* The MFP flag is set according to the station mfp field. Since
+ * we don't have a station, set it manually.
+ */
+ u32 key_flags =
+ iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) |
+ IWL_SEC_KEY_FLAG_MFP;
+ u32 sta_mask = BIT(sta->sta_id);
+
+ ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
+ } else {
+ ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
+ 0, NULL, 0, 0, true);
+ }
- ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
- 0, NULL, 0, 0, true);
kfree(keyconf);
return 0;
out:
@@ -4342,10 +4370,10 @@ out:
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 mac_id)
+ u32 id)
{
struct iwl_cancel_channel_switch_cmd cancel_channel_switch_cmd = {
- .mac_id = cpu_to_le32(mac_id),
+ .id = cpu_to_le32(id),
};
int ret;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index a61d4f88125f..7364346a1209 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -336,6 +336,9 @@ struct iwl_mvm_rxq_dup_data {
* @sta_id: the index of the station in the fw
* @lq_sta: holds rate scaling data, either for the case when RS is done in
* the driver - %rs_drv or in the FW - %rs_fw.
+ * @orig_amsdu_len: used to save the original amsdu_len when it is changed via
+ * debugfs. If it's set to 0, it means that it is it's not set via
+ * debugfs.
* @avg_energy: energy as reported by FW statistics notification
*/
struct iwl_mvm_link_sta {
@@ -346,6 +349,8 @@ struct iwl_mvm_link_sta {
struct iwl_lq_sta rs_drv;
} lq_sta;
+ u16 orig_amsdu_len;
+
u8 avg_energy;
};
@@ -365,6 +370,7 @@ struct iwl_mvm_link_sta {
* and from Tx response flow, it needs a spinlock.
* @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data.
* @tid_to_baid: a simple map of TID to baid
+ * @vif: a vif pointer
* @reserved_queue: the queue reserved for this STA for DQA purposes
* Every STA has is given one reserved queue to allow it to operate. If no
* such queue can be guaranteed, the STA addition will fail.
@@ -374,10 +380,8 @@ struct iwl_mvm_link_sta {
* @amsdu_enabled: bitmap of TX AMSDU allowed TIDs.
* In case TLC offload is not active it is either 0xFFFF or 0.
* @max_amsdu_len: max AMSDU length
- * @orig_amsdu_len: used to save the original amsdu_len when it is changed via
- * debugfs. If it's set to 0, it means that it is it's not set via
- * debugfs.
* @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON)
+ * @sleeping: sta sleep transitions in power management
* @sleep_tx_count: the number of frames that we told the firmware to let out
* even when that station is asleep. This is useful in case the queue
* gets empty before all the frames were sent, which can happen when
@@ -427,7 +431,6 @@ struct iwl_mvm_sta {
bool disable_tx;
u16 amsdu_enabled;
u16 max_amsdu_len;
- u16 orig_amsdu_len;
bool sleeping;
u8 agg_tids;
u8 sleep_tx_count;
@@ -580,7 +583,7 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u8 *key, u32 key_len);
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 mac_id);
+ u32 id);
/* Queues */
int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
@@ -616,7 +619,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state,
- struct iwl_mvm_sta_state_ops *callbacks);
+ const struct iwl_mvm_sta_state_ops *callbacks);
/* New MLD STA related APIs */
/* STA */
@@ -646,6 +649,11 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
u16 old_links, u16 new_links);
u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int filter_link_id);
+int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm,
+ struct iwl_mvm_int_sta *sta,
+ const u8 *addr, int link_id,
+ u16 *queue, u8 tid,
+ unsigned int *_wdg_timeout);
/* Queues */
void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 6b7b6250f1bb..5f0e7144a951 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
@@ -103,7 +103,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
/* In newer version of this command an aux station is added only
* in cases of dedicated tx queue and need to be removed in end
* of use */
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12)
+ if (iwl_mvm_has_new_station_api(mvm->fw))
iwl_mvm_rm_aux_sta(mvm);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 00719e130438..36d70d589aed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <linux/tcp.h>
+#include <net/gso.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -40,13 +41,14 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
#define OPT_HDR(type, skb, off) \
(type *)(skb_network_header(skb) + (off))
-static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct ieee80211_tx_info *info, bool amsdu)
+static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
+ struct ieee80211_tx_info *info,
+ bool amsdu)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
+ u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u16 offload_assist = 0;
#if IS_ENABLED(CONFIG_INET)
- u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u8 protocol = 0;
/* Do not compute checksum if already computed */
@@ -118,6 +120,8 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
else
udp_hdr(skb)->check = 0;
+out:
+#endif
/*
* mac header len should include IV, size is in words unless
* the IV is added by the firmware like in WEP.
@@ -130,8 +134,6 @@ static u16 iwl_mvm_tx_csum_pre_bz(struct iwl_mvm *mvm, struct sk_buff *skb,
mh_len /= 2;
offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE;
-out:
-#endif
if (amsdu)
offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
else if (ieee80211_hdrlen(hdr->frame_control) % 4)
@@ -141,54 +143,6 @@ out:
return offload_assist;
}
-u32 iwl_mvm_tx_csum_bz(struct iwl_mvm *mvm, struct sk_buff *skb, bool amsdu)
-{
- struct ieee80211_hdr *hdr = (void *)skb->data;
- u32 offload_assist = IWL_TX_CMD_OFFLD_BZ_PARTIAL_CSUM;
- unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
- unsigned int csum_start = skb_checksum_start_offset(skb);
-
- offload_assist |= u32_encode_bits(hdrlen / 2,
- IWL_TX_CMD_OFFLD_BZ_MH_LEN);
- if (amsdu)
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_AMSDU;
- else if (hdrlen % 4)
- /* padding is inserted later in transport */
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_MH_PAD;
-
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- return offload_assist;
-
- offload_assist |= IWL_TX_CMD_OFFLD_BZ_ENABLE_CSUM |
- IWL_TX_CMD_OFFLD_BZ_ZERO2ONES;
-
- /*
- * mac80211 will always calculate checksum in software for
- * non-fast-xmit, and so we can only do offloaded checksum
- * for fast-xmit frames. In this case, we always have the
- * RFC 1042 header present. skb_checksum_start_offset()
- * returns the offset from the beginning, but the hardware
- * needs it from after the header & SNAP header.
- */
- csum_start -= hdrlen + 8;
-
- offload_assist |= u32_encode_bits(csum_start,
- IWL_TX_CMD_OFFLD_BZ_START_OFFS);
- offload_assist |= u32_encode_bits(csum_start + skb->csum_offset,
- IWL_TX_CMD_OFFLD_BZ_RESULT_OFFS);
-
- return offload_assist;
-}
-
-static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct ieee80211_tx_info *info,
- bool amsdu)
-{
- if (!iwl_mvm_has_new_tx_csum(mvm))
- return iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu);
- return iwl_mvm_tx_csum_bz(mvm, skb, amsdu);
-}
-
/*
* Sets most of the Tx cmd's fields
*/
@@ -288,7 +242,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->sta_id = sta_id;
tx_cmd->offload_assist =
- cpu_to_le16(iwl_mvm_tx_csum_pre_bz(mvm, skb, info, amsdu));
+ cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu));
}
static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm,
@@ -308,6 +262,54 @@ static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm,
return BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
}
+static u32 iwl_mvm_get_inject_tx_rate(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info)
+{
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ u32 result;
+
+ /*
+ * we only care about legacy/HT/VHT so far, so we can
+ * build in v1 and use iwl_new_rate_from_v1()
+ */
+
+ if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+ u8 mcs = ieee80211_rate_get_vht_mcs(rate);
+ u8 nss = ieee80211_rate_get_vht_nss(rate);
+
+ result = RATE_MCS_VHT_MSK_V1;
+ result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK);
+ result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK);
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ result |= RATE_MCS_SGI_MSK_V1;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ } else if (rate->flags & IEEE80211_TX_RC_MCS) {
+ result = RATE_MCS_HT_MSK_V1;
+ result |= u32_encode_bits(rate->idx,
+ RATE_HT_MCS_RATE_CODE_MSK_V1 |
+ RATE_HT_MCS_NSS_MSK_V1);
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ result |= RATE_MCS_SGI_MSK_V1;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1);
+ if (info->flags & IEEE80211_TX_CTL_LDPC)
+ result |= RATE_MCS_LDPC_MSK_V1;
+ if (u32_get_bits(info->flags, IEEE80211_TX_CTL_STBC))
+ result |= RATE_MCS_STBC_MSK;
+ } else {
+ return 0;
+ }
+
+ if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6)
+ return iwl_new_rate_from_v1(result);
+ return result;
+}
+
static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc)
@@ -317,8 +319,15 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
u32 rate_flags = 0;
bool is_cck;
- /* info->control is only relevant for non HW rate control */
- if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
+ if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) {
+ u32 result = iwl_mvm_get_inject_tx_rate(mvm, info);
+
+ if (result)
+ return result;
+ rate_idx = info->control.rates[0].idx;
+ } else if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) {
+ /* info->control is only relevant for non HW rate control */
+
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS &&
!ieee80211_is_data(fc),
@@ -398,7 +407,8 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
* table is controlled by LINK_QUALITY commands
*/
- if (ieee80211_is_data(fc) && sta) {
+ if (likely(ieee80211_is_data(fc) && sta &&
+ !(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
@@ -556,9 +566,8 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
} else {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
- u16 offload_assist = iwl_mvm_tx_csum_pre_bz(mvm, skb,
- info,
- amsdu);
+ u16 offload_assist = iwl_mvm_tx_csum(mvm, skb,
+ info, amsdu);
cmd->offload_assist = cpu_to_le16(offload_assist);
@@ -749,6 +758,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
}
link = mvmvif->link[link_id];
+ if (WARN_ON(!link))
+ return -1;
if (!ieee80211_is_data(hdr->frame_control))
sta_id = link->bcast_sta.sta_id;
@@ -840,7 +851,7 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
band = mvmsta->vif->bss_conf.chandef.chan->band;
}
- lmac = iwl_mvm_get_lmac_id(mvm->fw, band);
+ lmac = iwl_mvm_get_lmac_id(mvm, band);
} else if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CDB_SUPPORT)) {
/* for real MLO restrict to both LMACs if they exist */
@@ -2065,7 +2076,8 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
u16 tfd_cnt;
int i;
- if (unlikely(sizeof(*ba_res) > pkt_len))
+ if (IWL_FW_CHECK(mvm, sizeof(*ba_res) > pkt_len,
+ "short BA notification (%d)\n", pkt_len))
return;
sta_id = ba_res->sta_id;
@@ -2077,7 +2089,13 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
(void *)(uintptr_t)ba_res->reduced_txp;
tfd_cnt = le16_to_cpu(ba_res->tfd_cnt);
- if (!tfd_cnt || struct_size(ba_res, tfd, tfd_cnt) > pkt_len)
+ if (!tfd_cnt)
+ return;
+
+ if (IWL_FW_CHECK(mvm,
+ struct_size(ba_res, tfd, tfd_cnt) > pkt_len,
+ "short BA notification (tfds:%d, size:%d)\n",
+ tfd_cnt, pkt_len))
return;
rcu_read_lock();
@@ -2135,7 +2153,9 @@ void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
rcu_read_lock();
mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, sta_id);
- if (WARN_ON_ONCE(!mvmsta)) {
+ if (IWL_FW_CHECK(mvm, !mvmsta,
+ "invalid STA ID %d in BA notif\n",
+ sta_id)) {
rcu_read_unlock();
return;
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index af31b09c3966..48016b4343d2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
*/
@@ -312,6 +312,10 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
smps_mode = IEEE80211_SMPS_DYNAMIC;
}
+ /* SMPS is disabled in eSR */
+ if (mvmvif->esr_active)
+ smps_mode = IEEE80211_SMPS_OFF;
+
ieee80211_request_smps(vif, link_id, smps_mode);
}
@@ -413,16 +417,20 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_diversity_iter_data *data = _data;
- int i;
+ int i, link_id;
- if (mvmvif->deflink.phy_ctxt != data->ctxt)
- return;
+ for_each_mvm_vif_valid_link(mvmvif, link_id) {
+ struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
- for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
- if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC ||
- mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
- data->result = false;
- break;
+ if (link_info->phy_ctxt != data->ctxt)
+ continue;
+
+ for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
+ if (link_info->smps_requests[i] == IEEE80211_SMPS_STATIC ||
+ link_info->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) {
+ data->result = false;
+ break;
+ }
}
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
index cb60ba40fe97..fa4a14546860 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-fh.h"
@@ -281,70 +281,273 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive)
trans_pcie->prph_info = NULL;
}
-int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
- const void *data, u32 len)
+static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_data,
+ struct iwl_dram_data *dram)
+{
+ u32 len, len0, len1;
+
+ if (pnvm_data->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) {
+ IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n",
+ pnvm_data->n_chunks);
+ return -EINVAL;
+ }
+
+ len0 = pnvm_data->chunks[0].len;
+ len1 = pnvm_data->chunks[1].len;
+ if (len1 > 0xFFFFFFFF - len0) {
+ IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n");
+ return -EINVAL;
+ }
+ len = len0 + len1;
+
+ dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len,
+ &dram->physical);
+ if (!dram->block) {
+ IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n");
+ return -ENOMEM;
+ }
+
+ dram->size = len;
+ memcpy(dram->block, pnvm_data->chunks[0].data, len0);
+ memcpy((u8 *)dram->block + len0, pnvm_data->chunks[1].data, len1);
+
+ return 0;
+}
+
+static int iwl_pcie_load_payloads_segments
+ (struct iwl_trans *trans,
+ struct iwl_dram_regions *dram_regions,
+ const struct iwl_pnvm_image *pnvm_data)
+{
+ struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0];
+ struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
+ struct iwl_prph_scrath_mem_desc_addr_array *addresses;
+ const void *data;
+ u32 len;
+ int i;
+
+ /* allocate and init DRAM descriptors array */
+ len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array);
+ desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent
+ (trans,
+ len,
+ &desc_dram->physical);
+ if (!desc_dram->block) {
+ IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n");
+ return -ENOMEM;
+ }
+ desc_dram->size = len;
+ memset(desc_dram->block, 0, len);
+
+ /* allocate DRAM region for each payload */
+ dram_regions->n_regions = 0;
+ for (i = 0; i < pnvm_data->n_chunks; i++) {
+ len = pnvm_data->chunks[i].len;
+ data = pnvm_data->chunks[i].data;
+
+ if (iwl_pcie_ctxt_info_alloc_dma(trans,
+ data,
+ len,
+ cur_payload_dram)) {
+ iwl_trans_pcie_free_pnvm_dram_regions(dram_regions,
+ trans->dev);
+ return -ENOMEM;
+ }
+
+ dram_regions->n_regions++;
+ cur_payload_dram++;
+ }
+
+ /* fill desc with the DRAM payloads addresses */
+ addresses = desc_dram->block;
+ for (i = 0; i < pnvm_data->n_chunks; i++) {
+ addresses->mem_descs[i] =
+ cpu_to_le64(dram_regions->drams[i].physical);
+ }
+
+ return 0;
+
+}
+
+int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *pnvm_payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
- int ret;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data;
+ int ret = 0;
+
+ /* only allocate the DRAM if not allocated yet */
+ if (trans->pnvm_loaded)
+ return 0;
+
+ if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
+ return -EBUSY;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
- /* only allocate the DRAM if not allocated yet */
- if (!trans->pnvm_loaded) {
- if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size))
- return -EBUSY;
-
- ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
- &trans_pcie->pnvm_dram);
- if (ret < 0) {
- IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n",
- ret);
- return ret;
+ if (!pnvm_payloads->n_chunks) {
+ IWL_DEBUG_FW(trans, "no payloads\n");
+ return -EINVAL;
+ }
+
+ /* save payloads in several DRAM sections */
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) {
+ ret = iwl_pcie_load_payloads_segments(trans,
+ dram_regions,
+ pnvm_payloads);
+ if (!ret)
+ trans->pnvm_loaded = true;
+ } else {
+ /* save only in one DRAM section */
+ ret = iwl_pcie_load_payloads_continuously
+ (trans,
+ pnvm_payloads,
+ &dram_regions->drams[0]);
+ if (!ret) {
+ dram_regions->n_regions = 1;
+ trans->pnvm_loaded = true;
}
}
+ return ret;
+}
+
+static inline size_t
+iwl_dram_regions_size(const struct iwl_dram_regions *dram_regions)
+{
+ size_t total_size = 0;
+ int i;
+
+ for (i = 0; i < dram_regions->n_regions; i++)
+ total_size += dram_regions->drams[i].size;
+
+ return total_size;
+}
+
+static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data;
+
prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
- cpu_to_le64(trans_pcie->pnvm_dram.physical);
+ cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical);
prph_sc_ctrl->pnvm_cfg.pnvm_size =
- cpu_to_le32(trans_pcie->pnvm_dram.size);
+ cpu_to_le32(iwl_dram_regions_size(dram_regions));
+}
- return 0;
+static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+
+ prph_sc_ctrl->pnvm_cfg.pnvm_base_addr =
+ cpu_to_le64(trans_pcie->pnvm_data.drams[0].physical);
+ prph_sc_ctrl->pnvm_cfg.pnvm_size =
+ cpu_to_le32(trans_pcie->pnvm_data.drams[0].size);
+}
+
+void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return;
+
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
+ iwl_pcie_set_pnvm_segments(trans);
+ else
+ iwl_pcie_set_continuous_pnvm(trans);
}
-int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
- const void *data, u32 len)
+int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
+ const struct iwl_pnvm_image *payloads,
+ const struct iwl_ucode_capabilities *capa)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
&trans_pcie->prph_scratch->ctrl_cfg;
- int ret;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data;
+ int ret = 0;
+
+ /* only allocate the DRAM if not allocated yet */
+ if (trans->reduce_power_loaded)
+ return 0;
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
return 0;
- /* only allocate the DRAM if not allocated yet */
- if (!trans->reduce_power_loaded) {
- if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
- return -EBUSY;
+ if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size))
+ return -EBUSY;
- ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len,
- &trans_pcie->reduce_power_dram);
- if (ret < 0) {
- IWL_DEBUG_FW(trans,
- "Failed to allocate reduce power DMA %d.\n",
- ret);
- return ret;
+ if (!payloads->n_chunks) {
+ IWL_DEBUG_FW(trans, "no payloads\n");
+ return -EINVAL;
+ }
+
+ /* save payloads in several DRAM sections */
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) {
+ ret = iwl_pcie_load_payloads_segments(trans,
+ dram_regions,
+ payloads);
+ if (!ret)
+ trans->reduce_power_loaded = true;
+ } else {
+ /* save only in one DRAM section */
+ ret = iwl_pcie_load_payloads_continuously
+ (trans,
+ payloads,
+ &dram_regions->drams[0]);
+ if (!ret) {
+ dram_regions->n_regions = 1;
+ trans->reduce_power_loaded = true;
}
}
+ return ret;
+}
+
+static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+ struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data;
+
prph_sc_ctrl->reduce_power_cfg.base_addr =
- cpu_to_le64(trans_pcie->reduce_power_dram.physical);
+ cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical);
prph_sc_ctrl->reduce_power_cfg.size =
- cpu_to_le32(trans_pcie->reduce_power_dram.size);
+ cpu_to_le32(iwl_dram_regions_size(dram_regions));
+}
- return 0;
+static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl =
+ &trans_pcie->prph_scratch->ctrl_cfg;
+
+ prph_sc_ctrl->reduce_power_cfg.base_addr =
+ cpu_to_le64(trans_pcie->reduced_tables_data.drams[0].physical);
+ prph_sc_ctrl->reduce_power_cfg.size =
+ cpu_to_le32(trans_pcie->reduced_tables_data.drams[0].size);
+}
+
+void
+iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans,
+ const struct iwl_ucode_capabilities *capa)
+{
+ if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+ return;
+
+ if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG))
+ iwl_pcie_set_reduce_power_segments(trans);
+ else
+ iwl_pcie_set_continuous_reduce_power(trans);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
index 74ce31fdf45e..5f55efe64bf5 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2022 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-fh.h"
@@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
return result;
}
-static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
- size_t size,
- dma_addr_t *phys)
+void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans,
+ size_t size,
+ dma_addr_t *phys)
{
return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 79115eb1c285..bc83d2ba55c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -484,17 +484,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x43F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0xA0F0, PCI_ANY_ID, iwl_qu_long_latency_trans_cfg)},
- {IWL_PCI_DEVICE(0x2720, PCI_ANY_ID, iwl_qnj_trans_cfg)},
-
{IWL_PCI_DEVICE(0x2723, PCI_ANY_ID, iwl_ax200_trans_cfg)},
/* So devices */
{IWL_PCI_DEVICE(0x2725, PCI_ANY_ID, iwl_so_trans_cfg)},
- {IWL_PCI_DEVICE(0x2726, PCI_ANY_ID, iwl_snj_trans_cfg)},
{IWL_PCI_DEVICE(0x7A70, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
{IWL_PCI_DEVICE(0x7AF0, PCI_ANY_ID, iwl_so_trans_cfg)},
{IWL_PCI_DEVICE(0x51F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_imr_trans_cfg)},
+ {IWL_PCI_DEVICE(0x51F1, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x54F0, PCI_ANY_ID, iwl_so_long_latency_trans_cfg)},
{IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_so_trans_cfg)},
@@ -507,6 +505,9 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)},
{IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)},
+
+/* Sc devices */
+ {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_trans_cfg)},
#endif /* CONFIG_IWLMVM */
{0}
@@ -514,17 +515,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
#define _IWL_DEV_INFO(_device, _subdevice, _mac_type, _mac_step, _rf_type, \
- _rf_id, _rf_step, _no_160, _cores, _cdb, _jacket, _cfg, \
- _name) \
+ _rf_id, _rf_step, _no_160, _cores, _cdb, _cfg, _name) \
{ .device = (_device), .subdevice = (_subdevice), .cfg = &(_cfg), \
.name = _name, .mac_type = _mac_type, .rf_type = _rf_type, .rf_step = _rf_step, \
.no_160 = _no_160, .cores = _cores, .rf_id = _rf_id, \
- .mac_step = _mac_step, .cdb = _cdb, .jacket = _jacket }
+ .mac_step = _mac_step, .cdb = _cdb, .jacket = IWL_CFG_ANY }
#define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
- _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, _cfg, _name)
+ _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, \
+ IWL_CFG_ANY, _cfg, _name)
static const struct iwl_dev_info iwl_dev_info_table[] = {
#if IS_ENABLED(CONFIG_IWLMVM)
@@ -544,6 +544,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x51F1, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
@@ -552,8 +553,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7AF0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
- IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name),
+ IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma, iwl_ax411_killer_1690s_name),
+ IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma, iwl_ax411_killer_1690i_name),
/* AX200 */
IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
@@ -663,25 +664,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
- /* SnJ with HR */
- IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0098, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x00B4, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL),
- IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name),
- IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name),
- IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),
- IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
- IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
-
/* SO with GF2 */
IWL_DEV_INFO(0x2726, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x2726, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x51F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x51F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
+ IWL_DEV_INFO(0x51F1, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
+ IWL_DEV_INFO(0x51F1, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x54F0, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
IWL_DEV_INFO(0x54F0, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
IWL_DEV_INFO(0x7A70, 0x1671, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675s_name),
@@ -692,93 +681,72 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
IWL_DEV_INFO(0x7F70, 0x1672, iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_killer_1675i_name),
/* MA with GF2 */
- IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675s_name),
- IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma_a0_gf_a0, iwl_ax211_killer_1675i_name),
+ IWL_DEV_INFO(0x7E40, 0x1671, iwl_cfg_ma, iwl_ax211_killer_1675s_name),
+ IWL_DEV_INFO(0x7E40, 0x1672, iwl_cfg_ma, iwl_ax211_killer_1675i_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_2ac_cfg_soc, iwl9560_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9461_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9260_2ac_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9270_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9270_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9162_160_name),
_IWL_DEV_INFO(0x271B, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9162_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9260_160_name),
_IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9260_2ac_cfg, iwl9260_name),
/* Qu with Jf */
@@ -786,585 +754,341 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_qu_c0_jf_b0_cfg, iwl9560_killer_1550i_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9462_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550s_name),
_IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwl9560_quz_a0_jf_b0_cfg, iwl9560_killer_1550i_name),
- /* QnJ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1551,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550s_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, 0x1552,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name),
-
/* Qu with Hr */
/* Qu B step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_b0_hr_b0, iwl_ax203_name),
/* Qu C step */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr_b0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_qu_c0_hr_b0, iwl_ax201_name),
/* QuZ */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_quz_a0_hr1_b0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_quz_a0_hr_b0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_QUZ, SILICON_B_STEP,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_quz_a0_hr_b0, iwl_ax201_name),
-/* QnJ with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_QNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name),
-
-/* SnJ with Jf */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9461_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9461_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9462_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9462_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9560_160_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_jf_b0, iwl9560_name),
-
-/* SnJ with Hr */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_hr_b0, iwl_ax101_name),
-
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_hr_b0, iwl_ax201_name),
-
/* Ma */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_hr_b0, iwl_ax201_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_gf_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_gf4_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_mr_a0, iwl_ax221_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_fm_a0, iwl_ax231_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_mr_a0, iwl_ax221_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_hr_b0, iwl_ax201_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax201_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_gf_a0, iwl_ax211_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_gf4_a0, iwl_ax211_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_ma, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_mr_a0, iwl_ax221_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax221_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_MA, SILICON_B_STEP,
+ IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_b0_fm_a0, iwl_ax231_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax231_name),
/* So with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Hr */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_hr_a0, iwl_ax201_name),
/* So-F with Gf */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* Bz */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_hr_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_mr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_bz_a0_fm4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bz_a0_fm_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bz_a0_fm4_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_NO_JACKET,
- iwl_cfg_gl_b0_fm_b0, iwl_bz_name),
-
-/* BZ Z step */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bz_z0_gf_a0, iwl_bz_name),
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_bz_name),
-/* BNJ */
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_fm_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_fm_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_A_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_fm4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, SILICON_B_STEP,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_fm4_b0, iwl_bz_name),
+/* Ga (Gl) */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_gf_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_a0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_IS_JACKET,
- iwl_cfg_bnj_b0_gf4_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_a0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_A_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_a0_hr_b0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_b0_hr_a0, iwl_bz_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_GL, SILICON_B_STEP,
- IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_bnj_b0_hr_b0, iwl_bz_name),
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_gl, iwl_bz_name),
/* SoF with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* SoF with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* So with GF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
/* So with JF2 */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
/* So with JF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV, IWL_CFG_ANY,
- IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* MsP */
@@ -1372,24 +1096,25 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
iwl_cfg_so_a0_ms_a0, iwl_ax204_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_MA, IWL_CFG_ANY,
IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_ma_a0_ms_a0, iwl_ax204_name),
- _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_MAC_TYPE_SNJ, IWL_CFG_ANY,
- IWL_CFG_RF_TYPE_MS, IWL_CFG_ANY, IWL_CFG_ANY,
- IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, IWL_CFG_ANY,
- iwl_cfg_snj_a0_ms_a0, iwl_ax204_name)
+ IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+ iwl_cfg_ma, iwl_ax204_name),
+/* Sc */
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_SC, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_sc, iwl_sc_name),
#endif /* CONFIG_IWLMVM */
};
@@ -1407,12 +1132,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
else
sd_reg_ver_addr = SD_REG_VER;
- if (!iwl_trans_grab_nic_access(iwl_trans)) {
- IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n");
- ret = -EIO;
- goto out;
- }
-
/* Enable access to peripheral registers */
val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG);
val |= ENABLE_WFPM;
@@ -1432,9 +1151,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id,
iwl_trans->hw_wfpm_id);
- iwl_trans_release_nic_access(iwl_trans);
-
-out:
return ret;
}
@@ -1626,6 +1342,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto out_free_trans;
if (iwl_trans_grab_nic_access(iwl_trans)) {
+ get_crf_id(iwl_trans);
/* all good */
iwl_trans_release_nic_access(iwl_trans);
} else {
@@ -1635,7 +1352,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
- get_crf_id(iwl_trans);
/*
* The RF_ID is set to zero in blank OTP so read version to
@@ -1669,17 +1385,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
#if IS_ENABLED(CONFIG_IWLMVM)
-
- /*
- * Workaround for problematic SnJ device: sometimes when
- * certain RF modules are connected to SnJ, the device ID
- * changes to QnJ's ID. So we are using QnJ's trans_cfg until
- * here. But if we detect that the MAC type is actually SnJ,
- * we should switch to it here to avoid problems later.
- */
- if (CSR_HW_REV_TYPE(iwl_trans->hw_rev) == IWL_CFG_MAC_TYPE_SNJ)
- iwl_trans->trans_cfg = &iwl_so_trans_cfg;
-
/*
* special-case 7265D, it has the same PCI IDs.
*
@@ -1752,6 +1457,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
}
+ if (!iwl_trans->trans_cfg->integrated) {
+ u16 link_status;
+
+ pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &link_status);
+
+ iwl_trans->pcie_link_speed =
+ u16_get_bits(link_status, PCI_EXP_LNKSTA_CLS);
+ }
+
ret = iwl_trans_init(iwl_trans);
if (ret)
goto out_free_trans;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
index 69b95ad5993b..0adcf0e13e85 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -23,6 +23,7 @@
#include "iwl-op-mode.h"
#include "iwl-drv.h"
#include "queue/tx.h"
+#include "iwl-context-info.h"
/*
* RX related structures and functions
@@ -306,7 +307,9 @@ enum iwl_pcie_imr_status {
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
* @kw: keep warm address
- * @pnvm_dram: DRAM area that contains the PNVM data
+ * @pnvm_data: holds info about pnvm payloads allocated in DRAM
+ * @reduced_tables_data: holds info about power reduced tablse
+ * payloads allocated in DRAM
* @pci_dev: basic pci-network driver stuff
* @hw_base: pci hardware address support
* @ucode_write_complete: indicates that the ucode has been copied.
@@ -380,8 +383,9 @@ struct iwl_trans_pcie {
u32 scd_base_addr;
struct iwl_dma_ptr kw;
- struct iwl_dram_data pnvm_dram;
- struct iwl_dram_data reduce_power_dram;
+ /* pnvm data */
+ struct iwl_dram_regions pnvm_data;
+ struct iwl_dram_regions reduced_tables_data;
struct iwl_txq *txq_memory;
@@ -478,6 +482,8 @@ struct iwl_trans
const struct pci_device_id *ent,
const struct iwl_cfg_trans_params *cfg_trans);
void iwl_trans_pcie_free(struct iwl_trans *trans);
+void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
+ struct device *dev);
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
#define _iwl_trans_pcie_grab_nic_access(trans) \
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 0d7890f99a5f..f87b28edc267 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -699,17 +699,25 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans,
rxq->used_bd = NULL;
}
+static size_t iwl_pcie_rb_stts_size(struct iwl_trans *trans)
+{
+ bool use_rx_td = (trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_AX210);
+
+ if (use_rx_td)
+ return sizeof(__le16);
+
+ return sizeof(struct iwl_rb_status);
+}
+
static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
struct iwl_rxq *rxq)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct device *dev = trans->dev;
int i;
int free_size;
- bool use_rx_td = (trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210);
- size_t rb_stts_size = use_rx_td ? sizeof(__le16) :
- sizeof(struct iwl_rb_status);
spin_lock_init(&rxq->lock);
if (trans->trans_cfg->mq_rx_supported)
@@ -757,11 +765,9 @@ err:
static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i, ret;
- size_t rb_stts_size = trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210 ?
- sizeof(__le16) : sizeof(struct iwl_rb_status);
if (WARN_ON(trans_pcie->rxq))
return -EINVAL;
@@ -1193,11 +1199,9 @@ int iwl_pcie_gen2_rx_init(struct iwl_trans *trans)
void iwl_pcie_rx_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ size_t rb_stts_size = iwl_pcie_rb_stts_size(trans);
struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i;
- size_t rb_stts_size = trans->trans_cfg->device_family >=
- IWL_DEVICE_FAMILY_AX210 ?
- sizeof(__le16) : sizeof(struct iwl_rb_status);
/*
* if rxq is NULL, it means that nothing has been allocated,
@@ -1636,14 +1640,14 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
struct msix_entry *entry = dev_id;
struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry);
struct iwl_trans *trans = trans_pcie->trans;
- struct iwl_rxq *rxq = &trans_pcie->rxq[entry->entry];
+ struct iwl_rxq *rxq;
trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0);
if (WARN_ON(entry->entry >= trans->num_rx_queues))
return IRQ_NONE;
- if (!rxq) {
+ if (!trans_pcie->rxq) {
if (net_ratelimit())
IWL_ERR(trans,
"[%d] Got MSI-X interrupt before we have Rx queues\n",
@@ -1651,6 +1655,7 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
return IRQ_NONE;
}
+ rxq = &trans_pcie->rxq[entry->entry];
lock_map_acquire(&trans->sync_cmd_lockdep_map);
IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry);
@@ -1873,7 +1878,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
return IRQ_NONE;
}
- if (unlikely(inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+ if (unlikely(inta == 0xFFFFFFFF || iwl_trans_is_hw_error_value(inta))) {
/*
* Hardware disappeared. It might have
* already raised an interrupt.
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
index 73b395841ca8..fa46dad5fd68 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#include "iwl-trans.h"
#include "iwl-prph.h"
@@ -117,9 +117,14 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
trans_pcie->fw_reset_state != FW_RESET_REQUESTED,
FW_RESET_TIMEOUT);
if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) {
- IWL_INFO(trans,
- "firmware didn't ACK the reset - continue anyway\n");
- iwl_trans_fw_error(trans, true);
+ u32 inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
+
+ IWL_ERR(trans,
+ "timeout waiting for FW reset ACK (inta_hw=0x%x)\n",
+ inta_hw);
+
+ if (!(inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE))
+ iwl_trans_fw_error(trans, true);
}
trans_pcie->fw_reset_state = FW_RESET_IDLE;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index b281850fbf7a..3e988da44973 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2007-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2007-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -131,13 +131,15 @@ static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
bool retake_ownership)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_SW_RESET);
- else
+ usleep_range(10000, 20000);
+ } else {
iwl_set_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(5000, 6000);
+ usleep_range(5000, 6000);
+ }
if (retake_ownership)
return iwl_pcie_prepare_card_hw(trans);
@@ -161,7 +163,7 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
}
static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
- u8 max_power, u8 min_power)
+ u8 max_power)
{
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
void *block = NULL;
@@ -169,10 +171,13 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
u32 size = 0;
u8 power;
- if (fw_mon->size)
+ if (fw_mon->size) {
+ memset(fw_mon->block, 0, fw_mon->size);
return;
+ }
- for (power = max_power; power >= min_power; power--) {
+ /* need at least 2 KiB, so stop at 11 */
+ for (power = max_power; power >= 11; power--) {
size = BIT(power);
block = dma_alloc_coherent(trans->dev, size, &physical,
GFP_KERNEL | __GFP_NOWARN);
@@ -213,10 +218,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
max_power))
return;
- if (trans->dbg.fw_mon.size)
- return;
-
- iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11);
+ iwl_pcie_alloc_fw_monitor_block(trans, max_power);
}
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
@@ -475,7 +477,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
100);
- msleep(100);
+ usleep_range(10000, 20000);
} else {
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
@@ -817,7 +819,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
iwl_enable_interrupts(trans);
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
if (cpu == 1)
iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS,
0xFFFF);
@@ -1786,7 +1788,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
}
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
- if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
+ if (!iwl_trans_is_hw_error_value(hpm) && (hpm & PERSISTENCE_BIT)) {
u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
if (wprot_val & PREG_WFPM_ACCESS) {
@@ -1993,6 +1995,29 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake;
}
+void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
+ struct device *dev)
+{
+ u8 i;
+ struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
+
+ /* free DRAM payloads */
+ for (i = 0; i < dram_regions->n_regions; i++) {
+ dma_free_coherent(dev, dram_regions->drams[i].size,
+ dram_regions->drams[i].block,
+ dram_regions->drams[i].physical);
+ }
+ dram_regions->n_regions = 0;
+
+ /* free DRAM addresses array */
+ if (desc_dram->block) {
+ dma_free_coherent(dev, desc_dram->size,
+ desc_dram->block,
+ desc_dram->physical);
+ }
+ memset(desc_dram, 0, sizeof(*desc_dram));
+}
+
void iwl_trans_pcie_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2025,16 +2050,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_free_fw_monitor(trans);
- if (trans_pcie->pnvm_dram.size)
- dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size,
- trans_pcie->pnvm_dram.block,
- trans_pcie->pnvm_dram.physical);
-
- if (trans_pcie->reduce_power_dram.size)
- dma_free_coherent(trans->dev,
- trans_pcie->reduce_power_dram.size,
- trans_pcie->reduce_power_dram.block,
- trans_pcie->reduce_power_dram.physical);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data,
+ trans->dev);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data,
+ trans->dev);
mutex_destroy(&trans_pcie->mutex);
iwl_trans_free(trans);
@@ -3375,7 +3394,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans,
u8 tfdidx;
u32 caplen, cmdlen;
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
tfdidx = idx;
else
tfdidx = ptr;
@@ -3534,7 +3553,9 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_free = iwl_txq_dyn_free,
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
.rxq_dma_data = iwl_trans_pcie_rxq_dma_data,
+ .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm,
.set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm,
+ .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power,
.set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup,
@@ -3576,7 +3597,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
init_waitqueue_head(&trans_pcie->imr_waitq);
trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator",
- WQ_HIGHPRI | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_UNBOUND, 0);
if (!trans_pcie->rba.alloc_wq) {
ret = -ENOMEM;
goto out_free_trans;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 3546c5269c3b..790e5b124740 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2003-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2003-2014, 2018-2021, 2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -364,7 +364,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
txq_id++) {
struct iwl_txq *txq = trans->txqs.txq[txq_id];
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
iwl_write_direct64(trans,
FH_MEM_CBBC_QUEUE(trans, txq_id),
txq->dma_addr);
@@ -1547,6 +1547,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
/* there must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd, scratch) >
+ IWL_FIRST_TB_SIZE);
/* map the data for TB1 */
tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE;
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
index d1c39c214f95..5bb3cc3367c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
*/
#include <net/tso.h>
#include <linux/tcp.h>
@@ -648,6 +648,13 @@ struct iwl_tfh_tfd *iwl_txq_gen2_build_tfd(struct iwl_trans *trans,
/* There must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd_gen2, dram_info) >
+ IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) < IWL_FIRST_TB_SIZE);
+ BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
+ offsetofend(struct iwl_tx_cmd_gen3, dram_info) >
+ IWL_FIRST_TB_SIZE);
memset(tfd, 0, sizeof(*tfd));
@@ -978,7 +985,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
bool active;
u8 fifo;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
txq->read_ptr, txq->write_ptr);
/* TODO: access new SCD registers and dump them */
@@ -1027,10 +1034,13 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
size_t tb0_buf_sz;
int i;
+ if (WARN_ONCE(slots_num <= 0, "Invalid slots num:%d\n", slots_num))
+ return -EINVAL;
+
if (WARN_ON(txq->entries || txq->tfds))
return -EINVAL;
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
tfd_sz = trans->txqs.tfd.size * slots_num;
timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0);
@@ -1337,7 +1347,7 @@ static inline dma_addr_t iwl_txq_gen1_tfd_tb_get_addr(struct iwl_trans *trans,
dma_addr_t addr;
dma_addr_t hi_len;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
@@ -1398,7 +1408,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans,
meta->tbs = 0;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
tfd_fh->num_tbs = 0;
@@ -1615,7 +1625,7 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
txq->entries[read_ptr].skb = NULL;
- if (!trans->trans_cfg->use_tfh)
+ if (!trans->trans_cfg->gen2)
iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq);
iwl_txq_free_tfd(trans, txq);
diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.h b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
index eca53bfd326d..1e4a24ab9bab 100644
--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.h
+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
*/
#ifndef __iwl_trans_queue_tx_h__
#define __iwl_trans_queue_tx_h__
@@ -38,7 +38,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
static inline void *iwl_txq_get_tfd(struct iwl_trans *trans,
struct iwl_txq *txq, int idx)
{
- if (trans->trans_cfg->use_tfh)
+ if (trans->trans_cfg->gen2)
idx = iwl_txq_get_cmd_index(txq, idx);
return (u8 *)txq->tfds + trans->txqs.tfd.size * idx;
@@ -135,7 +135,7 @@ static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans,
{
struct iwl_tfd *tfd;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
return le16_to_cpu(tfh_tfd->num_tbs) & 0x1f;
@@ -151,7 +151,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
struct iwl_tfd *tfd;
struct iwl_tfd_tb *tb;
- if (trans->trans_cfg->use_tfh) {
+ if (trans->trans_cfg->gen2) {
struct iwl_tfh_tfd *tfh_tfd = _tfd;
struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
diff --git a/drivers/net/wireless/intersil/hostap/Kconfig b/drivers/net/wireless/intersil/hostap/Kconfig
index c865d3156cea..2edff8efbcbb 100644
--- a/drivers/net/wireless/intersil/hostap/Kconfig
+++ b/drivers/net/wireless/intersil/hostap/Kconfig
@@ -56,7 +56,7 @@ config HOSTAP_FIRMWARE_NVRAM
config HOSTAP_PLX
tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors"
- depends on PCI && HOSTAP
+ depends on PCI && HOSTAP && HAS_IOPORT
help
Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based
PCI adaptors.
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
index 26287b129d18..b4adfc190ae8 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
@@ -3630,7 +3630,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
param->u.crypt.key_len = 0;
param->u.crypt.idx = 0xff;
} else {
- strncpy(param->u.crypt.alg, (*crypt)->ops->name,
+ strscpy(param->u.crypt.alg, (*crypt)->ops->name,
HOSTAP_CRYPT_ALG_NAME_LEN);
param->u.crypt.key_len = 0;
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
index a956f965a1e5..03bfd2482656 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
@@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link)
{
struct orinoco_private *priv;
struct orinoco_pccard *card;
+ int ret;
priv = alloc_orinocodev(sizeof(*card), &link->dev,
orinoco_cs_hard_reset, NULL);
@@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- return orinoco_cs_config(link);
-} /* orinoco_cs_attach */
+ ret = orinoco_cs_config(link);
+ if (ret)
+ goto err_free_orinocodev;
+
+ return 0;
+
+err_free_orinocodev:
+ free_orinocodev(priv);
+ return ret;
+}
static void orinoco_cs_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index dd31929261ab..866e0230df25 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -129,18 +129,18 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
#define USB_AVAYA8_VENDOR_ID 0x0D98
#define USB_AVAYAE_VENDOR_ID 0x0D9E
-#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya Wireless USB Card */
+#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya USB Wireless Card */
#define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */
-#define USB_AGERE_MODEL0801_ID 0x1000 /* Wireless USB Card Model 0801 */
-#define USB_AGERE_MODEL0802_ID 0x1001 /* Wireless USB Card Model 0802 */
-#define USB_AGERE_REBRANDED_ID 0x047A /* WLAN USB Card */
+#define USB_AGERE_MODEL0801_ID 0x1000 /* USB Wireless Card Model 0801 */
+#define USB_AGERE_MODEL0802_ID 0x1001 /* USB Wireless Card Model 0802 */
+#define USB_AGERE_REBRANDED_ID 0x047A /* USB WLAN Card */
#define USB_ELSA_VENDOR_ID 0x05CC
#define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */
#define USB_LEGEND_VENDOR_ID 0x0E7C
-#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet WLAN USB Card */
+#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet USB WLAN Card */
#define USB_SAMSUNG_VENDOR_ID 0x04E8
#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
@@ -154,7 +154,7 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
#define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */
#define USB_2WIRE_VENDOR_ID 0x1630
-#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire Wireless USB adapter */
+#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire USB Wireless adapter */
#define EZUSB_REQUEST_FW_TRANS 0xA0
diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
index 291ef97ed45e..841d623c621a 100644
--- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
@@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link)
{
struct orinoco_private *priv;
struct orinoco_pccard *card;
+ int ret;
priv = alloc_orinocodev(sizeof(*card), &link->dev,
spectrum_cs_hard_reset,
@@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link)
card->p_dev = link;
link->priv = priv;
- return spectrum_cs_config(link);
-} /* spectrum_cs_attach */
+ ret = spectrum_cs_config(link);
+ if (ret)
+ goto err_free_orinocodev;
+
+ return 0;
+
+err_free_orinocodev:
+ free_orinocodev(priv);
+ return ret;
+}
static void spectrum_cs_detach(struct pcmcia_device *link)
{
diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c
index 19152fd449ba..ce0179b8ab36 100644
--- a/drivers/net/wireless/intersil/p54/p54spi.c
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
@@ -28,6 +28,7 @@
#endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */
MODULE_FIRMWARE("3826.arm");
+MODULE_FIRMWARE("3826.eeprom");
/* gpios should be handled in board files and provided via platform data,
* but because it's currently impossible for p54spi to have a header file
diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c
index 1f57a0055bbd..8ace797ce951 100644
--- a/drivers/net/wireless/legacy/ray_cs.c
+++ b/drivers/net/wireless/legacy/ray_cs.c
@@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev)
{
ray_dev_t *local;
struct net_device *dev;
+ int ret;
dev_dbg(&p_dev->dev, "ray_attach()\n");
/* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t));
if (!dev)
- goto fail_alloc_dev;
+ return -ENOMEM;
local = netdev_priv(dev);
local->finder = p_dev;
@@ -313,16 +314,20 @@ static int ray_probe(struct pcmcia_device *p_dev)
timer_setup(&local->timer, NULL, 0);
this_device = p_dev;
- return ray_config(p_dev);
+ ret = ray_config(p_dev);
+ if (ret)
+ goto err_free_dev;
-fail_alloc_dev:
- return -ENOMEM;
-} /* ray_attach */
+ return 0;
+
+err_free_dev:
+ free_netdev(dev);
+ return ret;
+}
static void ray_detach(struct pcmcia_device *link)
{
struct net_device *dev;
- ray_dev_t *local;
dev_dbg(&link->dev, "ray_detach\n");
@@ -331,9 +336,6 @@ static void ray_detach(struct pcmcia_device *link)
ray_release(link);
- local = netdev_priv(dev);
- del_timer_sync(&local->timer);
-
if (link->priv) {
unregister_netdev(dev);
free_netdev(dev);
@@ -625,7 +627,7 @@ static void init_startup_params(ray_dev_t *local)
local->sparm.b4.a_acting_as_ap_status = TYPE_STA;
if (essid != NULL)
- strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
+ strscpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
} /* init_startup_params */
/*===========================================================================*/
@@ -734,11 +736,14 @@ static void ray_release(struct pcmcia_device *link)
dev_dbg(&link->dev, "ray_release\n");
- del_timer(&local->timer);
+ del_timer_sync(&local->timer);
- iounmap(local->sram);
- iounmap(local->rmem);
- iounmap(local->amem);
+ if (local->sram)
+ iounmap(local->sram);
+ if (local->rmem)
+ iounmap(local->rmem);
+ if (local->amem)
+ iounmap(local->amem);
pcmcia_disable_device(link);
dev_dbg(&link->dev, "ray_release ending\n");
diff --git a/drivers/net/wireless/legacy/rayctl.h b/drivers/net/wireless/legacy/rayctl.h
index 2b0f332043d7..1f3bde8ac73d 100644
--- a/drivers/net/wireless/legacy/rayctl.h
+++ b/drivers/net/wireless/legacy/rayctl.h
@@ -577,7 +577,7 @@ struct tx_msg {
struct tib_structure tib;
struct phy_header phy;
struct mac_header mac;
- UCHAR var[1];
+ UCHAR var[];
};
/****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800 */
diff --git a/drivers/net/wireless/legacy/rndis_wlan.c b/drivers/net/wireless/legacy/rndis_wlan.c
index 712038d46bdb..e7fea7ded6d5 100644
--- a/drivers/net/wireless/legacy/rndis_wlan.c
+++ b/drivers/net/wireless/legacy/rndis_wlan.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Driver for RNDIS based wireless USB devices.
+ * Driver for RNDIS based USB wireless devices.
*
* Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
* Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@iki.fi>
diff --git a/drivers/net/wireless/legacy/wl3501_cs.c b/drivers/net/wireless/legacy/wl3501_cs.c
index 7fb2f9513476..c45c4b7cbbaf 100644
--- a/drivers/net/wireless/legacy/wl3501_cs.c
+++ b/drivers/net/wireless/legacy/wl3501_cs.c
@@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
{
struct net_device *dev;
struct wl3501_card *this;
+ int ret;
/* The io structure describes IO port mapping */
p_dev->resource[0]->end = 16;
@@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
dev = alloc_etherdev(sizeof(struct wl3501_card));
if (!dev)
- goto out_link;
-
+ return -ENOMEM;
dev->netdev_ops = &wl3501_netdev_ops;
dev->watchdog_timeo = 5 * HZ;
@@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
netif_stop_queue(dev);
p_dev->priv = dev;
- return wl3501_config(p_dev);
-out_link:
- return -ENOMEM;
+ ret = wl3501_config(p_dev);
+ if (ret)
+ goto out_free_etherdev;
+
+ return 0;
+
+out_free_etherdev:
+ free_netdev(dev);
+ return ret;
}
static int wl3501_config(struct pcmcia_device *link)
diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h
index 94b5e3e4ba08..7738ebe1fec1 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n.h
+++ b/drivers/net/wireless/marvell/mwifiex/11n.h
@@ -102,14 +102,14 @@ static inline u8 mwifiex_space_avail_for_new_ba_stream(
{
struct mwifiex_private *priv;
u8 i;
- u32 ba_stream_num = 0, ba_stream_max;
+ size_t ba_stream_num = 0, ba_stream_max;
ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED;
for (i = 0; i < adapter->priv_num; i++) {
priv = adapter->priv[i];
if (priv)
- ba_stream_num += mwifiex_wmm_list_len(
+ ba_stream_num += list_count_nodes(
&priv->tx_ba_stream_tbl_ptr);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index bcd564dc3554..813d1cbebe19 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3127,7 +3127,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1, name);
+ WQ_UNBOUND, 0, name);
if (!priv->dfs_cac_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
ret = -ENOMEM;
@@ -3138,7 +3138,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1, name);
+ WQ_MEM_RECLAIM, 0, name);
if (!priv->dfs_chan_sw_workqueue) {
mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");
ret = -ENOMEM;
@@ -3753,10 +3753,10 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
*/
static int
mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer, u8 action_code, u8 dialog_token,
- u16 status_code, u32 peer_capability,
- bool initiator, const u8 *extra_ies,
- size_t extra_ies_len)
+ const u8 *peer, int link_id, u8 action_code,
+ u8 dialog_token, u16 status_code,
+ u32 peer_capability, bool initiator,
+ const u8 *extra_ies, size_t extra_ies_len)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int ret;
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index 52b18f4a774b..0cdd6c50c1c0 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -253,8 +253,11 @@ mwifiex_histogram_read(struct file *file, char __user *ubuf,
if (!p)
return -ENOMEM;
- if (!priv || !priv->hist_data)
- return -EFAULT;
+ if (!priv || !priv->hist_data) {
+ ret = -EFAULT;
+ goto free_and_exit;
+ }
+
phist_data = priv->hist_data;
p += sprintf(p, "\n"
@@ -309,6 +312,8 @@ mwifiex_histogram_read(struct file *file, char __user *ubuf,
ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
(unsigned long)p - page);
+free_and_exit:
+ free_page(page);
return ret;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index ea22a08e6c08..1cd9d20cca16 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -1547,7 +1547,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter)
adapter->workqueue =
alloc_workqueue("MWIFIEX_WORK_QUEUE",
- WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (!adapter->workqueue)
goto err_kmalloc;
@@ -1557,7 +1557,7 @@ mwifiex_reinit_sw(struct mwifiex_adapter *adapter)
adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1);
+ WQ_UNBOUND, 0);
if (!adapter->rx_workqueue)
goto err_kmalloc;
INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
@@ -1702,7 +1702,7 @@ mwifiex_add_card(void *card, struct completion *fw_done,
adapter->workqueue =
alloc_workqueue("MWIFIEX_WORK_QUEUE",
- WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 0);
if (!adapter->workqueue)
goto err_kmalloc;
@@ -1712,7 +1712,7 @@ mwifiex_add_card(void *card, struct completion *fw_done,
adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
WQ_HIGHPRI |
WQ_MEM_RECLAIM |
- WQ_UNBOUND, 1);
+ WQ_UNBOUND, 0);
if (!adapter->rx_workqueue)
goto err_kmalloc;
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 9a698a16a8f3..6697132ecc97 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -189,6 +189,8 @@ static int mwifiex_pcie_probe_of(struct device *dev)
}
static void mwifiex_pcie_work(struct work_struct *work);
+static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter);
+static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter);
static int
mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -792,14 +794,15 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
if (!skb) {
mwifiex_dbg(adapter, ERROR,
"Unable to allocate skb for RX ring.\n");
- kfree(card->rxbd_ring_vbase);
return -ENOMEM;
}
if (mwifiex_map_pci_memory(adapter, skb,
MWIFIEX_RX_DATA_BUF_SIZE,
- DMA_FROM_DEVICE))
- return -1;
+ DMA_FROM_DEVICE)) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
@@ -849,7 +852,6 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
if (!skb) {
mwifiex_dbg(adapter, ERROR,
"Unable to allocate skb for EVENT buf.\n");
- kfree(card->evtbd_ring_vbase);
return -ENOMEM;
}
skb_put(skb, MAX_EVENT_SIZE);
@@ -857,8 +859,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
DMA_FROM_DEVICE)) {
kfree_skb(skb);
- kfree(card->evtbd_ring_vbase);
- return -1;
+ return -ENOMEM;
}
buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
@@ -1058,6 +1059,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
*/
static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
{
+ int ret;
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
@@ -1096,7 +1098,10 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
(u32)((u64)card->rxbd_ring_pbase >> 32),
card->rxbd_ring_size);
- return mwifiex_init_rxq_ring(adapter);
+ ret = mwifiex_init_rxq_ring(adapter);
+ if (ret)
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+ return ret;
}
/*
@@ -1127,6 +1132,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
*/
static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
{
+ int ret;
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
@@ -1161,7 +1167,10 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
(u32)((u64)card->evtbd_ring_pbase >> 32),
card->evtbd_ring_size);
- return mwifiex_pcie_init_evt_ring(adapter);
+ ret = mwifiex_pcie_init_evt_ring(adapter);
+ if (ret)
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+ return ret;
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index ac8001c84293..644b1e134b01 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2187,9 +2187,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
if (nd_config) {
adapter->nd_info =
- kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
- sizeof(struct cfg80211_wowlan_nd_match *) *
- scan_rsp->number_of_sets, GFP_ATOMIC);
+ kzalloc(struct_size(adapter->nd_info, matches,
+ scan_rsp->number_of_sets),
+ GFP_ATOMIC);
if (adapter->nd_info)
adapter->nd_info->n_matches = scan_rsp->number_of_sets;
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c
index 13659b02ba88..65420ad67416 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c
@@ -86,6 +86,15 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
+ if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) {
+ mwifiex_dbg(priv->adapter, ERROR,
+ "wrong rx packet offset: len=%d, rx_pkt_off=%d\n",
+ skb->len, rx_pkt_off);
+ priv->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ return -1;
+ }
+
if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
sizeof(bridge_tunnel_header))) ||
(!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
@@ -194,7 +203,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
- if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
+ if ((rx_pkt_offset + rx_pkt_length) > skb->len ||
+ sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) {
mwifiex_dbg(adapter, ERROR,
"wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
skb->len, rx_pkt_offset, rx_pkt_length);
diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index 97bb87c3676b..6c60621b6ccc 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -735,6 +735,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
int ret;
u16 capab;
struct ieee80211_ht_cap *ht_cap;
+ unsigned int extra;
u8 radio, *pos;
capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
@@ -753,7 +754,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
switch (action_code) {
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
- skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
+ /* See the layout of 'struct ieee80211_mgmt'. */
+ extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
+ sizeof(mgmt->u.action.category);
+ skb_put(skb, extra);
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
mgmt->u.action.u.tdls_discover_resp.action_code =
WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
@@ -762,8 +766,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
mgmt->u.action.u.tdls_discover_resp.capability =
cpu_to_le16(capab);
/* move back for addr4 */
- memmove(pos + ETH_ALEN, &mgmt->u.action.category,
- sizeof(mgmt->u.action.u.tdls_discover_resp));
+ memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
/* init address 4 */
eth_broadcast_addr(pos);
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
index e495f7eaea03..b8b9a0fcb19c 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -103,6 +103,16 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
return;
}
+ if (sizeof(*rx_pkt_hdr) +
+ le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) {
+ mwifiex_dbg(adapter, ERROR,
+ "wrong rx packet offset: len=%d,rx_pkt_offset=%d\n",
+ skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
+ priv->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
sizeof(bridge_tunnel_header))) ||
(!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
@@ -243,7 +253,15 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
if (is_multicast_ether_addr(ra)) {
skb_uap = skb_copy(skb, GFP_ATOMIC);
- mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+ if (likely(skb_uap)) {
+ mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+ } else {
+ mwifiex_dbg(adapter, ERROR,
+ "failed to copy skb for uAP\n");
+ priv->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ return -1;
+ }
} else {
if (mwifiex_get_sta_entry(priv, ra)) {
/* Requeue Intra-BSS packet */
@@ -367,6 +385,16 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+ if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
+ sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) {
+ mwifiex_dbg(adapter, ERROR,
+ "wrong rx packet for struct ethhdr: len=%d, offset=%d\n",
+ skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
+ priv->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c
index 94c2d219835d..745b1d925b21 100644
--- a/drivers/net/wireless/marvell/mwifiex/util.c
+++ b/drivers/net/wireless/marvell/mwifiex/util.c
@@ -393,11 +393,15 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
}
rx_pd = (struct rxpd *)skb->data;
+ pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
+ if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) {
+ mwifiex_dbg(priv->adapter, ERROR, "invalid rx_pkt_length");
+ return -1;
+ }
skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
skb_pull(skb, sizeof(pkt_len));
-
- pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
+ pkt_len -= sizeof(pkt_len);
ieee_hdr = (void *)skb->data;
if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
@@ -410,7 +414,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
skb->data + sizeof(struct ieee80211_hdr),
pkt_len - sizeof(struct ieee80211_hdr));
- pkt_len -= ETH_ALEN + sizeof(pkt_len);
+ pkt_len -= ETH_ALEN;
rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h
index 4f53a271dae0..d7659e688933 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.h
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.h
@@ -39,21 +39,6 @@ mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)
}
/*
- * This function gets the length of a list.
- */
-static inline int
-mwifiex_wmm_list_len(struct list_head *head)
-{
- struct list_head *pos;
- int count = 0;
-
- list_for_each(pos, head)
- ++count;
-
- return count;
-}
-
-/*
* This function checks if a RA list is empty or not.
*/
static inline u8
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 6b07b8fafec2..0e9f4197213a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -277,7 +277,7 @@ struct mt76_sta_stats {
u64 tx_mcs[16]; /* mcs idx */
u64 tx_bytes;
/* WED TX */
- u32 tx_packets;
+ u32 tx_packets; /* unit: MSDU */
u32 tx_retries;
u32 tx_failed;
/* WED RX */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
index 6a0080f1d91c..dd16acfd9735 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig
@@ -5,7 +5,7 @@ config MT7603E
depends on MAC80211
depends on PCI
help
- This adds support for MT7603E wireless PCIe devices and the WLAN core
+ This adds support for MT7603E PCIe wireless devices and the WLAN core
on MT7628/MT7688 SoC devices. This family supports IEEE 802.11n 2x2
to 300Mbps PHY rate
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
index 30fba36ff46b..1ab1439143f4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig
@@ -11,7 +11,7 @@ config MT7615E
depends on MAC80211
depends on PCI
help
- This adds support for MT7615-based wireless PCIe devices,
+ This adds support for MT7615-based PCIe wireless devices,
which support concurrent dual-band operation at both 5GHz
and 2.4GHz, IEEE 802.11ac 4x4:4SS 1733Mbps PHY rate, wave2
MU-MIMO up to 4 users/group and 160MHz channels.
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
index 68e88224b8b1..ccedea7e8a50 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
@@ -128,12 +128,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
case MT_EE_5GHZ:
dev->mphy.cap.has_5ghz = true;
break;
- case MT_EE_2GHZ:
- dev->mphy.cap.has_2ghz = true;
- break;
case MT_EE_DBDC:
dev->dbdc_support = true;
fallthrough;
+ case MT_EE_2GHZ:
+ dev->mphy.cap.has_2ghz = true;
+ break;
default:
dev->mphy.cap.has_2ghz = true;
dev->mphy.cap.has_5ghz = true;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index d39a3cc5e381..e415ac5e321f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -495,6 +495,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
BSS_CHANGED_BEACON_ENABLED));
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
+ bool amsdu_en = wcid->amsdu;
if (vif) {
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
@@ -521,9 +522,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));
- /* counting non-offloading skbs */
- wcid->stats.tx_bytes += skb->len;
- wcid->stats.tx_packets++;
+ /* mt7915 WA only counts WED path */
+ if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed))
+ wcid->stats.tx_packets++;
}
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
@@ -554,12 +555,14 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
txwi[4] = 0;
val = FIELD_PREP(MT_TXD5_PID, pid);
- if (pid >= MT_PACKET_ID_FIRST)
+ if (pid >= MT_PACKET_ID_FIRST) {
val |= MT_TXD5_TX_STATUS_HOST;
+ amsdu_en = amsdu_en && !is_mt7921(dev);
+ }
txwi[5] = cpu_to_le32(val);
txwi[6] = 0;
- txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
+ txwi[7] = amsdu_en ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
if (is_8023)
mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid);
@@ -606,12 +609,11 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
txs = le32_to_cpu(txs_data[0]);
/* PPDU based reporting */
- if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
+ if (mtk_wed_device_active(&dev->mmio.wed) &&
+ FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
stats->tx_bytes +=
le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) -
le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE);
- stats->tx_packets +=
- le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT);
stats->tx_failed +=
le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
stats->tx_retries +=
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index ca1ce97a6d2f..7a52b68491b6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -998,6 +998,7 @@ enum {
MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
MCU_EXT_EVENT_RDD_REPORT = 0x3a,
MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
+ MCU_EXT_EVENT_WA_TX_STAT = 0x74,
MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
MCU_EXT_EVENT_MURU_CTRL = 0x9f,
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
index 7c88ed8b8f1e..3ed888782a70 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig
@@ -10,7 +10,7 @@ config MT76x0U
depends on MAC80211
depends on USB
help
- This adds support for MT7610U-based wireless USB 2.0 dongles,
+ This adds support for MT7610U-based USB 2.0 wireless dongles,
which comply with IEEE 802.11ac standards and support 1x1
433Mbps PHY rate.
@@ -22,7 +22,7 @@ config MT76x0E
depends on MAC80211
depends on PCI
help
- This adds support for MT7610/MT7630-based wireless PCIe devices,
+ This adds support for MT7610/MT7630-based PCIe wireless devices,
which comply with IEEE 802.11ac standards and support 1x1
433Mbps PHY rate.
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
index 5fd4973e32df..482a32b70ddf 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig
@@ -9,7 +9,7 @@ config MT76x2E
depends on MAC80211
depends on PCI
help
- This adds support for MT7612/MT7602/MT7662-based wireless PCIe
+ This adds support for MT7612/MT7602/MT7662-based PCIe wireless
devices, which comply with IEEE 802.11ac standards and support
2SS to 866Mbit/s PHY rate.
@@ -22,7 +22,7 @@ config MT76x2U
depends on MAC80211
depends on USB
help
- This adds support for MT7612U-based wireless USB 3.0 dongles,
+ This adds support for MT7612U-based USB 3.0 wireless dongles,
which comply with IEEE 802.11ac standards and support 2SS to
866Mbit/s PHY rate.
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
index d710726d47bf..3337cdfed010 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig
@@ -7,7 +7,7 @@ config MT7915E
depends on PCI
select RELAY
help
- This adds support for MT7915-based wireless PCIe devices,
+ This adds support for MT7915-based PCIe wireless devices,
which support concurrent dual-band operation at both 5GHz
and 2.4GHz IEEE 802.11ax 4x4:4SS 1024-QAM, 160MHz channels,
OFDMA, spatial reuse and dual carrier modulation.
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index ac2049f49bb3..9defd2b3c2f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -414,7 +414,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
if (!dev->dbdc_support)
vht_cap->cap |=
IEEE80211_VHT_CAP_SHORT_GI_160 |
- IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
} else {
vht_cap->cap |=
@@ -499,6 +498,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
+
+ /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
+ * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
+ */
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
}
static void
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 1b361199c061..42a983e40ade 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -269,6 +269,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
mt7915_init_bitrate_mask(vif);
+ memset(&mvif->cap, -1, sizeof(mvif->cap));
mt7915_mcu_add_bss_info(phy, vif, true);
mt7915_mcu_add_sta(dev, vif, NULL, true);
@@ -470,7 +471,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
ieee80211_wake_queues(hw);
}
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ if (changed & (IEEE80211_CONF_CHANGE_POWER |
+ IEEE80211_CONF_CHANGE_CHANNEL)) {
ret = mt7915_mcu_set_txpower_sku(phy);
if (ret)
return ret;
@@ -599,6 +601,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
{
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ int set_bss_info = -1, set_sta = -1;
mutex_lock(&dev->mt76.mutex);
@@ -607,15 +610,18 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
* and then peer references bss_info_rfch to set bandwidth cap.
*/
if (changed & BSS_CHANGED_BSSID &&
- vif->type == NL80211_IFTYPE_STATION) {
- bool join = !is_zero_ether_addr(info->bssid);
-
- mt7915_mcu_add_bss_info(phy, vif, join);
- mt7915_mcu_add_sta(dev, vif, NULL, join);
- }
-
+ vif->type == NL80211_IFTYPE_STATION)
+ set_bss_info = set_sta = !is_zero_ether_addr(info->bssid);
if (changed & BSS_CHANGED_ASSOC)
- mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
+ set_bss_info = vif->cfg.assoc;
+ if (changed & BSS_CHANGED_BEACON_ENABLED &&
+ vif->type != NL80211_IFTYPE_AP)
+ set_bss_info = set_sta = info->enable_beacon;
+
+ if (set_bss_info == 1)
+ mt7915_mcu_add_bss_info(phy, vif, true);
+ if (set_sta == 1)
+ mt7915_mcu_add_sta(dev, vif, NULL, true);
if (changed & BSS_CHANGED_ERP_CTS_PROT)
mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
@@ -629,11 +635,6 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
}
}
- if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
- mt7915_mcu_add_bss_info(phy, vif, true);
- mt7915_mcu_add_sta(dev, vif, NULL, true);
- }
-
/* ensure that enable txcmd_mode after bss_info */
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7915_mcu_set_tx(dev, vif);
@@ -650,6 +651,62 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_FILS_DISCOVERY))
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
+ if (set_bss_info == 0)
+ mt7915_mcu_add_bss_info(phy, vif, false);
+ if (set_sta == 0)
+ mt7915_mcu_add_sta(dev, vif, NULL, false);
+
+ mutex_unlock(&dev->mt76.mutex);
+}
+
+static void
+mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif)
+{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+ struct mt7915_vif_cap *vc = &mvif->cap;
+
+ vc->ht_ldpc = vif->bss_conf.ht_ldpc;
+ vc->vht_ldpc = vif->bss_conf.vht_ldpc;
+ vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer;
+ vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee;
+ vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer;
+ vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee;
+ vc->he_ldpc = vif->bss_conf.he_ldpc;
+ vc->he_su_ebfer = vif->bss_conf.he_su_beamformer;
+ vc->he_su_ebfee = vif->bss_conf.he_su_beamformee;
+ vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer;
+}
+
+static int
+mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ int err;
+
+ mutex_lock(&dev->mt76.mutex);
+
+ mt7915_vif_check_caps(phy, vif);
+
+ err = mt7915_mcu_add_bss_info(phy, vif, true);
+ if (err)
+ goto out;
+ err = mt7915_mcu_add_sta(dev, vif, NULL, true);
+out:
+ mutex_unlock(&dev->mt76.mutex);
+
+ return err;
+}
+
+static void
+mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+
+ mutex_lock(&dev->mt76.mutex);
+ mt7915_mcu_add_sta(dev, vif, NULL, false);
mutex_unlock(&dev->mt76.mutex);
}
@@ -1042,8 +1099,10 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
- sinfo->tx_packets = msta->wcid.stats.tx_packets;
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+ if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) {
+ sinfo->tx_packets = msta->wcid.stats.tx_packets;
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+ }
sinfo->tx_failed = msta->wcid.stats.tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
@@ -1526,6 +1585,8 @@ const struct ieee80211_ops mt7915_ops = {
.conf_tx = mt7915_conf_tx,
.configure_filter = mt7915_configure_filter,
.bss_info_changed = mt7915_bss_info_changed,
+ .start_ap = mt7915_start_ap,
+ .stop_ap = mt7915_stop_ap,
.sta_add = mt7915_sta_add,
.sta_remove = mt7915_sta_remove,
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 9fcb22fa1f97..1a8611c6b684 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -164,7 +164,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
}
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
- if (seq != rxd->seq)
+ if (seq != rxd->seq &&
+ !(rxd->eid == MCU_CMD_EXT_CID &&
+ rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
return -EAGAIN;
if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) {
@@ -274,7 +276,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
r = (struct mt7915_mcu_rdd_report *)skb->data;
- if (r->band_idx > MT_BAND1)
+ if (r->band_idx > MT_RX_SEL2)
return;
if ((r->band_idx && !dev->phy.mt76->band_idx) &&
@@ -395,12 +397,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
struct mt76_connac2_mcu_rxd *rxd;
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
- if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
- rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
- rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
- rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
- rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
- !rxd->seq)
+ if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT ||
+ rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
+ rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
+ rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
+ rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
+ !rxd->seq) &&
+ !(rxd->eid == MCU_CMD_EXT_CID &&
+ rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT))
mt7915_mcu_rx_unsolicited_event(dev, skb);
else
mt76_mcu_rx_event(&dev->mt76, skb);
@@ -706,6 +710,7 @@ static void
mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct ieee80211_he_mcs_nss_supp mcs_map;
struct sta_rec_he *he;
@@ -739,7 +744,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
- if (vif->bss_conf.he_ldpc &&
+ if (mvif->cap.he_ldpc &&
(elem->phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
cap |= STA_REC_HE_CAP_LDPC;
@@ -848,6 +853,7 @@ static void
mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, struct ieee80211_vif *vif)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem;
struct sta_rec_muru *muru;
struct tlv *tlv;
@@ -860,9 +866,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
muru = (struct sta_rec_muru *)tlv;
- muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformer ||
- vif->bss_conf.vht_mu_beamformee;
+ muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer ||
+ mvif->cap.vht_mu_ebfer ||
+ mvif->cap.vht_mu_ebfee;
if (!is_mt7915(&dev->mt76))
muru->cfg.mimo_ul_en = true;
muru->cfg.ofdma_dl_en = true;
@@ -995,8 +1001,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
if (sta)
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
- wtbl_hdr, vif->bss_conf.ht_ldpc,
- vif->bss_conf.vht_ldpc);
+ wtbl_hdr, mvif->cap.ht_ldpc,
+ mvif->cap.vht_ldpc);
return 0;
}
@@ -1005,6 +1011,7 @@ static inline bool
mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
{
+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -1018,10 +1025,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
if (bfee)
- return vif->bss_conf.he_su_beamformee &&
+ return mvif->cap.he_su_ebfee &&
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
else
- return vif->bss_conf.he_su_beamformer &&
+ return mvif->cap.he_su_ebfer &&
HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]);
}
@@ -1029,10 +1036,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif,
u32 cap = sta->deflink.vht_cap.cap;
if (bfee)
- return vif->bss_conf.vht_su_beamformee &&
+ return mvif->cap.vht_su_ebfee &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
else
- return vif->bss_conf.vht_su_beamformer &&
+ return mvif->cap.vht_su_ebfer &&
(cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
}
@@ -1527,7 +1534,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_TX_STBC;
if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
cap |= STA_CAP_RX_STBC;
- if (vif->bss_conf.ht_ldpc &&
+ if (mvif->cap.ht_ldpc &&
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
cap |= STA_CAP_LDPC;
@@ -1553,7 +1560,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_VHT_TX_STBC;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
cap |= STA_CAP_VHT_RX_STBC;
- if (vif->bss_conf.vht_ldpc &&
+ if (mvif->cap.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
cap |= STA_CAP_VHT_LDPC;
@@ -2993,7 +3000,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
}
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
- req, sizeof(req), true, &skb);
+ req, len * sizeof(req[0]), true, &skb);
if (ret)
return ret;
@@ -3733,6 +3740,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
+int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
+{
+ struct {
+ __le32 cmd;
+ __le32 num;
+ __le32 __rsv;
+ __le16 wlan_idx;
+ } req = {
+ .cmd = cpu_to_le32(0x15),
+ .num = cpu_to_le32(1),
+ .wlan_idx = cpu_to_le16(wlan_idx),
+ };
+ struct mt7915_mcu_wa_tx_stat {
+ __le16 wlan_idx;
+ u8 __rsv[2];
+
+ /* tx_bytes is deprecated since WA byte counter uses u32,
+ * which easily leads to overflow.
+ */
+ __le32 tx_bytes;
+ __le32 tx_packets;
+ } *res;
+ struct mt76_wcid *wcid;
+ struct sk_buff *skb;
+ int ret;
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
+ &req, sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ if (!is_mt7915(&dev->mt76))
+ skb_pull(skb, 4);
+
+ res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
+
+ if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rcu_read_lock();
+
+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
+ if (wcid)
+ wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
+ else
+ ret = -EINVAL;
+
+ rcu_read_unlock();
+out:
+ dev_kfree_skb(skb);
+
+ return ret;
+}
+
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
{
struct {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
index 45f3558bf31c..2fa059af23de 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
@@ -545,8 +545,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
- struct mt7915_phy *phy;
- int ret;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
@@ -554,43 +552,19 @@ static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed)
dev->mt76.token_size = wed->wlan.token_start;
spin_unlock_bh(&dev->mt76.token_lock);
- ret = wait_event_timeout(dev->mt76.tx_wait,
- !dev->mt76.wed_token_count, HZ);
- if (!ret)
- return -EAGAIN;
-
- phy = &dev->phy;
- mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H);
-
- phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
- if (phy)
- mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx),
- MT_AGG_ACR_PPDU_TXS2H);
-
- return 0;
+ return !wait_event_timeout(dev->mt76.tx_wait,
+ !dev->mt76.wed_token_count, HZ);
}
static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
- struct mt7915_phy *phy;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
spin_lock_bh(&dev->mt76.token_lock);
dev->mt76.token_size = MT7915_TOKEN_SIZE;
spin_unlock_bh(&dev->mt76.token_lock);
-
- /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than
- * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
- */
- phy = &dev->phy;
- mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H);
-
- phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
- if (phy)
- mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx),
- MT_AGG_ACR_PPDU_TXS2H);
}
static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index b3ead3530740..0f76733c9c1a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -147,9 +147,23 @@ struct mt7915_sta {
} twt;
};
+struct mt7915_vif_cap {
+ bool ht_ldpc:1;
+ bool vht_ldpc:1;
+ bool he_ldpc:1;
+ bool vht_su_ebfer:1;
+ bool vht_su_ebfee:1;
+ bool vht_mu_ebfer:1;
+ bool vht_mu_ebfee:1;
+ bool he_su_ebfer:1;
+ bool he_su_ebfee:1;
+ bool he_mu_ebfer:1;
+};
+
struct mt7915_vif {
struct mt76_vif mt76; /* must be first */
+ struct mt7915_vif_cap cap;
struct mt7915_sta sta;
struct mt7915_phy *phy;
@@ -539,6 +553,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
struct cfg80211_chan_def *chandef);
+int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid);
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
index f0a80c2b476a..4153cd6c2a01 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
@@ -231,10 +231,6 @@ int mt7921_dma_init(struct mt7921_dev *dev)
if (ret)
return ret;
- ret = mt7921_wfsys_reset(dev);
- if (ret)
- return ret;
-
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index bf1da9fddfab..f41975e37d06 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -113,7 +113,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
wiphy->max_sched_scan_reqs = 1;
- wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+ wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+ WIPHY_FLAG_SPLIT_SCAN_6GHZ;
wiphy->reg_notifier = mt7921_regd_notifier;
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 1675bf520481..a671c601c583 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -1180,6 +1180,10 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL;
+ err = skb_cow_head(skb, MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE);
+ if (err)
+ return err;
+
if (!wcid)
wcid = &dev->mt76.global_wcid;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 3b6adb29cbef..0e3ada1e008c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -1363,7 +1363,7 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
return -EINVAL;
if ((BIT(hweight8(tx_ant)) - 1) != tx_ant)
- tx_ant = BIT(ffs(tx_ant) - 1) - 1;
+ return -EINVAL;
mt7921_mutex_acquire(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index c69ce6df4956..f55caa00ac69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -476,12 +476,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
{
int ret;
- ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
- if (ret && mt76_is_mmio(&dev->mt76)) {
- dev_dbg(dev->mt76.dev, "Firmware is already download\n");
- goto fw_loaded;
- }
-
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
if (ret)
return ret;
@@ -504,8 +498,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
return -EIO;
}
-fw_loaded:
-
#ifdef CONFIG_PM
dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index ddb1fa4ee01d..95610a117d2f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -325,6 +325,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
bus_ops->rmw = mt7921_rmw;
dev->mt76.bus = bus_ops;
+ ret = mt7921e_mcu_fw_pmctrl(dev);
+ if (ret)
+ goto err_free_dev;
+
ret = __mt7921e_mcu_drv_pmctrl(dev);
if (ret)
goto err_free_dev;
@@ -333,6 +337,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+ ret = mt7921_wfsys_reset(dev);
+ if (ret)
+ goto err_free_dev;
+
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
index 1afa2f662e47..bb44d4a5e2dc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig
@@ -7,7 +7,7 @@ config MT7996E
depends on MAC80211
depends on PCI
help
- This adds support for MT7996-based wireless PCIe devices,
+ This adds support for MT7996-based PCIe wireless devices,
which support concurrent tri-band operation at 6GHz, 5GHz,
and 2.4GHz IEEE 802.11be 4x4:4SS 4096-QAM, 320MHz channels.
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
index 534143465d9b..fbedaacffbba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
@@ -293,7 +293,7 @@ int mt7996_dma_init(struct mt7996_dev *dev)
/* event from WA */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT_RXQ_ID(MT_RXQ_MCU_WA),
- MT7996_RX_MCU_RING_SIZE,
+ MT7996_RX_MCU_RING_SIZE_WA,
MT_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
if (ret)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 9b0f6053e0fa..25c5deb15d21 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -836,14 +836,19 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
skb_pull(skb, hdr_gap);
if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) {
pad_start = ieee80211_get_hdrlen_from_skb(skb);
- } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) &&
- get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) {
+ } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
/* When header translation failure is indicated,
* the hardware will insert an extra 2-byte field
* containing the data length after the protocol
- * type field.
+ * type field. This happens either when the LLC-SNAP
+ * pattern did not match, or if a VLAN header was
+ * detected.
*/
- pad_start = 16;
+ pad_start = 12;
+ if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)
+ pad_start += 4;
+ else
+ pad_start = 0;
}
if (pad_start) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 88e2f9d0e513..62a02b03d83b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
return;
- mphy = dev->mt76.phys[r->band_idx];
+ if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
+ mphy = dev->rdd2_phy->mt76;
+ else
+ mphy = dev->mt76.phys[r->band_idx];
+
if (!mphy)
return;
@@ -712,6 +716,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct cfg80211_chan_def *chandef = &phy->chandef;
struct mt76_connac_bss_basic_tlv *bss;
u32 type = CONNECTION_INFRA_AP;
+ u16 sta_wlan_idx = wlan_idx;
struct tlv *tlv;
int idx;
@@ -731,7 +736,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
struct mt76_wcid *wcid;
wcid = (struct mt76_wcid *)sta->drv_priv;
- wlan_idx = wcid->idx;
+ sta_wlan_idx = wcid->idx;
}
rcu_read_unlock();
}
@@ -751,7 +756,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
bss->dtim_period = vif->bss_conf.dtim_period;
bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
- bss->sta_idx = cpu_to_le16(wlan_idx);
+ bss->sta_idx = cpu_to_le16(sta_wlan_idx);
bss->conn_type = cpu_to_le32(type);
bss->omac_idx = mvif->omac_idx;
bss->band_idx = mvif->band_idx;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 4d7dcb95a620..b8bcad717d89 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -26,6 +26,7 @@
#define MT7996_RX_RING_SIZE 1536
#define MT7996_RX_MCU_RING_SIZE 512
+#define MT7996_RX_MCU_RING_SIZE_WA 1024
#define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
#define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c
index 0accc71a91c9..4644dace9bb3 100644
--- a/drivers/net/wireless/mediatek/mt76/testmode.c
+++ b/drivers/net/wireless/mediatek/mt76/testmode.c
@@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_RESET] = { .type = NLA_FLAG },
[MT76_TM_ATTR_STATE] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 },
+ [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 },
[MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 },
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 72b3ec715e47..e9b9728458a9 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -121,6 +121,7 @@ int
mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
struct sk_buff *skb)
{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
int pid;
@@ -134,8 +135,14 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
return MT_PACKET_ID_NO_ACK;
if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
- IEEE80211_TX_CTL_RATE_CTRL_PROBE)))
+ IEEE80211_TX_CTL_RATE_CTRL_PROBE))) {
+ if (mtk_wed_device_active(&dev->mmio.wed) &&
+ ((info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) ||
+ ieee80211_is_data(hdr->frame_control)))
+ return MT_PACKET_ID_WED;
+
return MT_PACKET_ID_NO_SKB;
+ }
spin_lock_bh(&dev->status_lock);
diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig
index 4a8b96280670..4880fc053d9d 100644
--- a/drivers/net/wireless/mediatek/mt7601u/Kconfig
+++ b/drivers/net/wireless/mediatek/mt7601u/Kconfig
@@ -4,4 +4,4 @@ config MT7601U
depends on MAC80211
depends on USB
help
- This adds support for MT7601U-based wireless USB dongles.
+ This adds support for MT7601U-based USB wireless dongles.
diff --git a/drivers/net/wireless/mediatek/mt7601u/debugfs.c b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
index 230b0e1061a7..dbddf256921b 100644
--- a/drivers/net/wireless/mediatek/mt7601u/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt7601u/debugfs.c
@@ -127,8 +127,6 @@ void mt7601u_init_debugfs(struct mt7601u_dev *dev)
struct dentry *dir;
dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
- if (!dir)
- return;
debugfs_create_u8("temperature", 0400, dir, &dev->raw_temp);
debugfs_create_u32("temp_mode", 0400, dir, &dev->temp_mode);
diff --git a/drivers/net/wireless/mediatek/mt7601u/trace.h b/drivers/net/wireless/mediatek/mt7601u/trace.h
index 5a6ba015085f..07696b672161 100644
--- a/drivers/net/wireless/mediatek/mt7601u/trace.h
+++ b/drivers/net/wireless/mediatek/mt7601u/trace.h
@@ -16,7 +16,7 @@
#define MAXNAME 32
#define DEV_ENTRY __array(char, wiphy_name, 32)
-#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \
+#define DEV_ASSIGN strscpy(__entry->wiphy_name, \
wiphy_name(dev->hw->wiphy), MAXNAME)
#define DEV_PR_FMT "%s "
#define DEV_PR_ARG __entry->wiphy_name
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c
index 5adc69d5bcae..a28da5938481 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.c
+++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -485,6 +485,9 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
int rsn_ie_len = sizeof(struct element) + rsn_ie[1];
int offset = 8;
+ param->mode_802_11i = 2;
+ param->rsn_found = true;
+
/* extract RSN capabilities */
if (offset < rsn_ie_len) {
/* skip over pairwise suites */
@@ -494,11 +497,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
/* skip over authentication suites */
offset += (rsn_ie[offset] * 4) + 2;
- if (offset + 1 < rsn_ie_len) {
- param->mode_802_11i = 2;
- param->rsn_found = true;
+ if (offset + 1 < rsn_ie_len)
memcpy(param->rsn_cap, &rsn_ie[offset], 2);
- }
}
}
}
diff --git a/drivers/net/wireless/microchip/wilc1000/hif.h b/drivers/net/wireless/microchip/wilc1000/hif.h
index baa2881f4465..8e386db72e45 100644
--- a/drivers/net/wireless/microchip/wilc1000/hif.h
+++ b/drivers/net/wireless/microchip/wilc1000/hif.h
@@ -30,8 +30,6 @@ enum {
WILC_GET_CFG
};
-#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256
-
struct rf_info {
u8 link_speed;
s8 rssi;
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
index 614c5673f232..7038b74f8e8f 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
@@ -30,7 +30,7 @@ struct wilc_cfg_str {
struct wilc_cfg_str_vals {
u8 mac_address[7];
u8 firmware_version[129];
- u8 assoc_rsp[256];
+ u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
};
struct wilc_cfg {
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_if.h b/drivers/net/wireless/microchip/wilc1000/wlan_if.h
index df2f5a63bdf6..254a046e3b1b 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan_if.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan_if.h
@@ -10,6 +10,8 @@
#include <linux/netdevice.h>
#include "fw.h"
+#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 512
+
/********************************************
*
* Wlan Configuration ID
diff --git a/drivers/net/wireless/purelifi/plfxlc/Kconfig b/drivers/net/wireless/purelifi/plfxlc/Kconfig
index 4e0be27a5e0e..dd5fca480d7e 100644
--- a/drivers/net/wireless/purelifi/plfxlc/Kconfig
+++ b/drivers/net/wireless/purelifi/plfxlc/Kconfig
@@ -3,7 +3,7 @@ config PLFXLC
tristate "pureLiFi X, XL, XC device support"
depends on CFG80211 && MAC80211 && USB
help
- This option adds support for pureLiFi LiFi wireless USB
+ This option adds support for pureLiFi LiFi USB wireless
adapters. The pureLiFi X, XL, XC USB devices are based on
802.11 OFDM PHY but uses light as the transmission medium.
The driver supports common 802.11 encryption/authentication
diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig
index dcccc290a7f5..d1fd66d44a7e 100644
--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
@@ -170,7 +170,7 @@ config RT2800USB_RT35XX
config RT2800USB_RT3573
bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
help
- This enables support for RT3573 chipset based wireless USB devices
+ This enables support for RT3573 chipset based USB wireless devices
in the rt2800usb driver.
config RT2800USB_RT53XX
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
index b052c96347d6..6cf7e7c997c2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -192,7 +192,7 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
return;
/*
- * Frame was received successfully since non-succesfull
+ * Frame was received successfully since non-successful
* frames would have been dropped by the hardware.
*/
qual->rx_success++;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
index 82bcaf44a65f..44ad94757a03 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
@@ -11,7 +11,8 @@ config RTL8XXXU
parts written to utilize the Linux mac80211 stack.
The driver is known to work with a number of RTL8723AU,
RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU,
- RTL8188FU, RTL8188EU, and RTL8710BU (aka RTL8188GU) devices.
+ RTL8188FU, RTL8188EU, RTL8710BU (aka RTL8188GU), and RTL8192FU
+ devices.
This driver is under development and has a limited feature
set. In particular it does not yet support 40MHz channels
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
index 1bf083c15dcd..fa466589eccb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/Makefile
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile
@@ -3,4 +3,4 @@ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o
rtl8xxxu-y := rtl8xxxu_core.o rtl8xxxu_8192e.o rtl8xxxu_8723b.o \
rtl8xxxu_8723a.o rtl8xxxu_8192c.o rtl8xxxu_8188f.o \
- rtl8xxxu_8188e.o rtl8xxxu_8710b.o
+ rtl8xxxu_8188e.o rtl8xxxu_8710b.o rtl8xxxu_8192f.o
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index 808c1c895113..4695fb4e2d2d 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -39,6 +39,7 @@
#define TX_TOTAL_PAGE_NUM_8188E 0xa9
#define TX_TOTAL_PAGE_NUM_8192E 0xf3
#define TX_TOTAL_PAGE_NUM_8723B 0xf7
+#define TX_TOTAL_PAGE_NUM_8192F 0xf7
/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */
#define TX_PAGE_NUM_PUBQ 0xe7
#define TX_PAGE_NUM_HI_PQ 0x0c
@@ -65,6 +66,11 @@
#define TX_PAGE_NUM_LO_PQ_8723B 0x02
#define TX_PAGE_NUM_NORM_PQ_8723B 0x02
+#define TX_PAGE_NUM_PUBQ_8192F 0xde
+#define TX_PAGE_NUM_HI_PQ_8192F 0x08
+#define TX_PAGE_NUM_LO_PQ_8192F 0x08
+#define TX_PAGE_NUM_NORM_PQ_8192F 0x08
+
#define RTL_FW_PAGE_SIZE 4096
#define RTL8XXXU_FIRMWARE_POLL_MAX 1000
@@ -81,6 +87,7 @@
#define EFUSE_REAL_CONTENT_LEN_8723A 512
#define EFUSE_BT_MAP_LEN_8723A 1024
#define EFUSE_MAX_WORD_UNIT 4
+#define EFUSE_UNDEFINED 0xff
enum rtl8xxxu_rtl_chip {
RTL8192S = 0x81920,
@@ -105,6 +112,7 @@ enum rtl8xxxu_rtl_chip {
RTL8195A = 0x8195a,
RTL8188F = 0x8188f,
RTL8710B = 0x8710b,
+ RTL8192F = 0x8192f,
};
enum rtl8xxxu_rx_type {
@@ -1246,6 +1254,40 @@ struct rtl8710bu_efuse {
u8 res7[0x3c];
} __packed;
+struct rtl8192fu_efuse {
+ __le16 rtl_id;
+ u8 res0[0x0e];
+ struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */
+ struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */
+ u8 res2[0x54];
+ u8 channel_plan; /* 0xb8 */
+ u8 xtal_k; /* 0xb9 */
+ u8 thermal_meter; /* 0xba */
+ u8 iqk_lck; /* 0xbb */
+ u8 pa_type; /* 0xbc */
+ u8 lna_type_2g; /* 0xbd */
+ u8 res3[1];
+ u8 lna_type_5g; /* 0xbf */
+ u8 res4[1];
+ u8 rf_board_option; /* 0xc1 */
+ u8 rf_feature_option; /* 0xc2 */
+ u8 rf_bt_setting; /* 0xc3 */
+ u8 eeprom_version; /* 0xc4 */
+ u8 eeprom_customer_id; /* 0xc5 */
+ u8 res5[3];
+ u8 rf_antenna_option; /* 0xc9 */
+ u8 rfe_option; /* 0xca */
+ u8 country_code; /* 0xcb */
+ u8 res6[52];
+ u8 vid[2]; /* 0x100 */
+ u8 pid[2]; /* 0x102 */
+ u8 usb_optional_function; /* 0x104 */
+ u8 res7[2];
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */
+ u8 device_info[80]; /* 0x10d */
+ u8 res9[163];
+} __packed;
+
struct rtl8xxxu_reg8val {
u16 reg;
u8 val;
@@ -1280,6 +1322,9 @@ struct rtl8xxxu_rfregs {
#define H2C_JOIN_BSS_DISCONNECT 0
#define H2C_JOIN_BSS_CONNECT 1
+#define H2C_MACID_ROLE_STA 1
+#define H2C_MACID_ROLE_AP 2
+
/*
* H2C (firmware) commands differ between the older generation chips
* 8188[cr]u, 819[12]cu, and 8723au, and the more recent chips 8723bu,
@@ -1727,6 +1772,8 @@ struct rtl8xxxu_cfo_tracking {
};
#define RTL8XXXU_HW_LED_CONTROL 2
+#define RTL8XXXU_MAX_MAC_ID_NUM 128
+#define RTL8XXXU_BC_MC_MACID 0
struct rtl8xxxu_priv {
struct ieee80211_hw *hw;
@@ -1791,6 +1838,7 @@ struct rtl8xxxu_priv {
u32 cck_agc_report_type:1;
u32 cck_new_agc:1;
u8 default_crystal_cap;
+ u8 rfe_type;
unsigned int pipe_interrupt;
unsigned int pipe_in;
unsigned int pipe_out[TXDESC_QUEUE_MAX];
@@ -1831,6 +1879,7 @@ struct rtl8xxxu_priv {
struct rtl8188fu_efuse efuse8188fu;
struct rtl8188eu_efuse efuse8188eu;
struct rtl8710bu_efuse efuse8710bu;
+ struct rtl8192fu_efuse efuse8192fu;
} efuse_wifi;
u32 adda_backup[RTL8XXXU_ADDA_REGS];
u32 mac_backup[RTL8XXXU_MAC_REGS];
@@ -1851,6 +1900,7 @@ struct rtl8xxxu_priv {
struct delayed_work ra_watchdog;
struct work_struct c2hcmd_work;
struct sk_buff_head c2hcmd_queue;
+ struct work_struct update_beacon_work;
struct rtl8xxxu_btcoex bt_coex;
struct rtl8xxxu_ra_report ra_report;
struct rtl8xxxu_cfo_tracking cfo_tracking;
@@ -1859,6 +1909,14 @@ struct rtl8xxxu_priv {
bool led_registered;
char led_name[32];
struct led_classdev led_cdev;
+ DECLARE_BITMAP(mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+};
+
+struct rtl8xxxu_sta_info {
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
+
+ u8 macid;
};
struct rtl8xxxu_rx_urb {
@@ -1903,15 +1961,16 @@ struct rtl8xxxu_fileops {
void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
bool ht40);
void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid);
void (*report_connect) (struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void (*report_rssi) (struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats);
int (*led_classdev_brightness_set) (struct led_classdev *led_cdev,
@@ -1929,6 +1988,9 @@ struct rtl8xxxu_fileops {
u8 init_reg_hmtfr:1;
u8 ampdu_max_time;
u8 ustime_tsf_edca;
+ u16 max_aggr_num;
+ u8 supports_ap:1;
+ u16 max_macid_num;
u32 adda_1t_init;
u32 adda_1t_path_on;
u32 adda_2t_path_on_a;
@@ -2015,6 +2077,7 @@ void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv,
int channel, bool ht40);
+void rtl8188f_channel_to_group(int channel, int *group, int *cck_group);
void rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv,
int channel, bool ht40);
void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw);
@@ -2022,13 +2085,13 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw);
void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv);
void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid);
void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz);
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz, u8 macid);
void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect);
+ u8 macid, u8 role, bool connect);
void rtl8xxxu_gen1_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void rtl8xxxu_gen2_report_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi);
void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv);
@@ -2057,17 +2120,17 @@ void rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
bool short_preamble, bool ampdu_enable,
- u32 rts_rate);
+ u32 rts_rate, u8 macid);
void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
@@ -2079,6 +2142,7 @@ void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra);
void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
+extern struct rtl8xxxu_fileops rtl8192fu_fops;
extern struct rtl8xxxu_fileops rtl8710bu_fops;
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8188eu_fops;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
index 8986783ae8fa..6d0f975f891b 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188e.c
@@ -1794,7 +1794,8 @@ static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra)
static void
rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
index dbdfd7787465..1e1c8fa194cb 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
@@ -351,7 +351,7 @@ out:
return ret;
}
-static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
+void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
{
if (channel < 3)
*group = 0;
@@ -654,7 +654,7 @@ static void rtl8188fu_config_channel(struct ieee80211_hw *hw)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_BB2, val32);
/* RC Corner */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00140);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00140);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_G2, 0x01c6c);
}
@@ -854,8 +854,8 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7);
/* PA,PAD gain adjust */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
/* enter IQK mode */
val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
@@ -886,7 +886,7 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* save LOK result */
*lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC);
@@ -927,8 +927,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA,PAD gain adjust */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
/*
* Enter IQK mode
@@ -967,7 +967,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* Check failed */
reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
@@ -1002,8 +1002,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
/*
* PA, PAD setting
*/
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x51000);
/*
* Enter IQK mode
@@ -1041,7 +1041,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
val32 &= 0x000000ff;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
/* reload LOK value */
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result);
@@ -1748,6 +1748,9 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.init_reg_hmtfr = 1,
.ampdu_max_time = 0x70,
.ustime_tsf_edca = 0x28,
+ .max_aggr_num = 0x0c14,
+ .supports_ap = 1,
+ .max_macid_num = 16,
.adda_1t_init = 0x03c00014,
.adda_1t_path_on = 0x03c00014,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index fcc2926ea938..f673aa9ba15a 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -716,7 +716,7 @@ static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv)
* PA/PAD controlled by 0x0
*/
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00180);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000);
@@ -776,8 +776,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x511e0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x511e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -816,7 +816,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
} else {
/* PA/PAD controlled by 0x0 */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
goto out;
}
@@ -838,8 +838,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x510e0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x510e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -869,7 +869,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
if (!(reg_eac & BIT(27)) &&
((reg_ea4 & 0x03ff0000) != 0x01320000) &&
@@ -889,7 +889,7 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv)
int result = 0;
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00180);
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000);
@@ -952,8 +952,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x511e0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x511e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -995,7 +995,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
* Vendor driver restores RF_A here which I believe is a bug
*/
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
goto out;
}
@@ -1017,8 +1017,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
/* PA/PAD control by 0x56, and set = 0x0 */
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x510e0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x510e0);
/* Enter IQK mode */
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
@@ -1049,7 +1049,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
- rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
if (!(reg_eac & BIT(30)) &&
((reg_ec4 & 0x03ff0000) != 0x01320000) &&
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
new file mode 100644
index 000000000000..18dc5221a9c0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c
@@ -0,0 +1,2090 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RTL8XXXU mac80211 USB driver - 8192fu specific subdriver
+ *
+ * Copyright (c) 2023 Bitterblue Smith <rtl8821cerfe2@gmail.com>
+ *
+ * Portions copied from existing rtl8xxxu code:
+ * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
+ *
+ * Portions, notably calibration code:
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/moduleparam.h>
+#include <net/mac80211.h>
+#include "rtl8xxxu.h"
+#include "rtl8xxxu_regs.h"
+
+static const struct rtl8xxxu_reg8val rtl8192f_mac_init_table[] = {
+ {0x420, 0x00}, {0x422, 0x78}, {0x428, 0x0a}, {0x429, 0x10},
+ {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01},
+ {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x07}, {0x437, 0x08},
+ {0x43c, 0x04}, {0x43d, 0x05}, {0x43e, 0x07}, {0x43f, 0x08},
+ {0x440, 0x5d}, {0x441, 0x01}, {0x442, 0x00}, {0x444, 0x10},
+ {0x445, 0xf0}, {0x446, 0x0e}, {0x447, 0x1f}, {0x448, 0x00},
+ {0x449, 0x00}, {0x44a, 0x00}, {0x44b, 0x00}, {0x44c, 0x10},
+ {0x44d, 0xf0}, {0x44e, 0x0e}, {0x44f, 0x00}, {0x450, 0x00},
+ {0x451, 0x00}, {0x452, 0x00}, {0x453, 0x00}, {0x480, 0x20},
+ {0x49c, 0x30}, {0x49d, 0xf0}, {0x49e, 0x03}, {0x49f, 0x3e},
+ {0x4a0, 0x00}, {0x4a1, 0x00}, {0x4a2, 0x00}, {0x4a3, 0x00},
+ {0x4a4, 0x15}, {0x4a5, 0xf0}, {0x4a6, 0x01}, {0x4a7, 0x0e},
+ {0x4a8, 0xe0}, {0x4a9, 0x00}, {0x4aa, 0x00}, {0x4ab, 0x00},
+ {0x2448, 0x06}, {0x244a, 0x06}, {0x244c, 0x06}, {0x244e, 0x06},
+ {0x4c7, 0x80}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4ca, 0x3c},
+ {0x4cb, 0x3c}, {0x4cc, 0xff}, {0x4cd, 0xff}, {0x4ce, 0x01},
+ {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, {0x503, 0x00},
+ {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, {0x507, 0x00},
+ {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, {0x50b, 0x00},
+ {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, {0x50f, 0x00},
+ {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, {0x521, 0x2f},
+ {0x525, 0x0f}, {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02},
+ {0x55c, 0x50}, {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e},
+ {0x609, 0x2a}, {0x60c, 0x18}, {0x620, 0xff}, {0x621, 0xff},
+ {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, {0x625, 0xff},
+ {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, {0x63c, 0x0a},
+ {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, {0x640, 0x40},
+ {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, {0x66e, 0x05},
+ {0x6a0, 0xff}, {0x6a1, 0xff}, {0x6a2, 0xff}, {0x6a3, 0xff},
+ {0x6a4, 0xff}, {0x6a5, 0xff}, {0x6de, 0x84}, {0x700, 0x21},
+ {0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21},
+ {0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87}, {0x718, 0x40},
+ {0x7c0, 0x38}, {0x7c2, 0x0f}, {0x7c3, 0xc0}, {0x073, 0x04},
+ {0x7c4, 0x77}, {0x024, 0xc7}, {0x7ec, 0xff}, {0x7ed, 0xff},
+ {0x7ee, 0xff}, {0x7ef, 0xff},
+ {0xffff, 0xff},
+};
+
+/* If updating the phy init table, also update rtl8192f_revise_cck_tx_psf(). */
+static const struct rtl8xxxu_reg32val rtl8192fu_phy_init_table[] = {
+ {0x800, 0x80006C00}, {0x804, 0x00004001},
+ {0x808, 0x0000FC00}, {0x80C, 0x00000000},
+ {0x810, 0x20200322}, {0x814, 0x020C3910},
+ {0x818, 0x00000385}, {0x81C, 0x07000000},
+ {0x820, 0x01000100}, {0x824, 0x00390204},
+ {0x828, 0x01000100}, {0x82C, 0x00390204},
+ {0x830, 0x25252525}, {0x834, 0x25252525},
+ {0x838, 0x25252525}, {0x83C, 0x25252525},
+ {0x840, 0x00010000}, {0x844, 0x00010000},
+ {0x848, 0x25252525}, {0x84C, 0x25252525},
+ {0x850, 0x00031FE0}, {0x854, 0x00000000},
+ {0x858, 0x569A569A}, {0x85C, 0x00400040},
+ {0x860, 0x66F60000}, {0x864, 0x061F0000},
+ {0x868, 0x25252525}, {0x86C, 0x25252525},
+ {0x870, 0x00000300}, {0x874, 0x04003400},
+ {0x878, 0x08080808}, {0x87C, 0x004F0201},
+ {0x880, 0xD8001402}, {0x884, 0xC0000120},
+ {0x888, 0x00000000}, {0x88C, 0xCC0000C0},
+ {0x890, 0x00000000}, {0x894, 0xFFFFFFFE},
+ {0x898, 0x40302010}, {0x89C, 0x00706050},
+ {0x900, 0x00000000}, {0x904, 0x00000023},
+ {0x908, 0x00000F00}, {0x90C, 0x81121313},
+ {0x910, 0x024C0000}, {0x914, 0x00000000},
+ {0x918, 0x00000000}, {0x91C, 0x00000000},
+ {0x920, 0x00000000}, {0x924, 0x00000000},
+ {0x928, 0x00000000}, {0x92C, 0x00000000},
+ {0x930, 0x88000000}, {0x934, 0x00000245},
+ {0x938, 0x00024588}, {0x93C, 0x00000000},
+ {0x940, 0x000007FF}, {0x944, 0x3F3F0000},
+ {0x948, 0x000001A3}, {0x94C, 0x20200008},
+ {0x950, 0x00338A98}, {0x954, 0x00000000},
+ {0x958, 0xCBCAD87A}, {0x95C, 0x06EB5735},
+ {0x960, 0x00000000}, {0x964, 0x00000000},
+ {0x968, 0x00000000}, {0x96C, 0x00000003},
+ {0x970, 0x00000000}, {0x974, 0x00000000},
+ {0x978, 0x00000000}, {0x97C, 0x10030000},
+ {0x980, 0x00000000}, {0x984, 0x02800280},
+ {0x988, 0x020A5704}, {0x98C, 0x1461C826},
+ {0x990, 0x0001469E}, {0x994, 0x008858D1},
+ {0x998, 0x400086C9}, {0x99C, 0x44444242},
+ {0x9A0, 0x00000000}, {0x9A4, 0x00000000},
+ {0x9A8, 0x00000000}, {0x9AC, 0xC0000000},
+ {0xA00, 0x00D047C8}, {0xA04, 0xC1FF0008},
+ {0xA08, 0x88838300}, {0xA0C, 0x2E20100F},
+ {0xA10, 0x9500BB78}, {0xA14, 0x11144028},
+ {0xA18, 0x00881117}, {0xA1C, 0x89140F00},
+ {0xA20, 0xE82C0001}, {0xA24, 0x64B80C1C},
+ {0xA28, 0x00158810}, {0xA2C, 0x10BB8000},
+ {0xA70, 0x00008000}, {0xA74, 0x80800100},
+ {0xA78, 0x000089F0}, {0xA7C, 0x225B0606},
+ {0xA80, 0x20803210}, {0xA84, 0x00200200},
+ {0xA88, 0x00000000}, {0xA8C, 0x00000000},
+ {0xA90, 0x00000000}, {0xA94, 0x00000000},
+ {0xA98, 0x00000000}, {0xA9C, 0x00460000},
+ {0xAA0, 0x00000000}, {0xAA4, 0x00020014},
+ {0xAA8, 0xBA0A0008}, {0xAAC, 0x01235667},
+ {0xAB0, 0x00000000}, {0xAB4, 0x00201402},
+ {0xAB8, 0x0000001C}, {0xABC, 0x0000F7FF},
+ {0xAC0, 0xD4C0A742}, {0xAC4, 0x00000000},
+ {0xAC8, 0x00000F08}, {0xACC, 0x00000F07},
+ {0xAD0, 0xA1052A10}, {0xAD4, 0x0D9D8452},
+ {0xAD8, 0x9E024024}, {0xADC, 0x0023C001},
+ {0xAE0, 0x00000391}, {0xB2C, 0x00000000},
+ {0xC00, 0x00000080}, {0xC04, 0x6F005433},
+ {0xC08, 0x000004E4}, {0xC0C, 0x6C6C6C6C},
+ {0xC10, 0x22000000}, {0xC14, 0x40000100},
+ {0xC18, 0x22000000}, {0xC1C, 0x40000100},
+ {0xC20, 0x00000000}, {0xC24, 0x40000100},
+ {0xC28, 0x00000000}, {0xC2C, 0x40000100},
+ {0xC30, 0x0401E809}, {0xC34, 0x30000020},
+ {0xC38, 0x23808080}, {0xC3C, 0x00002F44},
+ {0xC40, 0x1CF8403F}, {0xC44, 0x000100C7},
+ {0xC48, 0xEC060106}, {0xC4C, 0x007F037F},
+ {0xC50, 0x00E48020}, {0xC54, 0x04008017},
+ {0xC58, 0x00000020}, {0xC5C, 0x00708492},
+ {0xC60, 0x09280200}, {0xC64, 0x5014838B},
+ {0xC68, 0x47C006C7}, {0xC6C, 0x00000035},
+ {0xC70, 0x00001007}, {0xC74, 0x02815269},
+ {0xC78, 0x0FE07F1F}, {0xC7C, 0x00B91612},
+ {0xC80, 0x40000100}, {0xC84, 0x32000000},
+ {0xC88, 0x40000100}, {0xC8C, 0xA0240000},
+ {0xC90, 0x400E161E}, {0xC94, 0x00000F00},
+ {0xC98, 0x400E161E}, {0xC9C, 0x0000BDC8},
+ {0xCA0, 0x00000000}, {0xCA4, 0x098300A0},
+ {0xCA8, 0x00006B00}, {0xCAC, 0x87F45B1A},
+ {0xCB0, 0x0000002D}, {0xCB4, 0x00000000},
+ {0xCB8, 0x00000000}, {0xCBC, 0x28100200},
+ {0xCC0, 0x0010A3D0}, {0xCC4, 0x00000F7D},
+ {0xCC8, 0x00000000}, {0xCCC, 0x00000000},
+ {0xCD0, 0x593659AD}, {0xCD4, 0xB7545121},
+ {0xCD8, 0x64B22427}, {0xCDC, 0x00766932},
+ {0xCE0, 0x40201000}, {0xCE4, 0x00000000},
+ {0xCE8, 0x40E04407}, {0xCEC, 0x2E572000},
+ {0xD00, 0x000D8780}, {0xD04, 0x40020403},
+ {0xD08, 0x0002907F}, {0xD0C, 0x20010201},
+ {0xD10, 0x06288888}, {0xD14, 0x8888367B},
+ {0xD18, 0x7D806DB3}, {0xD1C, 0x0000007F},
+ {0xD20, 0x567600B8}, {0xD24, 0x0000018B},
+ {0xD28, 0xD513FF7D}, {0xD2C, 0xCC979975},
+ {0xD30, 0x04928000}, {0xD34, 0x40608000},
+ {0xD38, 0x88DDA000}, {0xD3C, 0x00026EE2},
+ {0xD50, 0x67270001}, {0xD54, 0x20500000},
+ {0xD58, 0x16161616}, {0xD5C, 0x71F20064},
+ {0xD60, 0x4653DA60}, {0xD64, 0x3E718A3C},
+ {0xD68, 0x00000183}, {0xD7C, 0x00000000},
+ {0xD80, 0x50000000}, {0xD84, 0x31310400},
+ {0xD88, 0xF5B50000}, {0xD8C, 0x00000000},
+ {0xD90, 0x00000000}, {0xD94, 0x44BBBB44},
+ {0xD98, 0x44BB44FF}, {0xD9C, 0x06033688},
+ {0xE00, 0x25252525}, {0xE04, 0x25252525},
+ {0xE08, 0x25252525}, {0xE10, 0x25252525},
+ {0xE14, 0x25252525}, {0xE18, 0x25252525},
+ {0xE1C, 0x25252525}, {0xE20, 0x00000000},
+ {0xE24, 0x00200000}, {0xE28, 0x00000000},
+ {0xE2C, 0x00000000}, {0xE30, 0x01007C00},
+ {0xE34, 0x01004800}, {0xE38, 0x10008C0F},
+ {0xE3C, 0x3C008C0F}, {0xE40, 0x01007C00},
+ {0xE44, 0x00000000}, {0xE48, 0x00000000},
+ {0xE4C, 0x00000000}, {0xE50, 0x01007C00},
+ {0xE54, 0x01004800}, {0xE58, 0x10008C0F},
+ {0xE5C, 0x3C008C0F}, {0xE60, 0x02100000},
+ {0xE64, 0xBBBBBBBB}, {0xE68, 0x40404040},
+ {0xE6C, 0x80408040}, {0xE70, 0x80408040},
+ {0xE74, 0x40404040}, {0xE78, 0x00400040},
+ {0xE7C, 0x40404040}, {0xE80, 0x00FF0000},
+ {0xE84, 0x80408040}, {0xE88, 0x40404040},
+ {0xE8C, 0x80408040}, {0xED0, 0x80408040},
+ {0xED4, 0x80408040}, {0xED8, 0x80408040},
+ {0xEDC, 0xC040C040}, {0xEE0, 0xC040C040},
+ {0xEE4, 0x00400040}, {0xEE8, 0xD8001402},
+ {0xEEC, 0xC0000120}, {0xEF0, 0x02000B09},
+ {0xEF4, 0x00000001}, {0xEF8, 0x00000000},
+ {0xF00, 0x00000300}, {0xF04, 0x00000002},
+ {0xF08, 0x00007D0C}, {0xF0C, 0x0000A907},
+ {0xF10, 0x00005807}, {0xF14, 0x00000003},
+ {0xF18, 0x07D003E8}, {0xF1C, 0x8000001F},
+ {0xF20, 0x00000000}, {0xF24, 0x00000000},
+ {0xF28, 0x00000000}, {0xF2C, 0x00000000},
+ {0xF30, 0x00000000}, {0xF34, 0x00000000},
+ {0xF38, 0x00030055}, {0xF3C, 0x0000003A},
+ {0xF40, 0x00000002}, {0xF44, 0x00000000},
+ {0xF48, 0x00000000}, {0xF4C, 0x0B000000},
+ {0xF50, 0x00000000},
+ {0xffff, 0xffffffff},
+};
+
+static const struct rtl8xxxu_reg32val rtl8192f_agc_table[] = {
+ {0xC78, 0x0FA0001F}, {0xC78, 0x0FA0011F},
+ {0xC78, 0x0FA0021F}, {0xC78, 0x0FA0031F},
+ {0xC78, 0x0FA0041F}, {0xC78, 0x0FA0051F},
+ {0xC78, 0x0F90061F}, {0xC78, 0x0F80071F},
+ {0xC78, 0x0F70081F}, {0xC78, 0x0F60091F},
+ {0xC78, 0x0F500A1F}, {0xC78, 0x0F400B1F},
+ {0xC78, 0x0F300C1F}, {0xC78, 0x0F200D1F},
+ {0xC78, 0x0F100E1F}, {0xC78, 0x0F000F1F},
+ {0xC78, 0x0EF0101F}, {0xC78, 0x0EE0111F},
+ {0xC78, 0x0ED0121F}, {0xC78, 0x0EC0131F},
+ {0xC78, 0x0EB0141F}, {0xC78, 0x0EA0151F},
+ {0xC78, 0x0E90161F}, {0xC78, 0x0E80171F},
+ {0xC78, 0x0E70181F}, {0xC78, 0x0E60191F},
+ {0xC78, 0x0E501A1F}, {0xC78, 0x0E401B1F},
+ {0xC78, 0x0E301C1F}, {0xC78, 0x0C701D1F},
+ {0xC78, 0x0C601E1F}, {0xC78, 0x0C501F1F},
+ {0xC78, 0x0C40201F}, {0xC78, 0x0C30211F},
+ {0xC78, 0x0A60221F}, {0xC78, 0x0A50231F},
+ {0xC78, 0x0A40241F}, {0xC78, 0x0A30251F},
+ {0xC78, 0x0860261F}, {0xC78, 0x0850271F},
+ {0xC78, 0x0840281F}, {0xC78, 0x0830291F},
+ {0xC78, 0x06702A1F}, {0xC78, 0x06602B1F},
+ {0xC78, 0x06502C1F}, {0xC78, 0x06402D1F},
+ {0xC78, 0x06302E1F}, {0xC78, 0x04602F1F},
+ {0xC78, 0x0450301F}, {0xC78, 0x0440311F},
+ {0xC78, 0x0430321F}, {0xC78, 0x0260331F},
+ {0xC78, 0x0250341F}, {0xC78, 0x0240351F},
+ {0xC78, 0x0230361F}, {0xC78, 0x0050371F},
+ {0xC78, 0x0040381F}, {0xC78, 0x0030391F},
+ {0xC78, 0x00203A1F}, {0xC78, 0x00103B1F},
+ {0xC78, 0x00003C1F}, {0xC78, 0x00003D1F},
+ {0xC78, 0x00003E1F}, {0xC78, 0x00003F1F},
+
+ {0xC78, 0x0FA0401F}, {0xC78, 0x0FA0411F},
+ {0xC78, 0x0FA0421F}, {0xC78, 0x0FA0431F},
+ {0xC78, 0x0F90441F}, {0xC78, 0x0F80451F},
+ {0xC78, 0x0F70461F}, {0xC78, 0x0F60471F},
+ {0xC78, 0x0F50481F}, {0xC78, 0x0F40491F},
+ {0xC78, 0x0F304A1F}, {0xC78, 0x0F204B1F},
+ {0xC78, 0x0F104C1F}, {0xC78, 0x0F004D1F},
+ {0xC78, 0x0EF04E1F}, {0xC78, 0x0EE04F1F},
+ {0xC78, 0x0ED0501F}, {0xC78, 0x0EC0511F},
+ {0xC78, 0x0EB0521F}, {0xC78, 0x0EA0531F},
+ {0xC78, 0x0E90541F}, {0xC78, 0x0E80551F},
+ {0xC78, 0x0E70561F}, {0xC78, 0x0E60571F},
+ {0xC78, 0x0E50581F}, {0xC78, 0x0E40591F},
+ {0xC78, 0x0E305A1F}, {0xC78, 0x0E205B1F},
+ {0xC78, 0x0E105C1F}, {0xC78, 0x0C505D1F},
+ {0xC78, 0x0C405E1F}, {0xC78, 0x0C305F1F},
+ {0xC78, 0x0C20601F}, {0xC78, 0x0C10611F},
+ {0xC78, 0x0A40621F}, {0xC78, 0x0A30631F},
+ {0xC78, 0x0A20641F}, {0xC78, 0x0A10651F},
+ {0xC78, 0x0840661F}, {0xC78, 0x0830671F},
+ {0xC78, 0x0820681F}, {0xC78, 0x0810691F},
+ {0xC78, 0x06506A1F}, {0xC78, 0x06406B1F},
+ {0xC78, 0x06306C1F}, {0xC78, 0x06206D1F},
+ {0xC78, 0x06106E1F}, {0xC78, 0x04406F1F},
+ {0xC78, 0x0430701F}, {0xC78, 0x0420711F},
+ {0xC78, 0x0410721F}, {0xC78, 0x0240731F},
+ {0xC78, 0x0230741F}, {0xC78, 0x0220751F},
+ {0xC78, 0x0210761F}, {0xC78, 0x0030771F},
+ {0xC78, 0x0020781F}, {0xC78, 0x0010791F},
+ {0xC78, 0x00007A1F}, {0xC78, 0x00007B1F},
+ {0xC78, 0x00007C1F}, {0xC78, 0x00007D1F},
+ {0xC78, 0x00007E1F}, {0xC78, 0x00007F1F},
+
+ {0xC78, 0x0FA0801F}, {0xC78, 0x0FA0811F},
+ {0xC78, 0x0FA0821F}, {0xC78, 0x0FA0831F},
+ {0xC78, 0x0FA0841F}, {0xC78, 0x0FA0851F},
+ {0xC78, 0x0F90861F}, {0xC78, 0x0F80871F},
+ {0xC78, 0x0F70881F}, {0xC78, 0x0F60891F},
+ {0xC78, 0x0F508A1F}, {0xC78, 0x0F408B1F},
+ {0xC78, 0x0F308C1F}, {0xC78, 0x0F208D1F},
+ {0xC78, 0x0F108E1F}, {0xC78, 0x0B908F1F},
+ {0xC78, 0x0B80901F}, {0xC78, 0x0B70911F},
+ {0xC78, 0x0B60921F}, {0xC78, 0x0B50931F},
+ {0xC78, 0x0B40941F}, {0xC78, 0x0B30951F},
+ {0xC78, 0x0B20961F}, {0xC78, 0x0B10971F},
+ {0xC78, 0x0B00981F}, {0xC78, 0x0AF0991F},
+ {0xC78, 0x0AE09A1F}, {0xC78, 0x0AD09B1F},
+ {0xC78, 0x0AC09C1F}, {0xC78, 0x0AB09D1F},
+ {0xC78, 0x0AA09E1F}, {0xC78, 0x0A909F1F},
+ {0xC78, 0x0A80A01F}, {0xC78, 0x0A70A11F},
+ {0xC78, 0x0A60A21F}, {0xC78, 0x0A50A31F},
+ {0xC78, 0x0A40A41F}, {0xC78, 0x0A30A51F},
+ {0xC78, 0x0A20A61F}, {0xC78, 0x0A10A71F},
+ {0xC78, 0x0A00A81F}, {0xC78, 0x0830A91F},
+ {0xC78, 0x0820AA1F}, {0xC78, 0x0810AB1F},
+ {0xC78, 0x0800AC1F}, {0xC78, 0x0640AD1F},
+ {0xC78, 0x0630AE1F}, {0xC78, 0x0620AF1F},
+ {0xC78, 0x0610B01F}, {0xC78, 0x0600B11F},
+ {0xC78, 0x0430B21F}, {0xC78, 0x0420B31F},
+ {0xC78, 0x0410B41F}, {0xC78, 0x0400B51F},
+ {0xC78, 0x0230B61F}, {0xC78, 0x0220B71F},
+ {0xC78, 0x0210B81F}, {0xC78, 0x0200B91F},
+ {0xC78, 0x0000BA1F}, {0xC78, 0x0000BB1F},
+ {0xC78, 0x0000BC1F}, {0xC78, 0x0000BD1F},
+ {0xC78, 0x0000BE1F}, {0xC78, 0x0000BF1F},
+ {0xC50, 0x00E48024}, {0xC50, 0x00E48020},
+ {0xffff, 0xffffffff}
+};
+
+static const struct rtl8xxxu_rfregval rtl8192fu_radioa_init_table[] = {
+ {0x00, 0x30000}, {0x18, 0x0FC07}, {0x81, 0x0FC00}, {0x82, 0x003C0},
+ {0x84, 0x00005}, {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010},
+ {0x8E, 0x64540}, {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007},
+ {0x53, 0x10061}, {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6},
+ {0x57, 0x2CC00}, {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006},
+ {0x5C, 0x00015}, {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180},
+ {0xEF, 0x00002}, {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A},
+ {0xEF, 0x00000}, {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008},
+ {0xEF, 0x00800}, {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848},
+ {0x33, 0x0C84B}, {0x33, 0x1088A}, {0x33, 0x14C50}, {0x33, 0x18C8E},
+ {0x33, 0x1CCCD}, {0x33, 0x20CD0}, {0x33, 0x24CD3}, {0x33, 0x28CD6},
+ {0x33, 0x4002B}, {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849},
+ {0x33, 0x50888}, {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC},
+ {0x33, 0x60CCF}, {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000},
+ {0xEF, 0x00400}, {0x33, 0x01C23}, {0x33, 0x05C23}, {0x33, 0x09D23},
+ {0x33, 0x0DD23}, {0x33, 0x11FA3}, {0x33, 0x15FA3}, {0x33, 0x19FAB},
+ {0x33, 0x1DFAB}, {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030},
+ {0x33, 0x04030}, {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030},
+ {0x33, 0x14030}, {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030},
+ {0x33, 0x24030}, {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030},
+ {0x33, 0x34030}, {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000},
+ {0xEF, 0x00100}, {0x33, 0x44001}, {0x33, 0x48001}, {0x33, 0x4C001},
+ {0x33, 0x50001}, {0x33, 0x54001}, {0x33, 0x58001}, {0x33, 0x5C001},
+ {0x33, 0x60001}, {0x33, 0x64001}, {0x33, 0x68001}, {0x33, 0x6C001},
+ {0x33, 0x70001}, {0x33, 0x74001}, {0x33, 0x78001}, {0x33, 0x04000},
+ {0x33, 0x08000}, {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000},
+ {0x33, 0x18001}, {0x33, 0x1C002}, {0x33, 0x20002}, {0x33, 0x24002},
+ {0x33, 0x28002}, {0x33, 0x2C002}, {0x33, 0x30002}, {0x33, 0x34002},
+ {0x33, 0x38002}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010},
+ {0x30, 0x20000}, {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000},
+ {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F},
+ {0x32, 0xF1DF3}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000},
+ {0x30, 0x38000}, {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000},
+ {0x1B, 0x746CE}, {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000},
+ {0x33, 0x70000}, {0x33, 0x78000}, {0xEF, 0x00000}, {0xDF, 0x08000},
+ {0xB0, 0xFFBCB}, {0xB3, 0x06000}, {0xB7, 0x18DF0}, {0xB8, 0x38FF0},
+ {0xC9, 0x00600}, {0xDF, 0x00000}, {0xB1, 0x33B8F}, {0xB2, 0x33762},
+ {0xB4, 0x141F0}, {0xB5, 0x14080}, {0xB6, 0x12425}, {0xB9, 0xC0008},
+ {0xBA, 0x40005}, {0xC2, 0x02C01}, {0xC3, 0x0000B}, {0xC4, 0x81E2F},
+ {0xC5, 0x5C28F}, {0xC6, 0x000A0}, {0xCA, 0x02000}, {0xFE, 0x00000},
+ {0x18, 0x08C07}, {0xFE, 0x00000}, {0xFE, 0x00000}, {0xFE, 0x00000},
+ {0x00, 0x31DD5},
+ {0xff, 0xffffffff}
+};
+
+static const struct rtl8xxxu_rfregval rtl8192fu_radiob_init_table[] = {
+ {0x00, 0x30000}, {0x81, 0x0FC00}, {0x82, 0x003C0}, {0x84, 0x00005},
+ {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, {0x8E, 0x64540},
+ {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, {0x53, 0x10061},
+ {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, {0x57, 0x2CC00},
+ {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, {0x5C, 0x00015},
+ {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, {0xEF, 0x00002},
+ {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, {0xEF, 0x00000},
+ {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, {0xEF, 0x00800},
+ {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, {0x33, 0x0C84B},
+ {0x33, 0x1088A}, {0x33, 0x14CC8}, {0x33, 0x18CCB}, {0x33, 0x1CCCE},
+ {0x33, 0x20CD1}, {0x33, 0x24CD4}, {0x33, 0x28CD7}, {0x33, 0x4002B},
+ {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, {0x33, 0x50888},
+ {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, {0x33, 0x60CCF},
+ {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, {0xEF, 0x00400},
+ {0x33, 0x01D23}, {0x33, 0x05D23}, {0x33, 0x09FA3}, {0x33, 0x0DFA3},
+ {0x33, 0x11D2B}, {0x33, 0x15D2B}, {0x33, 0x19FAB}, {0x33, 0x1DFAB},
+ {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, {0x33, 0x04030},
+ {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, {0x33, 0x14030},
+ {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, {0x33, 0x24030},
+ {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, {0x33, 0x34030},
+ {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, {0xEF, 0x00100},
+ {0x33, 0x44000}, {0x33, 0x48000}, {0x33, 0x4C000}, {0x33, 0x50000},
+ {0x33, 0x54000}, {0x33, 0x58000}, {0x33, 0x5C000}, {0x33, 0x60000},
+ {0x33, 0x64000}, {0x33, 0x68000}, {0x33, 0x6C000}, {0x33, 0x70000},
+ {0x33, 0x74000}, {0x33, 0x78000}, {0x33, 0x04000}, {0x33, 0x08000},
+ {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, {0x33, 0x18000},
+ {0x33, 0x1C001}, {0x33, 0x20001}, {0x33, 0x24001}, {0x33, 0x28001},
+ {0x33, 0x2C001}, {0x33, 0x30001}, {0x33, 0x34001}, {0x33, 0x38001},
+ {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, {0x30, 0x20000},
+ {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, {0x84, 0x00000},
+ {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, {0x32, 0xF1DF3},
+ {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x38000},
+ {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, {0x1B, 0x746CE},
+ {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, {0x33, 0x70000},
+ {0x33, 0x78000}, {0xEF, 0x00000}, {0x00, 0x31DD5},
+ {0xff, 0xffffffff}
+};
+
+static int rtl8192fu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 sys_cfg, vendor, val32;
+
+ strscpy(priv->chip_name, "8192FU", sizeof(priv->chip_name));
+ priv->rtl_chip = RTL8192F;
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ priv->tx_paths = 2;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ return -EOPNOTSUPP;
+ }
+
+ val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
+ priv->has_wifi = u32_get_bits(val32, MULTI_WIFI_FUNC_EN);
+ priv->has_bluetooth = u32_get_bits(val32, MULTI_BT_FUNC_EN);
+ priv->has_gps = u32_get_bits(val32, MULTI_GPS_FUNC_EN);
+ priv->is_multi_func = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_ID;
+ rtl8xxxu_identify_vendor_1bit(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ return rtl8xxxu_config_endpoints_no_sie(priv);
+}
+
+static void
+rtl8192f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
+{
+ u8 cck, ofdmbase, mcsbase;
+ u32 val32, ofdm, mcs;
+ int group, cck_group;
+
+ rtl8188f_channel_to_group(channel, &group, &cck_group);
+
+ cck = priv->cck_tx_power_index_A[cck_group];
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_CCK1_MCS32, 0x00007f00, cck);
+
+ val32 = (cck << 16) | (cck << 8) | cck;
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11,
+ 0x7f7f7f00, val32);
+
+ ofdmbase = priv->ht40_1s_tx_power_index_A[group];
+ ofdmbase += priv->ofdm_tx_power_diff[RF_A].a;
+ ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE18_06, 0x7f7f7f7f, ofdm);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE54_24, 0x7f7f7f7f, ofdm);
+
+ mcsbase = priv->ht40_1s_tx_power_index_A[group];
+ if (ht40)
+ mcsbase += priv->ht40_tx_power_diff[RF_A].a;
+ else
+ mcsbase += priv->ht20_tx_power_diff[RF_A].a;
+ mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS03_MCS00, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS07_MCS04, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS11_MCS08, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS15_MCS12, 0x7f7f7f7f, mcs);
+
+ if (priv->tx_paths == 1)
+ return;
+
+ cck = priv->cck_tx_power_index_B[cck_group];
+
+ val32 = (cck << 16) | (cck << 8) | cck;
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK1_55_MCS32,
+ 0x7f7f7f00, val32);
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11,
+ 0x0000007f, cck);
+
+ ofdmbase = priv->ht40_1s_tx_power_index_B[group];
+ ofdmbase += priv->ofdm_tx_power_diff[RF_B].b;
+ ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE18_06, 0x7f7f7f7f, ofdm);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE54_24, 0x7f7f7f7f, ofdm);
+
+ mcsbase = priv->ht40_1s_tx_power_index_B[group];
+ if (ht40)
+ mcsbase += priv->ht40_tx_power_diff[RF_B].b;
+ else
+ mcsbase += priv->ht20_tx_power_diff[RF_B].b;
+ mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
+
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS03_MCS00, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS07_MCS04, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS11_MCS08, 0x7f7f7f7f, mcs);
+ rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS15_MCS12, 0x7f7f7f7f, mcs);
+}
+
+static void rtl8192f_revise_cck_tx_psf(struct rtl8xxxu_priv *priv, u8 channel)
+{
+ if (channel == 13) {
+ /* Special value for channel 13 */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xf8fe0001);
+ /* Normal values */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667);
+ } else if (channel == 14) {
+ /* Normal value */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001);
+ /* Special values for channel 14 */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x0000B81C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x0000);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x00003667);
+ } else {
+ /* Restore normal values from the phy init table */
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C);
+ rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810);
+ rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667);
+ }
+}
+
+static void rtl8192fu_config_kfree(struct rtl8xxxu_priv *priv, u8 channel)
+{
+ u8 bb_gain[3] = { EFUSE_UNDEFINED, EFUSE_UNDEFINED, EFUSE_UNDEFINED };
+ u8 bb_gain_path_mask[2] = { 0x0f, 0xf0 };
+ enum rtl8xxxu_rfpath rfpath;
+ u8 bb_gain_for_path;
+ u8 channel_idx = 0;
+
+ if (channel >= 1 && channel <= 3)
+ channel_idx = 0;
+ if (channel >= 4 && channel <= 9)
+ channel_idx = 1;
+ if (channel >= 10 && channel <= 14)
+ channel_idx = 2;
+
+ rtl8xxxu_read_efuse8(priv, 0x1ee, &bb_gain[1]);
+ rtl8xxxu_read_efuse8(priv, 0x1ec, &bb_gain[0]);
+ rtl8xxxu_read_efuse8(priv, 0x1ea, &bb_gain[2]);
+
+ if (bb_gain[1] == EFUSE_UNDEFINED)
+ return;
+
+ if (bb_gain[0] == EFUSE_UNDEFINED)
+ bb_gain[0] = bb_gain[1];
+
+ if (bb_gain[2] == EFUSE_UNDEFINED)
+ bb_gain[2] = bb_gain[1];
+
+ for (rfpath = RF_A; rfpath < priv->rf_paths; rfpath++) {
+ /* power_trim based on 55[19:14] */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_55,
+ BIT(5), 1);
+
+ /* enable 55[14] for 0.5db step */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CTRL,
+ BIT(18), 1);
+
+ /* enter power_trim debug mode */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA,
+ BIT(7), 1);
+
+ /* write enable */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 1);
+
+ bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]);
+ bb_gain_for_path >>= __ffs(bb_gain_path_mask[rfpath]);
+
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x70000, channel_idx * 2);
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x3f, bb_gain_for_path);
+
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x70000, channel_idx * 2 + 1);
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3,
+ 0x3f, bb_gain_for_path);
+
+ /* leave power_trim debug mode */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA,
+ BIT(7), 0);
+
+ /* write disable */
+ rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 0);
+ }
+}
+
+static void rtl8192fu_config_channel(struct ieee80211_hw *hw)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ bool ht40 = conf_is_ht40(&hw->conf);
+ u8 channel, subchannel = 0;
+ bool sec_ch_above = 0;
+ u32 val32;
+
+ channel = (u8)hw->conf.chandef.chan->hw_value;
+
+ if (conf_is_ht40_plus(&hw->conf)) {
+ sec_ch_above = 1;
+ channel += 2;
+ subchannel = 2;
+ } else if (conf_is_ht40_minus(&hw->conf)) {
+ sec_ch_above = 0;
+ channel -= 2;
+ subchannel = 1;
+ }
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
+
+ rtl8192f_revise_cck_tx_psf(priv, channel);
+
+ /* Set channel */
+ val32 &= ~(BIT(18) | BIT(17)); /* select the 2.4G band(?) */
+ u32p_replace_bits(&val32, channel, 0xff);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
+ if (priv->rf_paths > 1)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32);
+
+ rtl8192fu_config_kfree(priv, channel);
+
+ rtl8xxxu_write8(priv, REG_DATA_SUBCHANNEL, subchannel);
+
+ /* small BW */
+ rtl8xxxu_write32_clear(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, GENMASK(31, 30));
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE, ht40);
+ rtl8xxxu_write32_mask(priv, REG_FPGA1_RF_MODE, FPGA_RF_MODE, ht40);
+
+ /* ADC clock = 160M */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, GENMASK(10, 8), 4);
+
+ /* DAC clock = 80M */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, BIT(13) | BIT(12), 2);
+
+ /* ADC buffer clk */
+ rtl8xxxu_write32_mask(priv, REG_ANTDIV_PARA1, BIT(27) | BIT(26), 2);
+
+ if (ht40)
+ /* Set Control channel to upper or lower. */
+ rtl8xxxu_write32_mask(priv, REG_CCK0_SYSTEM,
+ CCK0_SIDEBAND, !sec_ch_above);
+
+ /* Enable CCK */
+ rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_CCK);
+
+ /* RF TRX_BW */
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
+ val32 &= ~MODE_AG_BW_MASK;
+ if (ht40)
+ val32 |= MODE_AG_BW_40MHZ_8723B;
+ else
+ val32 |= MODE_AG_BW_20MHZ_8723B;
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
+ if (priv->rf_paths > 1)
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32);
+
+ /* Modify RX DFIR parameters */
+ rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, BIT(21) | BIT(20), 2);
+
+ rtl8xxxu_write32_mask(priv, REG_DOWNSAM_FACTOR, BIT(29) | BIT(28), 2);
+
+ if (ht40)
+ val32 = 0x3;
+ else
+ val32 = 0x1a3;
+ rtl8xxxu_write32_mask(priv, REG_RX_DFIR_MOD_97F, 0x1ff, val32);
+}
+
+static void rtl8192fu_init_aggregation(struct rtl8xxxu_priv *priv)
+{
+ u32 agg_rx;
+ u8 agg_ctrl;
+
+ /* RX aggregation */
+ agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL);
+ agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN;
+
+ agg_rx = rtl8xxxu_read32(priv, REG_RXDMA_AGG_PG_TH);
+ agg_rx &= ~RXDMA_USB_AGG_ENABLE;
+ agg_rx &= ~0xFF0F; /* reset agg size and timeout */
+
+ rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl);
+ rtl8xxxu_write32(priv, REG_RXDMA_AGG_PG_TH, agg_rx);
+}
+
+static int rtl8192fu_parse_efuse(struct rtl8xxxu_priv *priv)
+{
+ struct rtl8192fu_efuse *efuse = &priv->efuse_wifi.efuse8192fu;
+ int i;
+
+ if (efuse->rtl_id != cpu_to_le16(0x8129))
+ return -EINVAL;
+
+ ether_addr_copy(priv->mac_addr, efuse->mac_addr);
+
+ memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base,
+ sizeof(efuse->tx_power_index_A.cck_base));
+ memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base,
+ sizeof(efuse->tx_power_index_B.cck_base));
+
+ memcpy(priv->ht40_1s_tx_power_index_A,
+ efuse->tx_power_index_A.ht40_base,
+ sizeof(efuse->tx_power_index_A.ht40_base));
+ memcpy(priv->ht40_1s_tx_power_index_B,
+ efuse->tx_power_index_B.ht40_base,
+ sizeof(efuse->tx_power_index_B.ht40_base));
+
+ priv->ht20_tx_power_diff[0].a =
+ efuse->tx_power_index_A.ht20_ofdm_1s_diff.b;
+ priv->ht20_tx_power_diff[0].b =
+ efuse->tx_power_index_B.ht20_ofdm_1s_diff.b;
+
+ priv->ht40_tx_power_diff[0].a = 0;
+ priv->ht40_tx_power_diff[0].b = 0;
+
+ for (i = 1; i < RTL8723B_TX_COUNT; i++) {
+ priv->ofdm_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ofdm;
+ priv->ofdm_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ofdm;
+
+ priv->ht20_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ht20;
+ priv->ht20_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ht20;
+
+ priv->ht40_tx_power_diff[i].a =
+ efuse->tx_power_index_A.pwr_diff[i - 1].ht40;
+ priv->ht40_tx_power_diff[i].b =
+ efuse->tx_power_index_B.pwr_diff[i - 1].ht40;
+ }
+
+ priv->default_crystal_cap = efuse->xtal_k & 0x3f;
+
+ priv->rfe_type = efuse->rfe_option & 0x1f;
+
+ if (priv->rfe_type != 5 && priv->rfe_type != 1)
+ dev_warn(&priv->udev->dev,
+ "%s: RFE type %d was not tested. Please send an email to linux-wireless@vger.kernel.org about this.\n",
+ __func__, priv->rfe_type);
+
+ return 0;
+}
+
+static int rtl8192fu_load_firmware(struct rtl8xxxu_priv *priv)
+{
+ return rtl8xxxu_load_firmware(priv, "rtlwifi/rtl8192fufw.bin");
+}
+
+static void rtl8192fu_init_phy_bb(struct rtl8xxxu_priv *priv)
+{
+ /* Enable BB and RF */
+ rtl8xxxu_write16_set(priv, REG_SYS_FUNC,
+ SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN);
+
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
+
+ /* To Fix MAC loopback mode fail. */
+ rtl8xxxu_write8(priv, REG_LDOHCI12_CTRL, 0xf);
+ rtl8xxxu_write8(priv, REG_SYS_SWR_CTRL2 + 1, 0xe9);
+
+ rtl8xxxu_init_phy_regs(priv, rtl8192fu_phy_init_table);
+
+ rtl8xxxu_init_phy_regs(priv, rtl8192f_agc_table);
+}
+
+static int rtl8192fu_init_phy_rf(struct rtl8xxxu_priv *priv)
+{
+ int ret;
+
+ ret = rtl8xxxu_init_phy_rf(priv, rtl8192fu_radioa_init_table, RF_A);
+ if (ret)
+ return ret;
+
+ return rtl8xxxu_init_phy_rf(priv, rtl8192fu_radiob_init_table, RF_B);
+}
+
+static void rtl8192f_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
+{
+ u32 backup_mask = BIT(31) | BIT(30);
+ u32 backup;
+ u32 val32;
+
+ /* Aries's NarrowBand */
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
+ backup = u32_get_bits(val32, backup_mask);
+
+ u32p_replace_bits(&val32, 0, backup_mask);
+ rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
+
+ rtl8188f_phy_lc_calibrate(priv);
+
+ /* Aries's NarrowBand */
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
+ u32p_replace_bits(&val32, backup, backup_mask);
+ rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
+
+ /* reset OFDM state */
+ rtl8xxxu_write32_clear(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM);
+ rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM);
+}
+
+static int rtl8192fu_iqk_path_a(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_e94, reg_e9c, val32;
+ u32 rf_0x58_i, rf_0x58_q;
+ u8 rfe = priv->rfe_type;
+ int result = 0;
+ int ktime, i;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(4), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12)
+ val32 = 0x30;
+ else
+ val32 = 0xe9;
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, val32);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214000f);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28140000);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+
+ /* reload 0xdf and CCK_IND off */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 1);
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXMOD);
+ rf_0x58_i = u32_get_bits(val32, 0xfc000);
+ rf_0x58_q = u32_get_bits(val32, 0x003f0);
+
+ for (i = 0; i < 8; i++) {
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x1c000, i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x00fc0, rf_0x58_i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3,
+ 0x0003f, rf_0x58_q);
+ }
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, BIT(14), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00810, 0);
+
+ if (!(reg_eac & BIT(28)) &&
+ ((reg_e94 & 0x03ff0000) != 0x01420000) &&
+ ((reg_e9c & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+
+ return result;
+}
+
+static int rtl8192fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32;
+ int result = 0;
+ int ktime;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ /* PA/PAD control by 0x56, and set = 0x0 */
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x27);
+
+ /* Enter IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160027);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
+
+ /* Tx IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+
+ if (!(reg_eac & BIT(28)) &&
+ ((reg_e94 & 0x03ff0000) != 0x01420000) &&
+ ((reg_e9c & 0x03ff0000) != 0x00420000)) {
+ result |= 0x01;
+ } else { /* If TX not OK, ignore RX */
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA,
+ BIT(11), 0);
+
+ return result;
+ }
+
+ val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) | ((reg_e9c & 0x3ff0000) >> 16);
+ rtl8xxxu_write32(priv, REG_TX_IQK, val32);
+
+ /* Modify RX IQK mode table */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ /* PA/PAD control by 0x56, and set = 0x0 */
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ /* Enter IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-A IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82170000);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28170000);
+
+ /* RX IQK setting */
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a8d1);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXA) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 0);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0x02000);
+
+ if (!(reg_eac & BIT(27)) &&
+ ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
+ ((reg_eac & 0x03ff0000) != 0x00360000))
+ result |= 0x02;
+
+ return result;
+}
+
+static int rtl8192fu_iqk_path_b(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, val32;
+ u32 rf_0x58_i, rf_0x58_q;
+ u8 rfe = priv->rfe_type;
+ int result = 0;
+ int ktime, i;
+
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(4), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12)
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG,
+ 0x003ff, 0x30);
+ else
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG,
+ 0x00fff, 0xe9);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* Path B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8214000F);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28140000);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911);
+
+ /* One shot, path B LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+
+ /* reload 0xdf and CCK_IND off */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 1);
+
+ val32 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_TXMOD);
+ rf_0x58_i = u32_get_bits(val32, 0xfc000);
+ rf_0x58_q = u32_get_bits(val32, 0x003f0);
+
+ for (i = 0; i < 8; i++) {
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x1c000, i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x00fc0, rf_0x58_i);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3,
+ 0x0003f, rf_0x58_q);
+ }
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_AC, BIT(14), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00810, 0);
+
+ if (!(reg_eac & BIT(31)) &&
+ ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
+ ((reg_ebc & 0x03ff0000) != 0x00420000))
+ result |= 0x01;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n",
+ __func__);
+
+ return result;
+}
+
+static int rtl8192fu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
+{
+ u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32;
+ int result = 0;
+ int ktime;
+
+ /* Leave IQK mode */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x67);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* path-B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160027);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160000);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ /* Check failed */
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+
+ if (!(reg_eac & BIT(31)) &&
+ ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
+ ((reg_ebc & 0x03ff0000) != 0x00420000)) {
+ result |= 0x01;
+ } else {
+ /* PA/PAD controlled by 0x0 */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA,
+ BIT(11), 0);
+
+ return result;
+ }
+
+ val32 = 0x80007c00 | (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff);
+ rtl8xxxu_write32(priv, REG_TX_IQK, val32);
+
+ /* Modify RX IQK mode table */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+
+ /* Path B IQK setting */
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
+ rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c);
+
+ rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82170000);
+ rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28170000);
+
+ /* IQK setting */
+ rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
+
+ /* LO calibration setting */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
+
+ /* One shot, path A LOK & IQK */
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800);
+ rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800);
+
+ mdelay(15);
+
+ ktime = 0;
+ while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXB) == 0 && ktime < 21) {
+ mdelay(5);
+ ktime += 5;
+ }
+
+ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 0);
+ rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 0);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0x02000);
+
+ if (!(reg_eac & BIT(30)) &&
+ ((reg_ec4 & 0x03ff0000) != 0x01320000) &&
+ ((reg_ecc & 0x03ff0000) != 0x00360000))
+ result |= 0x02;
+ else
+ dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n",
+ __func__);
+
+ return result;
+}
+
+static void rtl8192fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
+ int result[][8], int t)
+{
+ static const u32 adda_regs[2] = {
+ REG_ANAPWR1, REG_RX_WAIT_CCA
+ };
+ static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
+ REG_TXPAUSE, REG_BEACON_CTRL,
+ REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
+ };
+ static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
+ REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
+ REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
+ REG_DPDT_CTRL, REG_RFE_CTRL_ANTA_SRC,
+ REG_RFE_CTRL_ANT_SRC2, REG_CCK0_AFE_SETTING
+ };
+ u32 rx_initial_gain_a, rx_initial_gain_b;
+ struct device *dev = &priv->udev->dev;
+ int path_a_ok, path_b_ok;
+ u8 rfe = priv->rfe_type;
+ int retry = 2;
+ u32 i, val32;
+
+ /*
+ * Note: IQ calibration must be performed after loading
+ * PHY_REG.txt , and radio_a, radio_b.txt
+ */
+
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rx_initial_gain_a = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
+ rx_initial_gain_b = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1);
+
+ if (t == 0) {
+ /* Save ADDA parameters, turn Path A ADDA on */
+ rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
+ ARRAY_SIZE(adda_regs));
+ rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+ rtl8xxxu_save_regs(priv, iqk_bb_regs,
+ priv->bb_backup, RTL8XXXU_BB_REGS);
+ }
+
+ /* Instead of rtl8xxxu_path_adda_on */
+ rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, BIT(31));
+
+ /* MAC settings */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+ rtl8xxxu_write8_clear(priv, REG_GPIO_MUXCFG, GPIO_MUXCFG_IO_SEL_ENBT);
+
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) {
+ /* in ePA IQK, rfe_func_config & SW both pull down */
+ /* path A */
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x1, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF00, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x4, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8, 0x0);
+
+ /* path B */
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x20000, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x100000, 0x0);
+
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, 0xF000, 0x7);
+ rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8000000, 0x0);
+ }
+
+ if (priv->rf_paths > 1) {
+ /* path B standby */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x000000);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000);
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000);
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_a_ok = rtl8192fu_iqk_path_a(priv);
+
+ if (path_a_ok == 0x01) {
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
+ result[t][0] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
+ result[t][1] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][0] = 0x100;
+ result[t][1] = 0x0;
+ }
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_a_ok = rtl8192fu_rx_iqk_path_a(priv);
+
+ if (path_a_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
+ result[t][2] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
+ result[t][3] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][2] = 0x100;
+ result[t][3] = 0x0;
+ }
+ }
+
+ if (!path_a_ok)
+ dev_warn(dev, "%s: Path A IQK failed!\n", __func__);
+
+ if (priv->rf_paths > 1) {
+ for (i = 0; i < retry; i++) {
+ path_b_ok = rtl8192fu_iqk_path_b(priv);
+
+ if (path_b_ok == 0x01) {
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
+ result[t][4] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
+ result[t][5] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][4] = 0x100;
+ result[t][5] = 0x0;
+ }
+ }
+
+ for (i = 0; i < retry; i++) {
+ path_b_ok = rtl8192fu_rx_iqk_path_b(priv);
+
+ if (path_b_ok == 0x03) {
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
+ result[t][6] = (val32 >> 16) & 0x3ff;
+
+ val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
+ result[t][7] = (val32 >> 16) & 0x3ff;
+ break;
+ } else {
+ result[t][6] = 0x100;
+ result[t][7] = 0x0;
+ }
+ }
+
+ if (!path_b_ok)
+ dev_warn(dev, "%s: Path B IQK failed!\n", __func__);
+ }
+
+ /* Back to BB mode, load original value */
+ rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0);
+
+ rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xcc0000c0);
+
+ rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44bbbb44);
+ rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x80408040);
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005433);
+ rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000004e4);
+ rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04003400);
+ rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
+
+ /* Reload ADDA power saving parameters */
+ rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
+ ARRAY_SIZE(adda_regs));
+
+ /* Reload MAC parameters */
+ rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
+
+ /* Reload BB parameters */
+ rtl8xxxu_restore_regs(priv, iqk_bb_regs, priv->bb_backup, RTL8XXXU_BB_REGS);
+
+ rtl8xxxu_write32_clear(priv, REG_FPGA0_XCD_RF_PARM, BIT(31));
+
+ /* Restore RX initial gain */
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, 0x50);
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff,
+ rx_initial_gain_a & 0xff);
+ if (priv->rf_paths > 1) {
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, 0x50);
+ rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff,
+ rx_initial_gain_b & 0xff);
+ }
+}
+
+static void rtl8192fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
+{
+ s32 reg_e94, reg_e9c, reg_ea4, reg_eac;
+ s32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+ struct device *dev = &priv->udev->dev;
+ u32 path_a_0xdf, path_a_0x35;
+ u32 path_b_0xdf, path_b_0x35;
+ bool path_a_ok, path_b_ok;
+ u8 rfe = priv->rfe_type;
+ u32 rfe_path_select;
+ int result[4][8]; /* last is final result */
+ int i, candidate;
+ s32 reg_tmp = 0;
+ bool simu;
+ u32 val32;
+
+ rfe_path_select = rtl8xxxu_read32(priv, REG_RFE_PATH_SELECT);
+
+ path_a_0xdf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
+ path_a_0x35 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_P1);
+ path_b_0xdf = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA);
+ path_b_0x35 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_P1);
+
+ memset(result, 0, sizeof(result));
+ candidate = -1;
+
+ path_a_ok = false;
+ path_b_ok = false;
+
+ for (i = 0; i < 3; i++) {
+ rtl8192fu_phy_iqcalibrate(priv, result, i);
+
+ if (i == 1) {
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2);
+ if (simu) {
+ candidate = 0;
+ break;
+ }
+
+ simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2);
+ if (simu) {
+ candidate = 1;
+ } else {
+ for (i = 0; i < 8; i++)
+ reg_tmp += result[3][i];
+
+ if (reg_tmp)
+ candidate = 3;
+ else
+ candidate = -1;
+ }
+ }
+ }
+
+ if (candidate >= 0) {
+ reg_e94 = result[candidate][0];
+ reg_e9c = result[candidate][1];
+ reg_ea4 = result[candidate][2];
+ reg_eac = result[candidate][3];
+ reg_eb4 = result[candidate][4];
+ reg_ebc = result[candidate][5];
+ reg_ec4 = result[candidate][6];
+ reg_ecc = result[candidate][7];
+
+ dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
+ dev_dbg(dev, "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%c\n",
+ __func__, reg_e94, reg_e9c, reg_ea4, reg_eac,
+ reg_eb4, reg_ebc, reg_ec4, reg_ecc);
+
+ path_a_ok = true;
+ path_b_ok = true;
+ }
+
+ rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_A, 0x3ff00000, 0x100);
+ rtl8xxxu_write32_mask(priv, REG_NP_ANTA, 0x3ff, 0);
+ rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_B, 0x3ff00000, 0x100);
+ rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, 0x3ff, 0);
+
+ if (candidate >= 0) {
+ if (reg_e94)
+ rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
+ candidate, (reg_ea4 == 0));
+
+ if (reg_eb4)
+ rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result,
+ candidate, (reg_ec4 == 0));
+ }
+
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, path_a_0xdf);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, path_a_0x35);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, path_b_0xdf);
+ rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, path_b_0x35);
+
+ if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) {
+ rtl8xxxu_write32_set(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x70000);
+ rtl8xxxu_write32_clear(priv, REG_LEDCFG0, 0x6c00000);
+ rtl8xxxu_write32_set(priv, REG_PAD_CTRL1, BIT(29) | BIT(28));
+ rtl8xxxu_write32_clear(priv, REG_SW_GPIO_SHARE_CTRL_0,
+ 0x600000 | BIT(4));
+
+ /*
+ * Originally:
+ * odm_set_bb_reg(dm, R_0x944, BIT(11) | 0x1F, 0x3F);
+ *
+ * It clears bit 11 and sets bits 0..4. The mask doesn't cover
+ * bit 5 so it's not modified. Is that what it's supposed to
+ * accomplish?
+ */
+ val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER);
+ val32 &= ~BIT(11);
+ val32 |= 0x1f;
+ rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32);
+
+ if (rfe == 7) {
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC,
+ 0xfffff, 0x23200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2,
+ 0xfffff, 0x23200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1,
+ 0xf000, 0x3);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3,
+ 0xf000, 0x3);
+ } else {
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC,
+ 0xfffff, 0x22200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2,
+ 0xfffff, 0x22200);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1,
+ 0xf000, 0x2);
+ rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3,
+ 0xf000, 0x2);
+ }
+
+ rtl8xxxu_write32_clear(priv, REG_RFE_OPT62, BIT(2));
+
+ if (rfe == 7)
+ rtl8xxxu_write32(priv, REG_RFE_OPT, 0x03000003);
+
+ rtl8xxxu_write32(priv, REG_RFE_PATH_SELECT, rfe_path_select);
+ }
+}
+
+static void rtl8192fu_disabled_to_emu(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_HW_POWERDOWN | APS_FSMCO_HW_SUSPEND);
+
+ rtl8xxxu_write32_clear(priv, REG_GPIO_INTM, BIT(16));
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND);
+}
+
+static int rtl8192fu_emu_to_active(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+ u16 val16;
+ int count;
+
+ /* enable LDOA12 MACRO block for all interface */
+ rtl8xxxu_write8_set(priv, REG_LDOA15_CTRL, LDOA15_ENABLE);
+
+ /* disable BT_GPS_SEL pins */
+ rtl8xxxu_write32_clear(priv, REG_PAD_CTRL1, BIT(28));
+
+ mdelay(1);
+
+ /* release analog Ips to digital */
+ rtl8xxxu_write8_clear(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS);
+
+ val16 = APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND | APS_FSMCO_SW_LPS;
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, val16);
+
+ /* wait till 0x04[17] = 1 power ready */
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if (val32 & BIT(17))
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & (APS_FSMCO_MAC_ENABLE | APS_FSMCO_MAC_OFF)) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* SWR OCP enable */
+ rtl8xxxu_write32_set(priv, REG_AFE_MISC, BIT(18));
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN);
+
+ rtl8xxxu_write16_clear(priv, REG_APS_FSMCO,
+ APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND);
+
+ /* 0x7c[31]=1, LDO has max output capability */
+ rtl8xxxu_write32_set(priv, REG_LDO_SW_CTRL, BIT(31));
+
+ rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_ENABLE);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & APS_FSMCO_MAC_ENABLE) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* Enable WL control XTAL setting */
+ rtl8xxxu_write8_set(priv, REG_AFE_MISC, AFE_MISC_WL_XTAL_CTRL);
+
+ /* Enable falling edge triggering interrupt */
+ rtl8xxxu_write16_set(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ);
+
+ /* Enable GPIO9 data mode */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_IRQ);
+
+ /* Enable GPIO9 input mode */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_INPUT);
+
+ /* Enable HSISR GPIO[C:0] interrupt */
+ rtl8xxxu_write8_set(priv, REG_HSIMR, BIT(0));
+
+ /* RF HW ON/OFF Enable */
+ rtl8xxxu_write8_clear(priv, REG_MULTI_FUNC_CTRL, MULTI_WIFI_HW_ROF_EN);
+
+ /* Register Lock Disable */
+ rtl8xxxu_write8_set(priv, REG_RSV_CTRL, BIT(7));
+
+ /* For GPIO9 internal pull high setting */
+ rtl8xxxu_write16_set(priv, REG_MULTI_FUNC_CTRL, BIT(14));
+
+ /* reset RF path S1 */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
+
+ /* reset RF path S0 */
+ rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, 0);
+
+ /* enable RF path S1 */
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_SDMRSTB | RF_RSTB | RF_ENABLE);
+
+ /* enable RF path S0 */
+ rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, RF_SDMRSTB | RF_RSTB | RF_ENABLE);
+
+ /* AFE_Ctrl */
+ rtl8xxxu_write8_set(priv, REG_RSVD_1, BIT(5));
+
+ /* AFE_Ctrl */
+ rtl8xxxu_write8(priv, REG_RSVD_4, 0xcc);
+
+ /* AFE_Ctrl 0x24[4:3]=00 for xtal gmn */
+ rtl8xxxu_write8_clear(priv, REG_AFE_XTAL_CTRL, BIT(4) | BIT(3));
+
+ /* GPIO_A[31:0] Pull down software register */
+ rtl8xxxu_write32(priv, REG_GPIO_A0, 0xffffffff);
+
+ /* GPIO_B[7:0] Pull down software register */
+ rtl8xxxu_write8(priv, REG_GPIO_B0, 0xff);
+
+ /* Register Lock Enable */
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(7));
+
+ return 0;
+}
+
+static int rtl8192fu_active_to_emu(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+ int count;
+
+ /* Reset BB, RF enter Power Down mode */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB);
+
+ /* Enable rising edge triggering interrupt */
+ rtl8xxxu_write16_clear(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ);
+
+ /* release WLON reset */
+ rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET);
+
+ /* turn off MAC by HW state machine */
+ rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_OFF);
+
+ for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
+ val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
+ if ((val32 & APS_FSMCO_MAC_OFF) == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (!count)
+ return -EBUSY;
+
+ /* analog Ips to digital, 1:isolation */
+ rtl8xxxu_write8_set(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS);
+
+ /* disable LDOA12 MACRO block */
+ rtl8xxxu_write8_clear(priv, REG_LDOA15_CTRL, LDOA15_ENABLE);
+
+ return 0;
+}
+
+static int rtl8192fu_emu_to_disabled(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+
+ /* SOP option to disable BG/MB */
+ rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20);
+
+ /* 0x04[12:11] = 2b'01 enable WL suspend */
+ val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
+ val16 &= ~APS_FSMCO_PCIE;
+ val16 |= APS_FSMCO_HW_SUSPEND;
+ rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
+
+ /* enable GPIO9 as EXT WAKEUP */
+ rtl8xxxu_write32_set(priv, REG_GPIO_INTM, BIT(16));
+
+ return 0;
+}
+
+static int rtl8192fu_active_to_lps(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u16 val16;
+ u32 val32;
+ int retry;
+
+ /* Tx Pause */
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
+
+ retry = 100;
+
+ /* Poll 32 bit wide REG_SCH_TX_CMD for 0 to ensure no TX is pending. */
+ do {
+ val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
+ if (!val32)
+ break;
+
+ udelay(10);
+ } while (retry--);
+
+ if (!retry) {
+ dev_warn(dev, "%s: Failed to flush TX queue\n", __func__);
+ return -EBUSY;
+ }
+
+ /* Disable CCK and OFDM, clock gated */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB);
+
+ udelay(2);
+
+ /* Whole BB is reset */
+ rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BB_GLB_RSTN);
+
+ /* Reset MAC TRX */
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 &= 0xff00;
+ val16 |= CR_HCI_RXDMA_ENABLE | CR_HCI_TXDMA_ENABLE;
+ val16 &= ~CR_SECURITY_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ /* Respond TxOK to scheduler */
+ rtl8xxxu_write8_set(priv, REG_DUAL_TSF_RST, DUAL_TSF_TX_OK);
+
+ return 0;
+}
+
+static int rtl8192fu_power_on(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+ int ret;
+
+ rtl8xxxu_write8(priv, REG_USB_ACCESS_TIMEOUT, 0x80);
+
+ rtl8192fu_disabled_to_emu(priv);
+
+ ret = rtl8192fu_emu_to_active(priv);
+ if (ret)
+ return ret;
+
+ rtl8xxxu_write16(priv, REG_CR, 0);
+
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+
+ val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
+ CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
+ CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
+ CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE;
+ rtl8xxxu_write16(priv, REG_CR, val16);
+
+ return 0;
+}
+
+static void rtl8192fu_power_off(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_flush_fifo(priv);
+
+ /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
+ rtl8xxxu_write8_clear(priv, REG_TX_REPORT_CTRL,
+ TX_REPORT_CTRL_TIMER_ENABLE);
+
+ /* stop rx */
+ rtl8xxxu_write8(priv, REG_CR, 0x00);
+
+ rtl8192fu_active_to_lps(priv);
+
+ /* Reset Firmware if running in RAM */
+ if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
+ rtl8xxxu_firmware_self_reset(priv);
+
+ /* Reset MCU */
+ rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+
+ /* Reset MCU ready status */
+ rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
+
+ rtl8192fu_active_to_emu(priv);
+ rtl8192fu_emu_to_disabled(priv);
+}
+
+static void rtl8192f_reset_8051(struct rtl8xxxu_priv *priv)
+{
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1));
+
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL + 1, BIT(0));
+
+ rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+
+ rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1));
+
+ rtl8xxxu_write8_set(priv, REG_RSV_CTRL + 1, BIT(0));
+
+ rtl8xxxu_write16_set(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE);
+}
+
+static void rtl8192f_enable_rf(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+
+ rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK);
+ val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B |
+ OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
+}
+
+static void rtl8192f_disable_rf(struct rtl8xxxu_priv *priv)
+{
+ u32 val32;
+
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
+ val32 &= ~OFDM_RF_PATH_TX_MASK;
+ rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
+
+ /* Power down RF module */
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0);
+}
+
+static void rtl8192f_usb_quirks(struct rtl8xxxu_priv *priv)
+{
+ u16 val16;
+
+ rtl8xxxu_gen2_usb_quirks(priv);
+
+ val16 = rtl8xxxu_read16(priv, REG_CR);
+ val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE);
+ rtl8xxxu_write16(priv, REG_CR, val16);
+}
+
+#define XTAL1 GENMASK(6, 1)
+#define XTAL0 GENMASK(30, 25)
+
+static void rtl8192f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
+{
+ struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
+ u32 xtal1, xtal0;
+
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ xtal1 = rtl8xxxu_read32(priv, REG_AFE_PLL_CTRL);
+ xtal0 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
+
+ dev_dbg(&priv->udev->dev,
+ "%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n",
+ __func__,
+ cfo->crystal_cap,
+ u32_get_bits(xtal1, XTAL1),
+ u32_get_bits(xtal0, XTAL0),
+ crystal_cap);
+
+ u32p_replace_bits(&xtal1, crystal_cap, XTAL1);
+ u32p_replace_bits(&xtal0, crystal_cap, XTAL0);
+ rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, xtal1);
+ rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, xtal0);
+
+ cfo->crystal_cap = crystal_cap;
+}
+
+static s8 rtl8192f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
+{
+ struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats;
+ u8 lna_idx = (phy_stats0->lna_h << 3) | phy_stats0->lna_l;
+ u8 vga_idx = phy_stats0->vga;
+ s8 rx_pwr_all;
+
+ switch (lna_idx) {
+ case 7:
+ rx_pwr_all = -44 - (2 * vga_idx);
+ break;
+ case 5:
+ rx_pwr_all = -28 - (2 * vga_idx);
+ break;
+ case 3:
+ rx_pwr_all = -10 - (2 * vga_idx);
+ break;
+ case 0:
+ rx_pwr_all = 14 - (2 * vga_idx);
+ break;
+ default:
+ rx_pwr_all = 0;
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
+static int rtl8192fu_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct rtl8xxxu_priv *priv = container_of(led_cdev,
+ struct rtl8xxxu_priv,
+ led_cdev);
+ u16 ledcfg;
+
+ /* Values obtained by observing the USB traffic from the Windows driver. */
+ rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080);
+ rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000);
+
+ ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0);
+
+ if (brightness == LED_OFF) {
+ /* Value obtained like above. */
+ ledcfg = BIT(1) | BIT(7);
+ } else if (brightness == LED_ON) {
+ /* Value obtained like above. */
+ ledcfg = BIT(1) | BIT(7) | BIT(11);
+ } else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
+ /* Value obtained by brute force. */
+ ledcfg = BIT(8) | BIT(9);
+ }
+
+ rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg);
+
+ return 0;
+}
+
+struct rtl8xxxu_fileops rtl8192fu_fops = {
+ .identify_chip = rtl8192fu_identify_chip,
+ .parse_efuse = rtl8192fu_parse_efuse,
+ .load_firmware = rtl8192fu_load_firmware,
+ .power_on = rtl8192fu_power_on,
+ .power_off = rtl8192fu_power_off,
+ .read_efuse = rtl8xxxu_read_efuse,
+ .reset_8051 = rtl8192f_reset_8051,
+ .llt_init = rtl8xxxu_auto_llt_table,
+ .init_phy_bb = rtl8192fu_init_phy_bb,
+ .init_phy_rf = rtl8192fu_init_phy_rf,
+ .phy_lc_calibrate = rtl8192f_phy_lc_calibrate,
+ .phy_iq_calibrate = rtl8192fu_phy_iq_calibrate,
+ .config_channel = rtl8192fu_config_channel,
+ .parse_rx_desc = rtl8xxxu_parse_rxdesc24,
+ .parse_phystats = jaguar2_rx_parse_phystats,
+ .init_aggregation = rtl8192fu_init_aggregation,
+ .init_burst = rtl8xxxu_init_burst,
+ .enable_rf = rtl8192f_enable_rf,
+ .disable_rf = rtl8192f_disable_rf,
+ .usb_quirks = rtl8192f_usb_quirks,
+ .set_tx_power = rtl8192f_set_tx_power,
+ .update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
+ .report_connect = rtl8xxxu_gen2_report_connect,
+ .report_rssi = rtl8xxxu_gen2_report_rssi,
+ .fill_txdesc = rtl8xxxu_fill_txdesc_v2,
+ .set_crystal_cap = rtl8192f_set_crystal_cap,
+ .cck_rssi = rtl8192f_cck_rssi,
+ .led_classdev_brightness_set = rtl8192fu_led_brightness_set,
+ .writeN_block_size = 254,
+ .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
+ .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
+ .has_tx_report = 1,
+ .gen2_thermal_meter = 1,
+ .needs_full_init = 1,
+ .init_reg_rxfltmap = 1,
+ .init_reg_pkt_life_time = 1,
+ .init_reg_hmtfr = 1,
+ .ampdu_max_time = 0x5e,
+ .ustime_tsf_edca = 0x50,
+ .max_aggr_num = 0x1f1f,
+ .trxff_boundary = 0x3f3f,
+ .pbp_rx = PBP_PAGE_SIZE_256,
+ .pbp_tx = PBP_PAGE_SIZE_256,
+ .mactable = rtl8192f_mac_init_table,
+ .total_page_num = TX_TOTAL_PAGE_NUM_8192F,
+ .page_num_hi = TX_PAGE_NUM_HI_PQ_8192F,
+ .page_num_lo = TX_PAGE_NUM_LO_PQ_8192F,
+ .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192F,
+};
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
index 22d4704dd31e..f0d17b75c5f1 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c
@@ -1031,12 +1031,12 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7);
/* PA,PAD gain adjust */
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0x1ed, 0x00fff);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/* enter IQK mode */
val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
@@ -1068,9 +1068,9 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
/* save LOK result */
*lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC);
@@ -1113,12 +1113,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
/* PA,PAD gain adjust */
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0xf, 0x003e0);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/*
* Enter IQK mode
@@ -1170,9 +1170,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
return result;
}
@@ -1197,12 +1197,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
/*
* PA, PAD setting
*/
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 |= BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG);
u32p_replace_bits(&val32, 0x2a, 0x00fff);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32);
/*
* Enter IQK mode
@@ -1241,9 +1241,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
u32p_replace_bits(&val32, 0, 0xffffff00);
rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
- val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF);
+ val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA);
val32 &= ~BIT(11);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32);
/* reload LOK value */
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result);
@@ -1874,6 +1874,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = {
* but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why?
*/
.ustime_tsf_edca = 0x28,
+ .max_aggr_num = 0x0c14,
.adda_1t_init = 0x03c00016,
.adda_1t_path_on = 0x03c00016,
.trxff_boundary = 0x3f7f,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
index abc56c7de6f7..13ad5d5b73f4 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
@@ -824,7 +824,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
/*
* PA, PAD setting
*/
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0xf80);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0xf80);
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55, 0x4021f);
/*
@@ -888,7 +888,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
- rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x780);
+ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x780);
val32 = (reg_eac >> 16) & 0x3ff;
if (val32 & 0x200)
@@ -1741,6 +1741,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.init_reg_hmtfr = 1,
.ampdu_max_time = 0x5e,
.ustime_tsf_edca = 0x50,
+ .max_aggr_num = 0x0c14,
.adda_1t_init = 0x01c00014,
.adda_1t_path_on = 0x01c00014,
.adda_2t_path_on_a = 0x01c00014,
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 831639d73657..5d102a1246a3 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -56,6 +56,7 @@ MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin");
MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin");
module_param_named(debug, rtl8xxxu_debug, int, 0600);
MODULE_PARM_DESC(debug, "Set debug mask");
@@ -642,7 +643,7 @@ const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = {
REG_OFDM0_XA_RX_IQ_IMBALANCE,
REG_OFDM0_XB_RX_IQ_IMBALANCE,
REG_OFDM0_ENERGY_CCA_THRES,
- REG_OFDM0_AGCR_SSI_TABLE,
+ REG_OFDM0_AGC_RSSI_TABLE,
REG_OFDM0_XA_TX_IQ_IMBALANCE,
REG_OFDM0_XB_TX_IQ_IMBALANCE,
REG_OFDM0_XC_TX_AFE,
@@ -1185,6 +1186,20 @@ static void rtl8xxxu_stop_tx_beacon(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
}
+static void rtl8xxxu_start_tx_beacon(struct rtl8xxxu_priv *priv)
+{
+ u8 val8;
+
+ val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2);
+ val8 |= EN_BCNQ_DL >> 16;
+ rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8);
+
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x80);
+ val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2);
+ val8 &= 0xF0;
+ rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8);
+}
+
/*
* The rtl8723a has 3 channel groups for it's efuse settings. It only
@@ -2006,12 +2021,18 @@ exit:
static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
{
int pages, remainder, i, ret;
+ u16 reg_fw_start_address;
u16 reg_mcu_fw_dl;
u8 val8;
u16 val16;
u32 val32;
u8 *fwptr;
+ if (priv->rtl_chip == RTL8192F)
+ reg_fw_start_address = REG_FW_START_ADDRESS_8192F;
+ else
+ reg_fw_start_address = REG_FW_START_ADDRESS;
+
if (priv->rtl_chip == RTL8710B) {
reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B;
} else {
@@ -2067,7 +2088,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
val8 |= i;
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
- ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ ret = rtl8xxxu_writeN(priv, reg_fw_start_address,
fwptr, RTL_FW_PAGE_SIZE);
if (ret != RTL_FW_PAGE_SIZE) {
ret = -EAGAIN;
@@ -2081,7 +2102,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8;
val8 |= i;
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
- ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
+ ret = rtl8xxxu_writeN(priv, reg_fw_start_address,
fwptr, remainder);
if (ret != remainder) {
ret = -EAGAIN;
@@ -2135,6 +2156,7 @@ int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name)
case 0x2300:
case 0x88f0:
case 0x10b0:
+ case 0x92f0:
break;
default:
ret = -EINVAL;
@@ -2581,6 +2603,7 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv)
u16 hiq, mgq, bkq, beq, viq, voq;
int hip, mgp, bkp, bep, vip, vop;
int ret = 0;
+ u32 val32;
switch (priv->ep_tx_count) {
case 1:
@@ -2663,15 +2686,28 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv)
* queue here .... why?
*/
if (!ret) {
- val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL);
- val16 &= 0x7;
- val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) |
- (viq << TRXDMA_CTRL_VIQ_SHIFT) |
- (beq << TRXDMA_CTRL_BEQ_SHIFT) |
- (bkq << TRXDMA_CTRL_BKQ_SHIFT) |
- (mgq << TRXDMA_CTRL_MGQ_SHIFT) |
- (hiq << TRXDMA_CTRL_HIQ_SHIFT);
- rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16);
+ /* Only RTL8192F seems to do it like this. */
+ if (priv->rtl_chip == RTL8192F) {
+ val32 = rtl8xxxu_read32(priv, REG_TRXDMA_CTRL);
+ val32 &= 0x7;
+ val32 |= (voq << TRXDMA_CTRL_VOQ_SHIFT_8192F) |
+ (viq << TRXDMA_CTRL_VIQ_SHIFT_8192F) |
+ (beq << TRXDMA_CTRL_BEQ_SHIFT_8192F) |
+ (bkq << TRXDMA_CTRL_BKQ_SHIFT_8192F) |
+ (mgq << TRXDMA_CTRL_MGQ_SHIFT_8192F) |
+ (hiq << TRXDMA_CTRL_HIQ_SHIFT_8192F);
+ rtl8xxxu_write32(priv, REG_TRXDMA_CTRL, val32);
+ } else {
+ val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL);
+ val16 &= 0x7;
+ val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) |
+ (viq << TRXDMA_CTRL_VIQ_SHIFT) |
+ (beq << TRXDMA_CTRL_BEQ_SHIFT) |
+ (bkq << TRXDMA_CTRL_BKQ_SHIFT) |
+ (mgq << TRXDMA_CTRL_MGQ_SHIFT) |
+ (hiq << TRXDMA_CTRL_HIQ_SHIFT);
+ rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16);
+ }
priv->pipe_out[TXDESC_QUEUE_VO] =
usb_sndbulkpipe(priv->udev, priv->out_ep[vop]);
@@ -2842,10 +2878,14 @@ void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok,
reg = (result[candidate][7] >> 6) & 0xf;
- val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE);
- val32 &= ~0x0000f000;
- val32 |= (reg << 12);
- rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32);
+ if (priv->rtl_chip == RTL8192F) {
+ rtl8xxxu_write32_mask(priv, REG_RXIQB_EXT, 0x000000f0, reg);
+ } else {
+ val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_RSSI_TABLE);
+ val32 &= ~0x0000f000;
+ val32 |= (reg << 12);
+ rtl8xxxu_write32(priv, REG_OFDM0_AGC_RSSI_TABLE, val32);
+ }
}
#define MAX_TOLERANCE 5
@@ -3944,13 +3984,14 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
val8 |= HT_SINGLE_AMPDU_ENABLE;
rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8);
- rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14);
+ rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, priv->fops->max_aggr_num);
rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B,
priv->fops->ampdu_max_time);
rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff);
rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18);
rtl8xxxu_write8(priv, REG_PIFS, 0x00);
- if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
+ if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B ||
+ priv->rtl_chip == RTL8192F) {
rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY);
rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666);
}
@@ -3963,6 +4004,34 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_RSV_CTRL, val8);
}
+static u8 rtl8xxxu_acquire_macid(struct rtl8xxxu_priv *priv)
+{
+ u8 macid;
+
+ macid = find_first_zero_bit(priv->mac_id_map, RTL8XXXU_MAX_MAC_ID_NUM);
+ if (macid < RTL8XXXU_MAX_MAC_ID_NUM)
+ set_bit(macid, priv->mac_id_map);
+
+ return macid;
+}
+
+static void rtl8xxxu_release_macid(struct rtl8xxxu_priv *priv, u8 macid)
+{
+ clear_bit(macid, priv->mac_id_map);
+}
+
+static inline u8 rtl8xxxu_get_macid(struct rtl8xxxu_priv *priv,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info;
+
+ if (!priv->vif || priv->vif->type == NL80211_IFTYPE_STATION || !sta)
+ return 0;
+
+ sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ return sta_info->macid;
+}
+
static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
{
struct rtl8xxxu_priv *priv = hw->priv;
@@ -4036,9 +4105,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (ret)
goto exit;
+ /* Mac APLL Setting */
+ if (priv->rtl_chip == RTL8192F)
+ rtl8xxxu_write16_set(priv, REG_AFE_CTRL4, BIT(4) | BIT(15));
+
/* RFSW Control - clear bit 14 ?? */
if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E &&
- priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
+ priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B &&
+ priv->rtl_chip != RTL8192F)
rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003);
val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW |
@@ -4052,7 +4126,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* 0x860[6:5]= 00 - why? - this sets antenna B */
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E &&
- priv->rtl_chip != RTL8710B)
+ priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F)
rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210);
if (!macpower) {
@@ -4126,7 +4200,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write8(priv, 0xa3, val8);
}
- if (priv->rtl_chip == RTL8710B)
+ if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F)
rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, 0);
}
@@ -4153,7 +4227,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val8);
} else if (priv->rtl_chip == RTL8710B) {
rtl8xxxu_write32(priv, REG_HIMR0_8710B, 0);
- } else {
+ } else if (priv->rtl_chip != RTL8192F) {
/*
* Enable all interrupts - not obvious USB needs to do this
*/
@@ -4242,7 +4316,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8);
rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16);
rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404);
- if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B)
+ if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B &&
+ priv->rtl_chip != RTL8192F)
/* Firmware will control REG_DRVERLYINT when power saving is enable, */
/* so don't set this register on STA mode. */
rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME);
@@ -4293,7 +4368,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* Disable BAR - not sure if this has any effect on USB */
rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff);
- if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
+ if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E &&
+ priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F)
rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0);
if (fops->init_statistics)
@@ -4311,9 +4387,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
* Reset USB mode switch setting
*/
rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00);
- } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E) {
+ } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E ||
+ priv->rtl_chip == RTL8192F) {
/*
- * Init GPIO settings for 8188f, 8188e
+ * Init GPIO settings for 8188f, 8188e, 8192f
*/
val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG);
val8 &= ~GPIO_MUXCFG_IO_SEL_ENBT;
@@ -4433,6 +4510,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
if (priv->rtl_chip == RTL8188E)
rtl8188e_ra_info_init_all(&priv->ra_info);
+ set_bit(RTL8XXXU_BC_MC_MACID, priv->mac_id_map);
+
exit:
return ret;
}
@@ -4490,6 +4569,16 @@ int rtl8xxxu_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0;
}
+static int rtl8xxxu_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+ bool set)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ schedule_work(&priv->update_beacon_work);
+
+ return 0;
+}
+
static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, const u8 *mac)
{
@@ -4513,7 +4602,8 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw,
}
void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct h2c_cmd h2c;
@@ -4533,7 +4623,8 @@ void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
- u32 ramask, u8 rateid, int sgi, int txbw_40mhz)
+ u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
+ u8 macid)
{
struct h2c_cmd h2c;
u8 bw;
@@ -4550,6 +4641,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
h2c.b_macid_cfg.ramask1 = (ramask >> 8) & 0xff;
h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff;
h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff;
+ h2c.b_macid_cfg.macid = macid;
h2c.b_macid_cfg.data1 = rateid;
if (sgi)
@@ -4563,7 +4655,7 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect)
+ u8 macid, u8 role, bool connect)
{
struct h2c_cmd h2c;
@@ -4580,7 +4672,7 @@ void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
}
void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
- u8 macid, bool connect)
+ u8 macid, u8 role, bool connect)
{
/*
* The firmware turns on the rate control when it knows it's
@@ -4596,6 +4688,9 @@ void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
else
h2c.media_status_rpt.parm &= ~BIT(0);
+ h2c.media_status_rpt.parm |= ((role << 4) & 0xf0);
+ h2c.media_status_rpt.macid = macid;
+
rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
}
@@ -4912,7 +5007,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
priv->vif = vif;
priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
- priv->fops->update_rate_mask(priv, ramask, 0, sgi, bw == RATE_INFO_BW_40);
+ priv->fops->update_rate_mask(priv, ramask, 0, sgi,
+ bw == RATE_INFO_BW_40, 0);
rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
@@ -4922,13 +5018,13 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
rtl8xxxu_write16(priv, REG_BCN_PSR_RPT,
0xc000 | vif->cfg.aid);
- priv->fops->report_connect(priv, 0, true);
+ priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, true);
} else {
val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
val8 |= BEACON_DISABLE_TSF_UPDATE;
rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
- priv->fops->report_connect(priv, 0, false);
+ priv->fops->report_connect(priv, 0, H2C_MACID_ROLE_AP, false);
}
}
@@ -4965,10 +5061,35 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
dev_dbg(dev, "Changed BASIC_RATES!\n");
rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates);
}
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ if (bss_conf->enable_beacon)
+ rtl8xxxu_start_tx_beacon(priv);
+ else
+ rtl8xxxu_stop_tx_beacon(priv);
+ }
+
+ if (changed & BSS_CHANGED_BEACON)
+ schedule_work(&priv->update_beacon_work);
+
error:
return;
}
+static int rtl8xxxu_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct device *dev = &priv->udev->dev;
+
+ dev_dbg(dev, "Start AP mode\n");
+ rtl8xxxu_set_bssid(priv, vif->bss_conf.bssid);
+ rtl8xxxu_write16(priv, REG_BCN_INTERVAL, vif->bss_conf.beacon_int);
+ priv->fops->report_connect(priv, RTL8XXXU_BC_MC_MACID, 0, true);
+
+ return 0;
+}
+
static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue)
{
u32 rtlqueue;
@@ -4997,7 +5118,9 @@ static u32 rtl8xxxu_queue_select(struct ieee80211_hdr *hdr, struct sk_buff *skb)
{
u32 queue;
- if (ieee80211_is_mgmt(hdr->frame_control))
+ if (unlikely(ieee80211_is_beacon(hdr->frame_control)))
+ queue = TXDESC_QUEUE_BEACON;
+ else if (ieee80211_is_mgmt(hdr->frame_control))
queue = TXDESC_QUEUE_MGNT;
else
queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb));
@@ -5160,23 +5283,16 @@ void
rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
dev_info(dev, "%s: TX rate: %d, pkt size %u\n",
__func__, rate, le16_to_cpu(tx_desc->pkt_size));
@@ -5215,10 +5331,10 @@ rtl8xxxu_fill_txdesc_v1(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
@@ -5232,30 +5348,25 @@ void
rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_txdesc40 *tx_desc40;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
tx_desc40 = (struct rtl8xxxu_txdesc40 *)tx_desc32;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX)
dev_info(dev, "%s: TX rate: %d, pkt size %u\n",
__func__, rate, le16_to_cpu(tx_desc40->pkt_size));
+ tx_desc40->txdw1 |= cpu_to_le32(macid << TXDESC40_MACID_SHIFT);
+
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
tx_desc40->txdw4 = cpu_to_le32(rate);
@@ -5279,17 +5390,21 @@ rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
tx_desc40->txdw4 |= cpu_to_le32(TXDESC40_RETRY_LIMIT_ENABLE);
}
+ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ tx_desc40->txdw8 |= cpu_to_le32(TXDESC40_HW_SEQ_ENABLE);
+
if (short_preamble)
tx_desc40->txdw5 |= cpu_to_le32(TXDESC40_SHORT_PREAMBLE);
tx_desc40->txdw4 |= cpu_to_le32(rts_rate << TXDESC40_RTS_RATE_SHIFT);
+
/*
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_RTS_CTS_ENABLE);
tx_desc40->txdw3 |= cpu_to_le32(TXDESC40_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
/*
* For some reason the vendor driver doesn't set
* TXDESC40_HW_RTS_ENABLE for CTS to SELF
@@ -5307,24 +5422,17 @@ void
rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *tx_info,
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
- bool short_preamble, bool ampdu_enable, u32 rts_rate)
+ bool short_preamble, bool ampdu_enable, u32 rts_rate,
+ u8 macid)
{
- struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info);
struct rtl8xxxu_priv *priv = hw->priv;
struct device *dev = &priv->udev->dev;
struct rtl8xxxu_ra_info *ra = &priv->ra_info;
u8 *qc = ieee80211_get_qos_ctl(hdr);
u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
- u32 rate;
- u16 rate_flags = tx_info->control.rates[0].flags;
+ u32 rate = 0;
u16 seq_number;
- if (rate_flags & IEEE80211_TX_RC_MCS &&
- !ieee80211_is_mgmt(hdr->frame_control))
- rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0;
- else
- rate = tx_rate->hw_value;
-
seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
if (ieee80211_is_data(hdr->frame_control)) {
@@ -5377,10 +5485,10 @@ rtl8xxxu_fill_txdesc_v3(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
* rts_rate is zero if RTS/CTS or CTS to SELF are not enabled
*/
tx_desc->txdw4 |= cpu_to_le32(rts_rate << TXDESC32_RTS_RATE_SHIFT);
- if (ampdu_enable || (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
+ if (ampdu_enable || tx_info->control.use_rts) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_RTS_CTS_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
- } else if (rate_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+ } else if (tx_info->control.use_cts_prot) {
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_CTS_SELF_ENABLE);
tx_desc->txdw4 |= cpu_to_le32(TXDESC32_HW_RTS_ENABLE);
}
@@ -5404,8 +5512,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
struct device *dev = &priv->udev->dev;
u32 queue, rts_rate;
u16 pktlen = skb->len;
- u16 rate_flag = tx_info->control.rates[0].flags;
int tx_desc_size = priv->fops->tx_desc_size;
+ u8 macid;
int ret;
bool ampdu_enable, sgi = false, short_preamble = false;
@@ -5444,8 +5552,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
tx_desc->pkt_size = cpu_to_le16(pktlen);
tx_desc->pkt_offset = tx_desc_size;
- tx_desc->txdw0 =
- TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
+ /* These bits mean different things to the RTL8192F. */
+ if (priv->rtl_chip != RTL8192F)
+ tx_desc->txdw0 =
+ TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT;
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
@@ -5488,31 +5598,34 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
}
}
- if (rate_flag & IEEE80211_TX_RC_SHORT_GI ||
- (ieee80211_is_data_qos(hdr->frame_control) &&
- sta && sta->deflink.ht_cap.cap &
- (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)))
+ if (ieee80211_is_data_qos(hdr->frame_control) &&
+ sta && sta->deflink.ht_cap.cap &
+ (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))
sgi = true;
- if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ||
- (sta && vif && vif->bss_conf.use_short_preamble))
+ if (sta && vif && vif->bss_conf.use_short_preamble)
short_preamble = true;
- if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS)
- rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
- else if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT)
- rts_rate = ieee80211_get_rts_cts_rate(hw, tx_info)->hw_value;
+ if (skb->len > hw->wiphy->rts_threshold)
+ tx_info->control.use_rts = true;
+
+ if (sta && vif && vif->bss_conf.use_cts_prot)
+ tx_info->control.use_cts_prot = true;
+
+ if (ampdu_enable || tx_info->control.use_rts ||
+ tx_info->control.use_cts_prot)
+ rts_rate = DESC_RATE_24M;
else
rts_rate = 0;
-
+ macid = rtl8xxxu_get_macid(priv, sta);
priv->fops->fill_txdesc(hw, hdr, tx_info, tx_desc, sgi, short_preamble,
- ampdu_enable, rts_rate);
+ ampdu_enable, rts_rate, macid);
rtl8xxxu_calc_tx_desc_csum(tx_desc);
/* avoid zero checksum make tx hang */
- if (priv->rtl_chip == RTL8710B)
+ if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F)
tx_desc->csum = ~tx_desc->csum;
usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue],
@@ -5530,6 +5643,55 @@ error:
dev_kfree_skb(skb);
}
+static void rtl8xxxu_send_beacon_frame(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct rtl8xxxu_priv *priv = hw->priv;
+ struct sk_buff *skb = ieee80211_beacon_get(hw, vif, 0);
+ struct device *dev = &priv->udev->dev;
+ int retry;
+ u8 val8;
+
+ /* BCN_VALID, write 1 to clear, cleared by SW */
+ val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
+ val8 |= BIT_BCN_VALID >> 16;
+ rtl8xxxu_write8(priv, REG_TDECTRL + 2, val8);
+
+ /* SW_BCN_SEL - Port0 */
+ val8 = rtl8xxxu_read8(priv, REG_DWBCN1_CTRL_8723B + 2);
+ val8 &= ~(BIT_SW_BCN_SEL >> 16);
+ rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B + 2, val8);
+
+ if (skb)
+ rtl8xxxu_tx(hw, NULL, skb);
+
+ retry = 100;
+ do {
+ val8 = rtl8xxxu_read8(priv, REG_TDECTRL + 2);
+ if (val8 & (BIT_BCN_VALID >> 16))
+ break;
+ usleep_range(10, 20);
+ } while (--retry);
+
+ if (!retry)
+ dev_err(dev, "%s: Failed to read beacon valid bit\n", __func__);
+}
+
+static void rtl8xxxu_update_beacon_work_callback(struct work_struct *work)
+{
+ struct rtl8xxxu_priv *priv =
+ container_of(work, struct rtl8xxxu_priv, update_beacon_work);
+ struct ieee80211_hw *hw = priv->hw;
+ struct ieee80211_vif *vif = priv->vif;
+
+ if (!vif) {
+ WARN_ONCE(true, "no vif to update beacon\n");
+ return;
+ }
+
+ rtl8xxxu_send_beacon_frame(hw, vif);
+}
+
void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
@@ -6198,61 +6360,98 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
{
struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- struct rtl8xxxu_rxdesc24 *rx_desc =
- (struct rtl8xxxu_rxdesc24 *)skb->data;
+ struct ieee80211_rx_status *rx_status;
+ struct rtl8xxxu_rxdesc24 *rx_desc;
struct rtl8723au_phy_stats *phy_stats;
- __le32 *_rx_desc_le = (__le32 *)skb->data;
- u32 *_rx_desc = (u32 *)skb->data;
+ struct sk_buff *next_skb = NULL;
+ __le32 *_rx_desc_le;
+ u32 *_rx_desc;
int drvinfo_sz, desc_shift;
- int i;
+ int i, pkt_len, urb_len, pkt_offset;
- for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++)
- _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]);
+ urb_len = skb->len;
- memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+ if (urb_len < sizeof(struct rtl8xxxu_rxdesc24)) {
+ kfree_skb(skb);
+ return RX_TYPE_ERROR;
+ }
- skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24));
+ do {
+ rx_desc = (struct rtl8xxxu_rxdesc24 *)skb->data;
+ _rx_desc_le = (__le32 *)skb->data;
+ _rx_desc = (u32 *)skb->data;
- phy_stats = (struct rtl8723au_phy_stats *)skb->data;
+ for (i = 0; i < (sizeof(struct rtl8xxxu_rxdesc24) / sizeof(u32)); i++)
+ _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]);
- drvinfo_sz = rx_desc->drvinfo_sz * 8;
- desc_shift = rx_desc->shift;
- skb_pull(skb, drvinfo_sz + desc_shift);
+ pkt_len = rx_desc->pktlen;
- if (rx_desc->rpt_sel) {
- struct device *dev = &priv->udev->dev;
- dev_dbg(dev, "%s: C2H packet\n", __func__);
- rtl8723bu_handle_c2h(priv, skb);
- return RX_TYPE_C2H;
- }
+ drvinfo_sz = rx_desc->drvinfo_sz * 8;
+ desc_shift = rx_desc->shift;
+ pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift +
+ sizeof(struct rtl8xxxu_rxdesc24), 8);
+
+ /*
+ * Only clone the skb if there's enough data at the end to
+ * at least cover the rx descriptor
+ */
+ if (urb_len >= (pkt_offset + sizeof(struct rtl8xxxu_rxdesc24)))
+ next_skb = skb_clone(skb, GFP_ATOMIC);
- if (rx_desc->phy_stats)
- priv->fops->parse_phystats(priv, rx_status, phy_stats,
- rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data,
- rx_desc->crc32 || rx_desc->icverr);
+ rx_status = IEEE80211_SKB_RXCB(skb);
+ memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
- rx_status->mactime = rx_desc->tsfl;
- rx_status->flag |= RX_FLAG_MACTIME_START;
+ skb_pull(skb, sizeof(struct rtl8xxxu_rxdesc24));
- if (!rx_desc->swdec)
- rx_status->flag |= RX_FLAG_DECRYPTED;
- if (rx_desc->crc32)
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
- if (rx_desc->bw)
- rx_status->bw = RATE_INFO_BW_40;
+ phy_stats = (struct rtl8723au_phy_stats *)skb->data;
- if (rx_desc->rxmcs >= DESC_RATE_MCS0) {
- rx_status->encoding = RX_ENC_HT;
- rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
- } else {
- rx_status->rate_idx = rx_desc->rxmcs;
- }
+ skb_pull(skb, drvinfo_sz + desc_shift);
- rx_status->freq = hw->conf.chandef.chan->center_freq;
- rx_status->band = hw->conf.chandef.chan->band;
+ skb_trim(skb, pkt_len);
+
+ if (rx_desc->rpt_sel) {
+ struct device *dev = &priv->udev->dev;
+ dev_dbg(dev, "%s: C2H packet\n", __func__);
+ rtl8723bu_handle_c2h(priv, skb);
+ } else {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (rx_desc->phy_stats)
+ priv->fops->parse_phystats(priv, rx_status, phy_stats,
+ rx_desc->rxmcs, hdr,
+ rx_desc->crc32 || rx_desc->icverr);
+
+ rx_status->mactime = rx_desc->tsfl;
+ rx_status->flag |= RX_FLAG_MACTIME_START;
+
+ if (!rx_desc->swdec)
+ rx_status->flag |= RX_FLAG_DECRYPTED;
+ if (rx_desc->crc32)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (rx_desc->bw)
+ rx_status->bw = RATE_INFO_BW_40;
+
+ if (rx_desc->rxmcs >= DESC_RATE_MCS0) {
+ rx_status->encoding = RX_ENC_HT;
+ rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0;
+ } else {
+ rx_status->rate_idx = rx_desc->rxmcs;
+ }
+
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+
+ ieee80211_rx_irqsafe(hw, skb);
+ }
+
+ skb = next_skb;
+ if (skb)
+ skb_pull(next_skb, pkt_offset);
+
+ urb_len -= pkt_offset;
+ next_skb = NULL;
+ } while (skb && urb_len >= sizeof(struct rtl8xxxu_rxdesc24));
- ieee80211_rx_irqsafe(hw, skb);
return RX_TYPE_DATA_PKT;
}
@@ -6282,7 +6481,6 @@ static void rtl8xxxu_rx_complete(struct urb *urb)
cleanup:
usb_free_urb(urb);
dev_kfree_skb(skb);
- return;
}
static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv,
@@ -6372,12 +6570,13 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
int ret;
u8 val8;
+ if (!priv->vif)
+ priv->vif = vif;
+ else
+ return -EOPNOTSUPP;
+
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (!priv->vif)
- priv->vif = vif;
- else
- return -EOPNOTSUPP;
rtl8xxxu_stop_tx_beacon(priv);
val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
@@ -6386,11 +6585,33 @@ static int rtl8xxxu_add_interface(struct ieee80211_hw *hw,
rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
ret = 0;
break;
+ case NL80211_IFTYPE_AP:
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL,
+ BEACON_DISABLE_TSF_UPDATE | BEACON_CTRL_MBSSID);
+ rtl8xxxu_write8(priv, REG_ATIMWND, 0x0c); /* 12ms */
+ rtl8xxxu_write16(priv, REG_TSFTR_SYN_OFFSET, 0x7fff); /* ~32ms */
+ rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, DUAL_TSF_RESET_TSF0);
+
+ /* enable BCN0 function */
+ rtl8xxxu_write8(priv, REG_BEACON_CTRL,
+ BEACON_DISABLE_TSF_UPDATE |
+ BEACON_FUNCTION_ENABLE | BEACON_CTRL_MBSSID |
+ BEACON_CTRL_TX_BEACON_RPT);
+
+ /* select BCN on port 0 */
+ val8 = rtl8xxxu_read8(priv, REG_CCK_CHECK);
+ val8 &= ~BIT_BCN_PORT_SEL;
+ rtl8xxxu_write8(priv, REG_CCK_CHECK, val8);
+
+ ret = 0;
+ break;
default:
ret = -EOPNOTSUPP;
}
rtl8xxxu_set_linktype(priv, vif->type);
+ ether_addr_copy(priv->mac_addr, vif->addr);
+ rtl8xxxu_set_mac(priv);
return ret;
}
@@ -6521,22 +6742,22 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
*/
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
- rcr &= ~RCR_CHECK_BSSID_BEACON;
+ rcr &= ~(RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH);
else
- rcr |= RCR_CHECK_BSSID_BEACON;
+ rcr |= RCR_CHECK_BSSID_BEACON | RCR_CHECK_BSSID_MATCH;
+
+ if (priv->vif && priv->vif->type == NL80211_IFTYPE_AP)
+ rcr &= ~RCR_CHECK_BSSID_MATCH;
if (*total_flags & FIF_CONTROL)
rcr |= RCR_ACCEPT_CTRL_FRAME;
else
rcr &= ~RCR_ACCEPT_CTRL_FRAME;
- if (*total_flags & FIF_OTHER_BSS) {
+ if (*total_flags & FIF_OTHER_BSS)
rcr |= RCR_ACCEPT_AP;
- rcr &= ~RCR_CHECK_BSSID_MATCH;
- } else {
+ else
rcr &= ~RCR_ACCEPT_AP;
- rcr |= RCR_CHECK_BSSID_MATCH;
- }
if (*total_flags & FIF_PSPOLL)
rcr |= RCR_ACCEPT_PM;
@@ -6557,7 +6778,7 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts)
{
- if (rts > 2347)
+ if (rts > 2347 && rts != (u32)-1)
return -EINVAL;
return 0;
@@ -6706,7 +6927,8 @@ static u8 rtl8xxxu_signal_to_snr(int signal)
}
static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
- int signal, struct ieee80211_sta *sta)
+ int signal, struct ieee80211_sta *sta,
+ bool force)
{
struct ieee80211_hw *hw = priv->hw;
u16 wireless_mode;
@@ -6714,6 +6936,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
u8 txbw_40mhz;
u8 snr, snr_thresh_high, snr_thresh_low;
u8 go_up_gap = 5;
+ u8 macid = rtl8xxxu_get_macid(priv, sta);
rssi_level = priv->rssi_level;
snr = rtl8xxxu_signal_to_snr(signal);
@@ -6740,7 +6963,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
else
rssi_level = RTL8XXXU_RATR_STA_LOW;
- if (rssi_level != priv->rssi_level) {
+ if (rssi_level != priv->rssi_level || force) {
int sgi = 0;
u32 rate_bitmap = 0;
@@ -6833,7 +7056,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
}
priv->rssi_level = rssi_level;
- priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz);
+ priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz, macid);
}
}
@@ -6956,7 +7179,7 @@ static void rtl8xxxu_watchdog_callback(struct work_struct *work)
if (priv->fops->set_crystal_cap)
rtl8xxxu_track_cfo(priv);
- rtl8xxxu_refresh_rate_mask(priv, signal, sta);
+ rtl8xxxu_refresh_rate_mask(priv, signal, sta, false);
}
out:
@@ -7087,6 +7310,38 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw)
rtl8xxxu_free_tx_resources(priv);
}
+static int rtl8xxxu_sta_add(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ sta_info->macid = rtl8xxxu_acquire_macid(priv);
+ if (sta_info->macid >= RTL8XXXU_MAX_MAC_ID_NUM)
+ return -ENOSPC;
+
+ rtl8xxxu_refresh_rate_mask(priv, 0, sta, true);
+ priv->fops->report_connect(priv, sta_info->macid, H2C_MACID_ROLE_STA, true);
+ }
+
+ return 0;
+}
+
+static int rtl8xxxu_sta_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rtl8xxxu_sta_info *sta_info = (struct rtl8xxxu_sta_info *)sta->drv_priv;
+ struct rtl8xxxu_priv *priv = hw->priv;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ rtl8xxxu_release_macid(priv, sta_info->macid);
+
+ return 0;
+}
+
static const struct ieee80211_ops rtl8xxxu_ops = {
.tx = rtl8xxxu_tx,
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
@@ -7095,6 +7350,7 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
.config = rtl8xxxu_config,
.conf_tx = rtl8xxxu_conf_tx,
.bss_info_changed = rtl8xxxu_bss_info_changed,
+ .start_ap = rtl8xxxu_start_ap,
.configure_filter = rtl8xxxu_configure_filter,
.set_rts_threshold = rtl8xxxu_set_rts_threshold,
.start = rtl8xxxu_start,
@@ -7105,6 +7361,9 @@ static const struct ieee80211_ops rtl8xxxu_ops = {
.ampdu_action = rtl8xxxu_ampdu_action,
.sta_statistics = rtl8xxxu_sta_statistics,
.get_antenna = rtl8xxxu_get_antenna,
+ .set_tim = rtl8xxxu_set_tim,
+ .sta_add = rtl8xxxu_sta_add,
+ .sta_remove = rtl8xxxu_sta_remove,
};
static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv,
@@ -7240,6 +7499,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
case 0xf179:
case 0x8179:
case 0xb711:
+ case 0xf192:
untested = 0;
break;
}
@@ -7264,6 +7524,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
if (id->idProduct == 0x0109)
untested = 0;
break;
+ case 0x0b05:
+ if (id->idProduct == 0x18f1)
+ untested = 0;
+ break;
default:
break;
}
@@ -7296,6 +7560,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
spin_lock_init(&priv->rx_urb_lock);
INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
+ INIT_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_callback);
skb_queue_head_init(&priv->c2hcmd_queue);
usb_set_intfdata(interface, hw);
@@ -7347,7 +7612,11 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
hw->wiphy->max_scan_ssids = 1;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ if (priv->fops->max_macid_num)
+ hw->wiphy->max_ap_assoc_sta = priv->fops->max_macid_num - 1;
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ if (priv->fops->supports_ap)
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
hw->queues = 4;
sband = &rtl8xxxu_supported_band;
@@ -7525,6 +7794,16 @@ static const struct usb_device_id dev_table[] = {
/* TOTOLINK N150UA V5 / N150UA-B */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8710bu_fops},
+/* Comfast CF-826F */
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf192, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+/* Asus USB-N13 rev C1 */
+{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f1, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb722, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192fu_fops},
#ifdef CONFIG_RTL8XXXU_UNTESTED
/* Still supported by rtlwifi */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
index 4dffbab494c3..920ee50e2115 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h
@@ -67,6 +67,7 @@
#define REG_SPS0_CTRL 0x0011
#define REG_SPS_OCP_CFG 0x0018
#define REG_8192E_LDOV12_CTRL 0x0014
+#define REG_SYS_SWR_CTRL2 0x0014
#define REG_RSV_CTRL 0x001c
#define RSV_CTRL_WLOCK_1C BIT(5)
#define RSV_CTRL_DIS_PRST BIT(6)
@@ -215,6 +216,8 @@
#define REG_HMBOX_EXT_2 0x008c
#define REG_HMBOX_EXT_3 0x008e
+#define REG_RSVD_1 0x0097
+
/* Interrupt registers for 8192e/8723bu/8812 */
#define REG_HIMR0 0x00b0
#define IMR0_TXCCK BIT(30) /* TXRPT interrupt when CCX bit
@@ -283,6 +286,7 @@
#define REG_BIST_SCAN 0x00d0
#define REG_BIST_RPT 0x00d4
#define REG_BIST_ROM_RPT 0x00d8
+#define REG_RSVD_4 0x00dc
#define REG_USB_SIE_INTF 0x00e0
#define REG_PCIE_MIO_INTF 0x00e4
#define REG_PCIE_MIO_INTD 0x00e8
@@ -390,6 +394,12 @@
#define TRXDMA_CTRL_BKQ_SHIFT 10
#define TRXDMA_CTRL_MGQ_SHIFT 12
#define TRXDMA_CTRL_HIQ_SHIFT 14
+#define TRXDMA_CTRL_VOQ_SHIFT_8192F 4
+#define TRXDMA_CTRL_VIQ_SHIFT_8192F 7
+#define TRXDMA_CTRL_BEQ_SHIFT_8192F 10
+#define TRXDMA_CTRL_BKQ_SHIFT_8192F 13
+#define TRXDMA_CTRL_MGQ_SHIFT_8192F 16
+#define TRXDMA_CTRL_HIQ_SHIFT_8192F 19
#define TRXDMA_QUEUE_LOW 1
#define TRXDMA_QUEUE_NORMAL 2
#define TRXDMA_QUEUE_HIGH 3
@@ -439,7 +449,7 @@
#define LLT_OP_READ (0x2 << 30)
#define LLT_OP_MASK (0x3 << 30)
-#define REG_BB_ACCEESS_CTRL 0x01e8
+#define REG_BB_ACCESS_CTRL 0x01e8
#define REG_BB_ACCESS_DATA 0x01ec
#define REG_HMBOX_EXT0_8723B 0x01f0
@@ -456,6 +466,7 @@
#define REG_FIFOPAGE 0x0204
#define REG_TDECTRL 0x0208
+#define BIT_BCN_VALID BIT(16)
#define REG_DWBCN0_CTRL_8188F REG_TDECTRL
@@ -470,6 +481,7 @@
#define AUTO_LLT_INIT_LLT BIT(16)
#define REG_DWBCN1_CTRL_8723B 0x0228
+#define BIT_SW_BCN_SEL BIT(20)
/* 0x0280 ~ 0x02FF RXDMA Configuration */
#define REG_RXDMA_AGG_PG_TH 0x0280 /* 0-7 : USB DMA size bits
@@ -516,6 +528,7 @@
#define REG_FWHW_TXQ_CTRL 0x0420
#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7)
#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12)
+#define EN_BCNQ_DL BIT(22)
#define REG_HWSEQ_CTRL 0x0423
#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
@@ -572,6 +585,8 @@
#define REG_ARFR1 0x0448
#define REG_ARFR2 0x044c
#define REG_ARFR3 0x0450
+#define REG_CCK_CHECK 0x0454
+#define BIT_BCN_PORT_SEL BIT(5)
#define REG_AMPDU_MAX_TIME_8723B 0x0456
#define REG_AGGLEN_LMT 0x0458
#define REG_AMPDU_MIN_SPACE 0x045c
@@ -968,12 +983,18 @@
#define FPGA1_TX_OFDM_TXSC_MASK 0x30000000
#define REG_ANT_MAPPING1 0x0914
+#define REG_RFE_OPT 0x0920
#define REG_DPDT_CTRL 0x092c /* 8723BU */
#define REG_RFE_CTRL_ANTA_SRC 0x0930 /* 8723BU */
+#define REG_RFE_CTRL_ANT_SRC1 0x0934
+#define REG_RFE_CTRL_ANT_SRC2 0x0938
+#define REG_RFE_CTRL_ANT_SRC3 0x093c
#define REG_RFE_PATH_SELECT 0x0940 /* 8723BU */
#define REG_RFE_BUFFER 0x0944 /* 8723BU */
#define REG_S0S1_PATH_SWITCH 0x0948 /* 8723BU */
+#define REG_RX_DFIR_MOD_97F 0x0948
#define REG_OFDM_RX_DFIR 0x954
+#define REG_RFE_OPT62 0x0968
#define REG_CCK0_SYSTEM 0x0a00
#define CCK0_SIDEBAND BIT(4)
@@ -1033,6 +1054,8 @@
#define REG_OFDM0_FA_RSTC 0x0c0c
+#define REG_DOWNSAM_FACTOR 0x0c10
+
#define REG_OFDM0_XA_RX_AFE 0x0c10
#define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14
#define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c
@@ -1054,7 +1077,7 @@
#define REG_OFDM0_AGC_PARM1 0x0c70
-#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78
+#define REG_OFDM0_AGC_RSSI_TABLE 0x0c78
#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80
#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88
@@ -1069,6 +1092,8 @@
/* 8188eu */
#define REG_ANTDIV_PARA1 0x0ca4
+#define REG_RXIQB_EXT 0x0ca8
+
/* 8723bu */
#define REG_OFDM0_TX_PSDO_NOISE_WEIGHT 0x0ce4
@@ -1088,6 +1113,8 @@
#define REG_OFDM1_CSI_FIX_MASK1 0x0d40
#define REG_OFDM1_CSI_FIX_MASK2 0x0d44
+#define REG_ANAPWR1 0x0d94
+
#define REG_TX_AGC_A_RATE18_06 0x0e00
#define REG_TX_AGC_A_RATE54_24 0x0e04
#define REG_TX_AGC_A_CCK1_MCS32 0x0e08
@@ -1096,6 +1123,10 @@
#define REG_TX_AGC_A_MCS11_MCS08 0x0e18
#define REG_TX_AGC_A_MCS15_MCS12 0x0e1c
+#define REG_NP_ANTA 0x0e20
+
+#define REG_TAP_UPD_97F 0x0e24
+
#define REG_FPGA0_IQK 0x0e28
#define REG_TX_IQK_TONE_A 0x0e30
@@ -1124,19 +1155,23 @@
#define REG_RX_CCK 0x0e8c
#define REG_TX_POWER_BEFORE_IQK_A 0x0e94
+#define REG_IQK_RPT_TXA 0x0e98
#define REG_TX_POWER_AFTER_IQK_A 0x0e9c
#define REG_RX_POWER_BEFORE_IQK_A 0x0ea0
#define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4
#define REG_RX_POWER_AFTER_IQK_A 0x0ea8
+#define REG_IQK_RPT_RXA 0x0ea8
#define REG_RX_POWER_AFTER_IQK_A_2 0x0eac
#define REG_TX_POWER_BEFORE_IQK_B 0x0eb4
+#define REG_IQK_RPT_TXB 0x0eb8
#define REG_TX_POWER_AFTER_IQK_B 0x0ebc
#define REG_RX_POWER_BEFORE_IQK_B 0x0ec0
#define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4
#define REG_RX_POWER_AFTER_IQK_B 0x0ec8
+#define REG_IQK_RPT_RXB 0x0ec8
#define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc
#define REG_RX_OFDM 0x0ed0
@@ -1147,6 +1182,12 @@
#define REG_PMPD_ANAEN 0x0eec
#define REG_FW_START_ADDRESS 0x1000
+#define REG_FW_START_ADDRESS_8192F 0x4000
+
+#define REG_SW_GPIO_SHARE_CTRL_0 0x1038
+#define REG_SW_GPIO_SHARE_CTRL_1 0x103c
+#define REG_GPIO_A0 0x1050
+#define REG_GPIO_B0 0x105b
#define REG_USB_INFO 0xfe17
#define REG_USB_HIMR 0xfe38
@@ -1311,12 +1352,15 @@
/*
* NextGen regs: 8723BU
*/
+#define RF6052_REG_GAIN_P1 0x35
#define RF6052_REG_T_METER_8723B 0x42
#define RF6052_REG_UNKNOWN_43 0x43
#define RF6052_REG_UNKNOWN_55 0x55
-#define RF6052_REG_UNKNOWN_56 0x56
+#define RF6052_REG_PAD_TXG 0x56
+#define RF6052_REG_TXMOD 0x58
#define RF6052_REG_RXG_MIX_SWBW 0x87
#define RF6052_REG_S0S1 0xb0
-#define RF6052_REG_UNKNOWN_DF 0xdf
+#define RF6052_REG_GAIN_CCA 0xdf
#define RF6052_REG_UNKNOWN_ED 0xed
#define RF6052_REG_WE_LUT 0xef
+#define RF6052_REG_GAIN_CTRL 0xf5
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 9e7e98b55eff..807a53a97325 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -452,8 +452,7 @@ static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
/* <1> timer */
timer_setup(&rtlpriv->works.watchdog_timer,
rtl_watch_dog_timer_callback, 0);
- timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
- rtl_easy_concurrent_retrytimer_callback, 0);
+
/* <2> work queue */
rtlpriv->works.hw = hw;
rtlpriv->works.rtl_wq = wq;
@@ -1905,7 +1904,7 @@ EXPORT_SYMBOL(rtl_rx_ampdu_apply);
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
return;
@@ -1991,7 +1990,7 @@ void rtl_scan_list_expire(struct ieee80211_hw *hw)
void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
unsigned long flags;
@@ -2366,19 +2365,6 @@ static void rtl_c2hcmd_wq_callback(struct work_struct *work)
rtl_c2hcmd_launcher(hw, 1);
}
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t)
-{
- struct rtl_priv *rtlpriv =
- from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer);
- struct ieee80211_hw *hw = rtlpriv->hw;
- struct rtl_priv *buddy_priv = rtlpriv->buddy_priv;
-
- if (buddy_priv == NULL)
- return;
-
- rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
-}
-
/*********************************************************
*
* frame process functions
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index 0e4f8a8ae3a5..f081a9a90563 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(u8 tid);
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t);
extern struct rtl_global_var rtl_global_var;
void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 6f10727cdb94..4fb16f5f6f83 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1908,6 +1908,16 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
return true;
}
EXPORT_SYMBOL(rtl_cmd_send_packet);
+
+void rtl_init_sw_leds(struct ieee80211_hw *hw)
+{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+ rtlpriv->ledctl.sw_led0 = LED_PIN_LED0;
+ rtlpriv->ledctl.sw_led1 = LED_PIN_LED1;
+}
+EXPORT_SYMBOL(rtl_init_sw_leds);
+
const struct ieee80211_ops rtl_ops = {
.start = rtl_op_start,
.stop = rtl_op_stop,
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h
index 345161b47442..42c2d9e13bb8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.h
+++ b/drivers/net/wireless/realtek/rtlwifi/core.h
@@ -51,6 +51,8 @@ enum dm_dig_connect_e {
};
extern const struct ieee80211_ops rtl_ops;
+
+void rtl_init_sw_leds(struct ieee80211_hw *hw);
void rtl_fw_cb(const struct firmware *firmware, void *context);
void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context);
void rtl_addr_delay(u32 addr);
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index ca79f652fef3..9886e719739b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -482,11 +482,6 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
if (!rtlpriv->rtlhal.earlymode_enable)
return;
- if (rtlpriv->dm.supp_phymode_switch &&
- (rtlpriv->easy_concurrent_ctl.switch_in_process ||
- (rtlpriv->buddy_priv &&
- rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
- return;
/* we just use em for BE/BK/VI/VO */
for (tid = 7; tid >= 0; tid--) {
u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
@@ -2265,7 +2260,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
err = -ENODEV;
goto fail3;
}
- rtlpriv->cfg->ops->init_sw_leds(hw);
+ rtl_init_sw_leds(hw);
/*aspm */
rtl_pci_init_aspm(hw);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
index de61c9c0ddec..58b1a46066b5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c
@@ -803,17 +803,17 @@ static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
else
- rtl88ee_sw_led_off(hw, pled0);
+ rtl88ee_sw_led_off(hw, pin0);
}
static bool _rtl88ee_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
index 006b979da1c6..b57ba45902f9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl88ee_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -36,21 +28,20 @@ void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -73,34 +64,25 @@ void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl88ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl88ee_sw_led_on(hw, pled0);
+ rtl88ee_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl88ee_sw_led_off(hw, pled0);
+ rtl88ee_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
index 67d3dc389ba0..e5cc35d4c298 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl88ee_init_sw_leds(struct ieee80211_hw *hw);
-void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl88ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl88ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 02b77521b5cd..b77937fe2448 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -230,7 +230,6 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = {
.tx_polling = rtl88ee_tx_polling,
.enable_hw_sec = rtl88ee_enable_hw_security_config,
.set_key = rtl88ee_set_key,
- .init_sw_leds = rtl88ee_init_sw_leds,
.get_bbreg = rtl88e_phy_query_bb_reg,
.set_bbreg = rtl88e_phy_set_bb_reg,
.get_rfreg = rtl88e_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
index 6e4741e9483f..65ebe52883d3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c
@@ -674,7 +674,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index dc480323c9cb..049c4fe9eeed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -639,17 +639,17 @@ static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
else
- rtl92ce_sw_led_off(hw, pled0);
+ rtl92ce_sw_led_off(hw, pin0);
}
static bool _rtl92ce_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
index 57132278eb5c..9d3ffed13ba8 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c
@@ -6,25 +6,17 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ce_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -35,24 +27,22 @@ void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,34 +59,25 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_info("switch case %#x not processed\n", pled->ledpin);
+ pr_info("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92ce_sw_led_on(hw, pled0);
+ rtl92ce_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92ce_sw_led_off(hw, pled0);
+ rtl92ce_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
index 97ab1e00af5f..66dc28d62003 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl92ce_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92ce_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92ce_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index ed68c850f9a2..e452275d8789 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -207,7 +207,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
.tx_polling = rtl92ce_tx_polling,
.enable_hw_sec = rtl92ce_enable_hw_security_config,
.set_key = rtl92ce_set_key,
- .init_sw_leds = rtl92ce_init_sw_leds,
.get_bbreg = rtl92c_phy_query_bb_reg,
.set_bbreg = rtl92c_phy_set_bb_reg,
.set_rfreg = rtl92ce_phy_set_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
index 730c7e939bd2..5376bb34251f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c
@@ -527,7 +527,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
index 1488f52a2d2f..bfc07efd0eb0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c
@@ -6,27 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92cu_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-static void rtl92cu_deinit_led(struct rtl_led *pled)
-{
-}
-
-void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -37,22 +25,20 @@ void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,36 +55,13 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92cu_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92cu_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
-}
-
-void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led0);
- rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led1);
-}
-
-static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
- enum led_ctl_mode ledaction)
-{
}
void rtl92cu_led_control(struct ieee80211_hw *hw,
- enum led_ctl_mode ledaction)
+ enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -114,5 +77,4 @@ void rtl92cu_led_control(struct ieee80211_hw *hw,
return;
}
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction);
- _rtl92cu_sw_led_control(hw, ledaction);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
index 3fc1e7c8f78b..8175f8bddd6d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h
@@ -4,10 +4,8 @@
#ifndef __RTL92CU_LED_H__
#define __RTL92CU_LED_H__
-void rtl92cu_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw);
-void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index 876c14d46c2f..e6403d4c937c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
@@ -115,8 +115,6 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
.led_control = rtl92cu_led_control,
.enable_hw_sec = rtl92cu_enable_hw_security_config,
.set_key = rtl92c_set_key,
- .init_sw_leds = rtl92cu_init_sw_leds,
- .deinit_sw_leds = rtl92cu_deinit_sw_leds,
.get_bbreg = rtl92c_phy_query_bb_reg,
.set_bbreg = rtl92c_phy_set_bb_reg,
.get_rfreg = rtl92cu_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index ae3c4f97637e..b70767e72f3d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -394,7 +394,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
(struct rx_desc_92c *)rxdesc, p_drvinfo);
}
skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
bv = ieee80211_is_probe_resp(fc);
if (bv)
@@ -632,7 +632,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 fw_queue = QSLT_BEACON;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
__le32 *pdesc = (__le32 *)pdesc8;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
index df1e36fbc348..31a18bbface9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
@@ -595,16 +595,16 @@ static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
else
- rtl92de_sw_led_off(hw, pled0);
+ rtl92de_sw_led_off(hw, pin0);
}
static bool _rtl92de_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
index 93d1c6a610c3..4bd708570992 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ce_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -44,24 +36,22 @@ void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- REG_LEDCFG2, pled->ledpin);
+ REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -78,35 +68,25 @@ void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92de_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ce_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92de_sw_led_on(hw, pled0);
+ rtl92de_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92de_sw_led_off(hw, pled0);
+ rtl92de_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
index 7599c7e5ecc3..33e544ad6f99 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl92de_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92de_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92de_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index a74724c971b9..11f319c97124 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192de_hal_ops = {
.tx_polling = rtl92de_tx_polling,
.enable_hw_sec = rtl92de_enable_hw_security_config,
.set_key = rtl92de_set_key,
- .init_sw_leds = rtl92de_init_sw_leds,
.get_bbreg = rtl92d_phy_query_bb_reg,
.set_bbreg = rtl92d_phy_set_bb_reg,
.get_rfreg = rtl92d_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
index 807b66c16e11..c09c0c312665 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -665,7 +665,7 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 fw_queue = QSLT_BEACON;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
__le32 *pdesc = (__le32 *)pdesc8;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
index 47d8999e31c0..ebb7abd0c9ad 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
@@ -714,17 +714,17 @@ static void _rtl92ee_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
else
- rtl92ee_sw_led_off(hw, pled0);
+ rtl92ee_sw_led_off(hw, pin0);
}
static bool _rtl92ee_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
index fb4ea3a8481f..a9b5e3c884ee 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl92ee_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u32 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -39,21 +31,20 @@ void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -69,34 +60,25 @@ void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl92ee_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92ee_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl92ee_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92ee_sw_led_on(hw, pled0);
+ rtl92ee_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92ee_sw_led_off(hw, pled0);
+ rtl92ee_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
index 6d775e14846f..08b8ff328b63 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92E_LED_H__
#define __RTL92E_LED_H__
-void rtl92ee_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92ee_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92ee_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index 7a16563b3a5d..616a47d8d97a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -220,7 +220,6 @@ static struct rtl_hal_ops rtl8192ee_hal_ops = {
.tx_polling = rtl92ee_tx_polling,
.enable_hw_sec = rtl92ee_enable_hw_security_config,
.set_key = rtl92ee_set_key,
- .init_sw_leds = rtl92ee_init_sw_leds,
.get_bbreg = rtl92ee_phy_query_bb_reg,
.set_bbreg = rtl92ee_phy_set_bb_reg,
.get_rfreg = rtl92ee_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
index a8b5bf45b1bb..e5775b94f04e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
@@ -731,12 +731,12 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw)
/* After MACIO reset,we must refresh LED state. */
if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) ||
(ppsc->rfoff_reason == 0)) {
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
enum rf_pwrstate rfpwr_state_toset;
rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw);
if (rfpwr_state_toset == ERFON)
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
}
}
@@ -1302,7 +1302,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u8 u1btmp;
- if (rtlhal->driver_going2unload)
+ if (rtlhal->driver_is_goingto_unload)
rtl_write_byte(rtlpriv, 0x560, 0x0);
/* Power save for BB/RF */
@@ -1323,7 +1323,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
rtl_write_word(rtlpriv, CMDR, 0x57FC);
rtl_write_word(rtlpriv, CMDR, 0x0000);
- if (rtlhal->driver_going2unload) {
+ if (rtlhal->driver_is_goingto_unload) {
u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1));
u1btmp &= ~(BIT(0));
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp);
@@ -1345,7 +1345,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw)
/* Power save for MAC */
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS &&
- !rtlhal->driver_going2unload) {
+ !rtlhal->driver_is_goingto_unload) {
/* enable LED function */
rtl_write_byte(rtlpriv, 0x03, 0xF9);
/* SW/HW radio off or halt adapter!! For example S3/S4 */
@@ -1371,15 +1371,15 @@ static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpci->up_first_time)
return;
if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS)
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
else
- rtl92se_sw_led_off(hw, pled0);
+ rtl92se_sw_led_off(hw, pin0);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
index ecbf425f679f..db16a325c5e6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
@@ -6,33 +6,17 @@
#include "reg.h"
#include "led.h"
-static void _rtl92se_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl92se_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl92se_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
-}
-
-void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- LEDCFG, pled->ledpin);
+ LEDCFG, pin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -42,14 +26,12 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv;
u8 ledcfg;
@@ -58,11 +40,11 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
if (!rtlpriv || rtlpriv->max_fw_size)
return;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
- LEDCFG, pled->ledpin);
+ LEDCFG, pin);
ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -77,27 +59,25 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
}
static void _rtl92se_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl92se_sw_led_on(hw, pled0);
+ rtl92se_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl92se_sw_led_off(hw, pled0);
+ rtl92se_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
index c9e481a8d943..43fcc3c77bc1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h
@@ -4,9 +4,8 @@
#ifndef __REALTEK_PCI92SE_LED_H__
#define __REALTEK_PCI92SE_LED_H__
-void rtl92se_init_sw_leds(struct ieee80211_hw *hw);
-void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92se_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl92se_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index 6d352a3161b8..30bce381c3bb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -260,7 +260,6 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
.tx_polling = rtl92se_tx_polling,
.enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key,
- .init_sw_leds = rtl92se_init_sw_leds,
.get_bbreg = rtl92s_phy_query_bb_reg,
.set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
index 965d98b9b09f..d26d4c4314a3 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c
@@ -643,17 +643,17 @@ static void _rtl8723e_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
else
- rtl8723e_sw_led_off(hw, pled0);
+ rtl8723e_sw_led_off(hw, pin0);
}
static bool _rtl8712e_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
index 7fab02e01a8c..90d3f6ae82d5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8723e_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled, enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -36,24 +28,22 @@ void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -77,35 +67,25 @@ void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl8723e_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8723e_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8723e_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl8723e_sw_led_on(hw, pled0);
+ rtl8723e_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl8723e_sw_led_off(hw, pled0);
+ rtl8723e_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
index 9f85845d23cd..6db5290da806 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
-void rtl8723e_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723e_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8723e_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8723e_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 7828acb1de3f..c821436a1991 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -223,7 +223,6 @@ static struct rtl_hal_ops rtl8723e_hal_ops = {
.tx_polling = rtl8723e_tx_polling,
.enable_hw_sec = rtl8723e_enable_hw_security_config,
.set_key = rtl8723e_set_key,
- .init_sw_leds = rtl8723e_init_sw_leds,
.get_bbreg = rtl8723_phy_query_bb_reg,
.set_bbreg = rtl8723_phy_set_bb_reg,
.get_rfreg = rtl8723e_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
index 27fddbcade32..7f294e698994 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c
@@ -528,7 +528,7 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 fw_queue = QSLT_BEACON;
__le32 *pdesc = (__le32 *)pdesc8;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index 0ba3bbed6ed3..15575644551f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -793,17 +793,17 @@ static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
else
- rtl8723be_sw_led_off(hw, pled0);
+ rtl8723be_sw_led_off(hw, pin0);
}
static bool _rtl8723be_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
index 3954624ab314..462fe1d0262b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c
@@ -6,23 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8723be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled,
- enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -35,24 +27,22 @@ void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -76,35 +66,25 @@ void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
- pr_err("switch case %#x not processed\n",
- pled->ledpin);
+ pr_err("switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
-}
-
-void rtl8723be_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8723be_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8723be_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
- rtl8723be_sw_led_on(hw, pled0);
+ rtl8723be_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
- rtl8723be_sw_led_off(hw, pled0);
+ rtl8723be_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
index 8ac59374b632..3ca9277152f7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h
@@ -4,9 +4,8 @@
#ifndef __RTL8723BE_LED_H__
#define __RTL8723BE_LED_H__
-void rtl8723be_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8723be_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8723be_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8723be_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index d220e8955e37..43b611d5288d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -227,7 +227,6 @@ static struct rtl_hal_ops rtl8723be_hal_ops = {
.tx_polling = rtl8723be_tx_polling,
.enable_hw_sec = rtl8723be_enable_hw_security_config,
.set_key = rtl8723be_set_key,
- .init_sw_leds = rtl8723be_init_sw_leds,
.get_bbreg = rtl8723_phy_query_bb_reg,
.set_bbreg = rtl8723_phy_set_bb_reg,
.get_rfreg = rtl8723be_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index a7e3250957dc..3f8f6da33b12 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -869,7 +869,7 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
if (rtlpriv->rtlhal.up_first_time)
@@ -877,19 +877,19 @@ static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw)
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
else
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_off(hw, pled0);
+ rtl8812ae_sw_led_off(hw, pin0);
else
- rtl8821ae_sw_led_off(hw, pled0);
+ rtl8821ae_sw_led_off(hw, pin0);
}
static bool _rtl8821ae_init_mac(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
index 7d6fb134c10f..fb003f9ce1ac 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c
@@ -6,24 +6,15 @@
#include "reg.h"
#include "led.h"
-static void _rtl8821ae_init_led(struct ieee80211_hw *hw,
- struct rtl_led *pled,
- enum rtl_led_pin ledpin)
-{
- pled->hw = hw;
- pled->ledpin = ledpin;
- pled->ledon = false;
-}
-
-void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -38,19 +29,18 @@ void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = true;
}
-void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u16 ledreg = REG_LEDCFG1;
u8 ledcfg = 0;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_LED0:
ledreg = REG_LEDCFG1;
break;
@@ -66,27 +56,26 @@ void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
"In SwLedOn, LedAddr:%X LEDPIN=%d\n",
- ledreg, pled->ledpin);
+ ledreg, pin);
ledcfg = rtl_read_byte(rtlpriv, ledreg);
ledcfg |= BIT(5); /*Set 0x4c[21]*/
ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
/*Clear 0x4c[23:22] and 0x4c[19:16]*/
rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/
- pled->ledon = true;
}
-void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 ledcfg;
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
- "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin);
+ "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pin);
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
@@ -110,18 +99,17 @@ void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
break;
default:
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
- "switch case %#x not processed\n", pled->ledpin);
+ "switch case %#x not processed\n", pin);
break;
}
- pled->ledon = false;
}
-void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin)
{
u16 ledreg = REG_LEDCFG1;
struct rtl_priv *rtlpriv = rtl_priv(hw);
- switch (pled->ledpin) {
+ switch (pin) {
case LED_PIN_LED0:
ledreg = REG_LEDCFG1;
break;
@@ -137,7 +125,7 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD,
"In SwLedOff,LedAddr:%X LEDPIN=%d\n",
- ledreg, pled->ledpin);
+ ledreg, pin);
/*Open-drain arrangement for controlling the LED*/
if (rtlpriv->ledctl.led_opendrain) {
u8 ledcfg = rtl_read_byte(rtlpriv, ledreg);
@@ -152,23 +140,13 @@ void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
} else {
rtl_write_byte(rtlpriv, ledreg, 0x28);
}
-
- pled->ledon = false;
-}
-
-void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
-
- _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led0, LED_PIN_LED0);
- _rtl8821ae_init_led(hw, &rtlpriv->ledctl.sw_led1, LED_PIN_LED1);
}
static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_led *pled0 = &rtlpriv->ledctl.sw_led0;
+ enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
switch (ledaction) {
@@ -176,15 +154,15 @@ static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw,
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_on(hw, pled0);
+ rtl8812ae_sw_led_on(hw, pin0);
else
- rtl8821ae_sw_led_on(hw, pled0);
+ rtl8821ae_sw_led_on(hw, pin0);
break;
case LED_CTL_POWER_OFF:
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
- rtl8812ae_sw_led_off(hw, pled0);
+ rtl8812ae_sw_led_off(hw, pin0);
else
- rtl8821ae_sw_led_off(hw, pled0);
+ rtl8821ae_sw_led_off(hw, pin0);
break;
default:
break;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
index 249a37a8d9db..76d5c0b0e39e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h
@@ -4,11 +4,10 @@
#ifndef __RTL8821AE_LED_H__
#define __RTL8821AE_LED_H__
-void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw);
-void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
-void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
+void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, enum rtl_led_pin pin);
void rtl8821ae_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 950542a24e31..0bca542e103f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -269,7 +269,6 @@ static struct rtl_hal_ops rtl8821ae_hal_ops = {
.tx_polling = rtl8821ae_tx_polling,
.enable_hw_sec = rtl8821ae_enable_hw_security_config,
.set_key = rtl8821ae_set_key,
- .init_sw_leds = rtl8821ae_init_sw_leds,
.get_bbreg = rtl8821ae_phy_query_bb_reg,
.set_bbreg = rtl8821ae_phy_set_bb_reg,
.get_rfreg = rtl8821ae_phy_query_rf_reg,
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index a8eebafb9a7e..30bf2775a335 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -164,13 +164,17 @@ static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
u16 wvalue;
u16 index;
__le32 data;
+ int ret;
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)(addr&0x0000ffff);
data = cpu_to_le32(val);
- _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data,
- len);
+
+ ret = _usbctrl_vendorreq_async_write(udev, request, wvalue,
+ index, &data, len);
+ if (ret < 0)
+ dev_err(&udev->dev, "error %d writing at 0x%x\n", ret, addr);
}
static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
@@ -194,28 +198,6 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
_usb_write_async(to_usb_device(dev), addr, val, 4);
}
-static void _usb_writen_sync(struct rtl_priv *rtlpriv, u32 addr, void *data,
- u16 len)
-{
- struct device *dev = rtlpriv->io.dev;
- struct usb_device *udev = to_usb_device(dev);
- u8 request = REALTEK_USB_VENQT_CMD_REQ;
- u8 reqtype = REALTEK_USB_VENQT_WRITE;
- u16 wvalue;
- u16 index = REALTEK_USB_VENQT_CMD_IDX;
- int pipe = usb_sndctrlpipe(udev, 0); /* write_out */
- u8 *buffer;
-
- wvalue = (u16)(addr & 0x0000ffff);
- buffer = kmemdup(data, len, GFP_ATOMIC);
- if (!buffer)
- return;
- usb_control_msg(udev, pipe, request, reqtype, wvalue,
- index, buffer, len, 50);
-
- kfree(buffer);
-}
-
static void _rtl_usb_io_handler_init(struct device *dev,
struct ieee80211_hw *hw)
{
@@ -229,7 +211,6 @@ static void _rtl_usb_io_handler_init(struct device *dev,
rtlpriv->io.read8_sync = _usb_read8_sync;
rtlpriv->io.read16_sync = _usb_read16_sync;
rtlpriv->io.read32_sync = _usb_read32_sync;
- rtlpriv->io.writen_sync = _usb_writen_sync;
}
static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
@@ -433,7 +414,7 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
skb_pull(skb, RTL_RX_DESC_SIZE);
rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
if (!stats.crc) {
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -475,7 +456,7 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
skb_pull(skb, RTL_RX_DESC_SIZE);
rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
- hdr = (struct ieee80211_hdr *)(skb->data);
+ hdr = rtl_get_hdr(skb);
fc = hdr->frame_control;
if (!stats.crc) {
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -926,7 +907,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct rtl_tx_desc *pdesc = NULL;
struct rtl_tcb_desc tcb_desc;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
u8 *pda_addr = hdr->addr1;
@@ -961,7 +942,7 @@ static int rtl_usb_tx(struct ieee80211_hw *hw,
{
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+ struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
__le16 fc = hdr->frame_control;
u16 hw_queue;
@@ -1068,7 +1049,7 @@ int rtl_usb_probe(struct usb_interface *intf,
pr_err("Can't init_sw_vars\n");
goto error_out;
}
- rtlpriv->cfg->ops->init_sw_leds(hw);
+ rtl_init_sw_leds(hw);
err = ieee80211_register_hw(hw);
if (err) {
@@ -1117,7 +1098,6 @@ void rtl_usb_disconnect(struct usb_interface *intf)
rtl_usb_deinit(hw);
rtl_deinit_core(hw);
kfree(rtlpriv->usb_data);
- rtlpriv->cfg->ops->deinit_sw_leds(hw);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
usb_put_dev(rtlusb->udev);
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 082af216760f..2e7e04f91279 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -1070,18 +1070,10 @@ struct rtl_probe_rsp {
struct rtl_info_element info_element[];
} __packed;
-/*LED related.*/
-/*ledpin Identify how to implement this SW led.*/
-struct rtl_led {
- void *hw;
- enum rtl_led_pin ledpin;
- bool ledon;
-};
-
struct rtl_led_ctl {
bool led_opendrain;
- struct rtl_led sw_led0;
- struct rtl_led sw_led1;
+ enum rtl_led_pin sw_led0;
+ enum rtl_led_pin sw_led1;
};
struct rtl_qos_parameters {
@@ -1465,8 +1457,6 @@ struct rtl_io {
void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val);
void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val);
void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val);
- void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf,
- u16 len);
u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr);
u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr);
@@ -1673,8 +1663,6 @@ struct rtl_hal {
bool fw_clk_change_in_progress;
bool allow_sw_to_change_hwclc;
u8 fw_ps_state;
- /**/
- bool driver_going2unload;
/*AMPDU init min space*/
u8 minspace_cfg; /*For Min spacing configurations */
@@ -2289,8 +2277,6 @@ struct rtl_hal_ops {
void (*set_key)(struct ieee80211_hw *hw, u32 key_index,
u8 *macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all);
- void (*init_sw_leds)(struct ieee80211_hw *hw);
- void (*deinit_sw_leds)(struct ieee80211_hw *hw);
u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
u32 data);
@@ -2300,7 +2286,6 @@ struct rtl_hal_ops {
u32 regaddr, u32 bitmask, u32 data);
void (*linked_set_reg)(struct ieee80211_hw *hw);
void (*chk_switch_dmdp)(struct ieee80211_hw *hw);
- void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw);
void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw);
bool (*phy_rf6052_config)(struct ieee80211_hw *hw);
void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw,
@@ -2465,7 +2450,6 @@ struct rtl_works {
/*timer */
struct timer_list watchdog_timer;
- struct timer_list dualmac_easyconcurrent_retrytimer;
struct timer_list fw_clockoff_timer;
struct timer_list fast_antenna_training_timer;
/*task */
@@ -2498,14 +2482,6 @@ struct rtl_debug {
#define MIMO_PS_DYNAMIC 1
#define MIMO_PS_NOLIMIT 3
-struct rtl_dualmac_easy_concurrent_ctl {
- enum band_type currentbandtype_backfordmdp;
- bool close_bbandrf_for_dmsp;
- bool change_to_dmdp;
- bool change_to_dmsp;
- bool switch_in_process;
-};
-
struct rtl_dmsp_ctl {
bool activescan_for_slaveofdmsp;
bool scan_for_anothermac_fordmsp;
@@ -2746,7 +2722,6 @@ struct rtl_priv {
struct list_head list;
struct rtl_priv *buddy_priv;
struct rtl_global_var *glb_var;
- struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl;
struct rtl_dmsp_ctl dmsp_ctl;
struct rtl_locks locks;
struct rtl_works works;
diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 29eb2f8e0eb7..cffad1c01249 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -111,6 +111,17 @@ config RTW88_8723DE
802.11n PCIe wireless network adapter
+config RTW88_8723DS
+ tristate "Realtek 8723DS SDIO wireless network adapter"
+ depends on MMC
+ select RTW88_CORE
+ select RTW88_SDIO
+ select RTW88_8723D
+ help
+ Select this option will enable support for 8723DS chipset
+
+ 802.11n SDIO wireless network adapter
+
config RTW88_8723DU
tristate "Realtek 8723DU USB wireless network adapter"
depends on USB
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 82979b30ae8d..fd212c09d88a 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -50,6 +50,9 @@ rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o
rtw88_8723de-objs := rtw8723de.o
+obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o
+rtw88_8723ds-objs := rtw8723ds.o
+
obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o
rtw88_8723du-objs := rtw8723du.o
diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c
index fa3d73b333ba..f8ba133baff0 100644
--- a/drivers/net/wireless/realtek/rtw88/debug.c
+++ b/drivers/net/wireless/realtek/rtw88/debug.c
@@ -183,8 +183,8 @@ static int rtw_debugfs_copy_from_user(char tmp[], int size,
tmp_len = (count > size - 1 ? size - 1 : count);
- if (!buffer || copy_from_user(tmp, buffer, tmp_len))
- return count;
+ if (copy_from_user(tmp, buffer, tmp_len))
+ return -EFAULT;
tmp[tmp_len] = '\0';
@@ -201,13 +201,16 @@ static ssize_t rtw_debugfs_set_read_reg(struct file *filp,
char tmp[32 + 1];
u32 addr, len;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x", &addr, &len);
if (num != 2)
- return count;
+ return -EINVAL;
if (len != 1 && len != 2 && len != 4) {
rtw_warn(rtwdev, "read reg setting wrong len\n");
@@ -288,8 +291,11 @@ static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp,
char tmp[32 + 1];
u32 offset, page_num;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%d %d", &offset, &page_num);
@@ -314,8 +320,11 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp,
char tmp[32 + 1];
u32 input;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
num = kstrtoint(tmp, 0, &input);
@@ -338,14 +347,17 @@ static ssize_t rtw_debugfs_set_write_reg(struct file *filp,
char tmp[32 + 1];
u32 addr, val, len;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
/* write BB/MAC register */
num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
if (num != 3)
- return count;
+ return -EINVAL;
switch (len) {
case 1:
@@ -381,8 +393,11 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp,
char tmp[32 + 1];
u8 param[8];
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx",
&param[0], &param[1], &param[2], &param[3],
@@ -408,14 +423,17 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
char tmp[32 + 1];
u32 path, addr, mask, val;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val);
if (num != 4) {
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
- return count;
+ return -EINVAL;
}
mutex_lock(&rtwdev->mutex);
@@ -438,14 +456,17 @@ static ssize_t rtw_debugfs_set_rf_read(struct file *filp,
char tmp[32 + 1];
u32 path, addr, mask;
int num;
+ int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
+ if (ret)
+ return ret;
num = sscanf(tmp, "%x %x %x", &path, &addr, &mask);
if (num != 3) {
rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
- return count;
+ return -EINVAL;
}
debugfs_priv->rf_path = path;
@@ -467,7 +488,9 @@ static ssize_t rtw_debugfs_set_fix_rate(struct file *filp,
char tmp[32 + 1];
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtou8(tmp, 0, &fix_rate);
if (ret) {
@@ -860,7 +883,9 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
bool enable;
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtobool(tmp, &enable);
if (ret) {
@@ -930,7 +955,9 @@ static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,
bool input;
int ret;
- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+ if (ret)
+ return ret;
ret = kstrtobool(tmp, &input);
if (ret)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 2a8ccc8a7f60..567bbedd8ee0 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -308,6 +308,57 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev)
}
EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr);
+static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev,
+ struct rtw_h2c_register *h2c)
+{
+ u32 box_reg, box_ex_reg;
+ u8 box_state, box;
+ int ret;
+
+ rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0,
+ h2c->w1);
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ box = rtwdev->h2c.last_box_num;
+ switch (box) {
+ case 0:
+ box_reg = REG_HMEBOX0;
+ box_ex_reg = REG_HMEBOX0_EX;
+ break;
+ case 1:
+ box_reg = REG_HMEBOX1;
+ box_ex_reg = REG_HMEBOX1_EX;
+ break;
+ case 2:
+ box_reg = REG_HMEBOX2;
+ box_ex_reg = REG_HMEBOX2_EX;
+ break;
+ case 3:
+ box_reg = REG_HMEBOX3;
+ box_ex_reg = REG_HMEBOX3_EX;
+ break;
+ default:
+ WARN(1, "invalid h2c mail box number\n");
+ return;
+ }
+
+ ret = read_poll_timeout_atomic(rtw_read8, box_state,
+ !((box_state >> box) & 0x1), 100, 3000,
+ false, rtwdev, REG_HMETFR);
+
+ if (ret) {
+ rtw_err(rtwdev, "failed to send h2c command\n");
+ return;
+ }
+
+ rtw_write32(rtwdev, box_ex_reg, h2c->w1);
+ rtw_write32(rtwdev, box_reg, h2c->w0);
+
+ if (++rtwdev->h2c.last_box_num >= 4)
+ rtwdev->h2c.last_box_num = 0;
+}
+
static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
u8 *h2c)
{
@@ -468,6 +519,23 @@ void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+{
+ struct rtw_h2c_register h2c = {};
+
+ if (rtwvif->net_type != RTW_NET_MGD_LINKED)
+ return;
+
+ /* Leave LPS before default port H2C so FW timer is correct */
+ rtw_leave_lps(rtwdev);
+
+ h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) |
+ u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) |
+ u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID);
+
+ rtw_fw_send_h2c_command_register(rtwdev, &h2c);
+}
+
void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
{
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h
index 397cbc3f6af6..43ccdf9965ac 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.h
+++ b/drivers/net/wireless/realtek/rtw88/fw.h
@@ -81,6 +81,17 @@ struct rtw_c2h_adaptivity {
u8 option;
} __packed;
+struct rtw_h2c_register {
+ u32 w0;
+ u32 w1;
+} __packed;
+
+#define RTW_H2C_W0_CMDID GENMASK(7, 0)
+
+/* H2C_CMD_DEFAULT_PORT command */
+#define RTW_H2C_DEFAULT_PORT_W0_PORTID GENMASK(15, 8)
+#define RTW_H2C_DEFAULT_PORT_W0_MACID GENMASK(23, 16)
+
struct rtw_h2c_cmd {
__le32 msg;
__le32 msg_ext;
@@ -530,6 +541,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
#define H2C_CMD_MEDIA_STATUS_RPT 0x01
#define H2C_CMD_SET_PWR_MODE 0x20
#define H2C_CMD_LPS_PG_INFO 0x2b
+#define H2C_CMD_DEFAULT_PORT 0x2c
#define H2C_CMD_RA_INFO 0x40
#define H2C_CMD_RSSI_MONITOR 0x42
#define H2C_CMD_BCN_FILTER_OFFLOAD_P0 0x56
@@ -801,6 +813,7 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
void rtw_fw_send_general_info(struct rtw_dev *rtwdev);
void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
+void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start);
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index a168f36c38ec..298663b03580 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -794,8 +794,10 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev,
wlan_cpu_enable(rtwdev, true);
- if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp))
- return -EBUSY;
+ if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) {
+ ret = -EBUSY;
+ goto dlfw_fail;
+ }
ret = download_firmware_validate(rtwdev);
if (ret)
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 144618bb94c8..a99b53d44267 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -43,7 +43,11 @@ static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
list_add_tail(&rtwtxq->list, &rtwdev->txqs);
spin_unlock_bh(&rtwdev->txq_lock);
- queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
+ /* ensure to dequeue EAPOL (4/4) at the right time */
+ if (txq->ac == IEEE80211_AC_VO)
+ __rtw_tx_work(rtwdev);
+ else
+ queue_work(rtwdev->tx_wq, &rtwdev->tx_work);
}
static int rtw_ops_start(struct ieee80211_hw *hw)
@@ -164,8 +168,10 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
- if (port >= RTW_PORT_NUM)
+ if (port >= RTW_PORT_NUM) {
+ mutex_unlock(&rtwdev->mutex);
return -EINVAL;
+ }
set_bit(port, rtwdev->hw_port);
rtwvif->port = port;
@@ -376,6 +382,7 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_fw_download_rsvd_page(rtwdev);
rtw_send_rsvd_page_h2c(rtwdev);
+ rtw_fw_default_port(rtwdev, rtwvif);
rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf);
@@ -447,6 +454,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw,
const struct rtw_chip_info *chip = rtwdev->chip;
mutex_lock(&rtwdev->mutex);
+ rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
rtwdev->ap_active = true;
rtw_store_op_chan(rtwdev, true);
chip->ops->phy_calibration(rtwdev);
@@ -462,6 +470,7 @@ static void rtw_ops_stop_ap(struct ieee80211_hw *hw,
struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex);
+ rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
rtwdev->ap_active = false;
if (!rtw_core_check_sta_active(rtwdev))
rtw_clear_op_chan(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 9447a3aae3b5..c2ddb4d382af 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -334,12 +334,15 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+ struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
int i;
si->mac_id = rtw_acquire_macid(rtwdev);
if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
return -ENOSPC;
+ if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0)
+ rtwvif->mac_id = si->mac_id;
si->rtwdev = rtwdev;
si->sta = sta;
si->vif = vif;
@@ -2180,10 +2183,12 @@ void rtw_core_deinit(struct rtw_dev *rtwdev)
release_firmware(wow_fw->firmware);
destroy_workqueue(rtwdev->tx_wq);
+ timer_delete_sync(&rtwdev->tx_report.purge_timer);
spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags);
skb_queue_purge(&rtwdev->tx_report.queue);
- skb_queue_purge(&rtwdev->coex.queue);
spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags);
+ skb_queue_purge(&rtwdev->coex.queue);
+ skb_queue_purge(&rtwdev->c2h_queue);
list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list,
build_list) {
@@ -2340,6 +2345,9 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
rtw_dbg(rtwdev, RTW_DBG_STATE, "AP port switch from %d -> %d\n",
rtwvif_ap->port, rtwvif_target->port);
+ /* Leave LPS so the value swapped are not in PS mode */
+ rtw_leave_lps(rtwdev);
+
reg1 = &rtwvif_ap->conf->net_type;
reg2 = &rtwvif_target->conf->net_type;
rtw_swap_reg_mask(rtwdev, reg1, reg2);
@@ -2358,6 +2366,8 @@ static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
swap(rtwvif_target->port, rtwvif_ap->port);
swap(rtwvif_target->conf, rtwvif_ap->conf);
+
+ rtw_fw_default_port(rtwdev, rtwvif_target);
}
void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
@@ -2403,10 +2413,13 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable)
if (!rtwdev->ap_active)
return;
- if (enable)
+ if (enable) {
rtw_write32_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
- else
+ rtw_write32_clr(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ } else {
rtw_write32_clr(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+ rtw_write32_set(rtwdev, REG_TXPAUSE, BIT_HIGH_QUEUE);
+ }
}
MODULE_AUTHOR("Realtek Corporation");
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 9e841f6991a9..f9dd2ab941c8 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -803,6 +803,7 @@ struct rtw_bf_info {
struct rtw_vif {
enum rtw_net_type net_type;
u16 aid;
+ u8 mac_id; /* for STA mode only */
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 port;
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 672ddde80816..2bfc0e822b8d 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -738,8 +738,9 @@ static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues,
u8 q;
for (q = 0; q < RTK_MAX_TX_QUEUE_NUM; q++) {
- /* It may be not necessary to flush BCN and H2C tx queues. */
- if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C)
+ /* Unnecessary to flush BCN, H2C and HI tx queues. */
+ if (q == RTW_TX_QUEUE_BCN || q == RTW_TX_QUEUE_H2C ||
+ q == RTW_TX_QUEUE_HI0)
continue;
if (pci_queues & BIT(q))
@@ -1827,5 +1828,5 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
EXPORT_SYMBOL(rtw_pci_shutdown);
MODULE_AUTHOR("Realtek Corporation");
-MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver");
+MODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c
index 53933fb38a33..43e80a3a8136 100644
--- a/drivers/net/wireless/realtek/rtw88/ps.c
+++ b/drivers/net/wireless/realtek/rtw88/ps.c
@@ -18,6 +18,7 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
if (ret)
rtw_err(rtwdev, "leave idle state failed\n");
+ rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
rtw_set_channel(rtwdev);
return ret;
@@ -63,8 +64,6 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
- rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
-
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 2a2ae2081f34..7c6c11d50ff3 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -378,6 +378,7 @@
#define BIT_SIFS_BK_EN BIT(12)
#define REG_TXPAUSE 0x0522
#define BIT_AC_QUEUE GENMASK(7, 0)
+#define BIT_HIGH_QUEUE BIT(5)
#define REG_RD_CTRL 0x0524
#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11)
#define BIT_DIS_TXOP_CFE BIT(10)
@@ -410,6 +411,7 @@
#define REG_TCR 0x0604
#define BIT_PWRMGT_HWDATA_EN BIT(7)
#define BIT_TCR_UPDATE_TIMIE BIT(5)
+#define BIT_TCR_UPDATE_HGQMD BIT(4)
#define REG_RCR 0x0608
#define BIT_APP_FCS BIT(31)
#define BIT_APP_MIC BIT(30)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 06e7454c9ca6..c575476a0020 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -216,6 +216,12 @@ static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
+static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse,
+ struct rtw8723d_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->s.mac_addr);
+}
+
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
@@ -248,6 +254,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
case RTW_HCI_TYPE_USB:
rtw8723du_efuse_parsing(efuse, map);
break;
+ case RTW_HCI_TYPE_SDIO:
+ rtw8723ds_efuse_parsing(efuse, map);
+ break;
default:
/* unsupported now */
return -ENOTSUPP;
@@ -1961,15 +1970,17 @@ static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
+ RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static struct rtw_chip_ops rtw8723d_ops = {
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index a356318a5c15..3642a2c7f80c 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -49,6 +49,11 @@ struct rtw8723du_efuse {
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
+struct rtw8723ds_efuse {
+ u8 res4[0x4a]; /* 0xd0 */
+ u8 mac_addr[ETH_ALEN]; /* 0x11a */
+};
+
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
@@ -80,6 +85,7 @@ struct rtw8723d_efuse {
union {
struct rtw8723de_efuse e;
struct rtw8723du_efuse u;
+ struct rtw8723ds_efuse s;
};
};
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
new file mode 100644
index 000000000000..e5b6960ba0a0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include "main.h"
+#include "rtw8723d.h"
+#include "sdio.h"
+
+static const struct sdio_device_id rtw_8723ds_id_table[] = {
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT),
+ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
+ },
+ {
+ SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
+ SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT),
+ .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table);
+
+static struct sdio_driver rtw_8723ds_driver = {
+ .name = "rtw_8723ds",
+ .probe = rtw_sdio_probe,
+ .remove = rtw_sdio_remove,
+ .id_table = rtw_8723ds_id_table,
+ .drv = {
+ .pm = &rtw_sdio_pm_ops,
+ .shutdown = rtw_sdio_shutdown,
+ }
+};
+module_sdio_driver(rtw_8723ds_driver);
+
+MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
index 06fce7c3adda..2c1fb2dabd40 100644
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
@@ -998,9 +998,9 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len)
static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
{
- u32 rx_len, total_rx_bytes = 0;
+ u32 rx_len, hisr, total_rx_bytes = 0;
- while (total_rx_bytes < SZ_64K) {
+ do {
if (rtw_chip_wcpu_11n(rtwdev))
rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN);
else
@@ -1012,7 +1012,25 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev)
rtw_sdio_rxfifo_recv(rtwdev, rx_len);
total_rx_bytes += rx_len;
- }
+
+ if (rtw_chip_wcpu_11n(rtwdev)) {
+ /* Stop if no more RX requests are pending, even if
+ * rx_len could be greater than zero in the next
+ * iteration. This is needed because the RX buffer may
+ * already contain data while either HW or FW are not
+ * done filling that buffer yet. Still reading the
+ * buffer can result in packets where
+ * rtw_rx_pkt_stat.pkt_len is zero or points beyond the
+ * end of the buffer.
+ */
+ hisr = rtw_read32(rtwdev, REG_SDIO_HISR);
+ } else {
+ /* RTW_WCPU_11AC chips have improved hardware or
+ * firmware and can use rx_len unconditionally.
+ */
+ hisr = REG_SDIO_HISR_RX_REQUEST;
+ }
+ } while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST);
}
static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func)
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index bb5c7492c98b..2821119dc930 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -34,43 +34,57 @@ void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
{
- __le32 *txdesc = (__le32 *)skb->data;
-
- SET_TX_DESC_TXPKTSIZE(txdesc, pkt_info->tx_pkt_size);
- SET_TX_DESC_OFFSET(txdesc, pkt_info->offset);
- SET_TX_DESC_PKT_OFFSET(txdesc, pkt_info->pkt_offset);
- SET_TX_DESC_QSEL(txdesc, pkt_info->qsel);
- SET_TX_DESC_BMC(txdesc, pkt_info->bmc);
- SET_TX_DESC_RATE_ID(txdesc, pkt_info->rate_id);
- SET_TX_DESC_DATARATE(txdesc, pkt_info->rate);
- SET_TX_DESC_DISDATAFB(txdesc, pkt_info->dis_rate_fallback);
- SET_TX_DESC_USE_RATE(txdesc, pkt_info->use_rate);
- SET_TX_DESC_SEC_TYPE(txdesc, pkt_info->sec_type);
- SET_TX_DESC_DATA_BW(txdesc, pkt_info->bw);
- SET_TX_DESC_SW_SEQ(txdesc, pkt_info->seq);
- SET_TX_DESC_MAX_AGG_NUM(txdesc, pkt_info->ampdu_factor);
- SET_TX_DESC_AMPDU_DENSITY(txdesc, pkt_info->ampdu_density);
- SET_TX_DESC_DATA_STBC(txdesc, pkt_info->stbc);
- SET_TX_DESC_DATA_LDPC(txdesc, pkt_info->ldpc);
- SET_TX_DESC_AGG_EN(txdesc, pkt_info->ampdu_en);
- SET_TX_DESC_LS(txdesc, pkt_info->ls);
- SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
- SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
- SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
- SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
+ bool more_data = false;
+
+ if (pkt_info->qsel == TX_DESC_QSEL_HIGH)
+ more_data = true;
+
+ tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) |
+ le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) |
+ le32_encode_bits(pkt_info->bmc, RTW_TX_DESC_W0_BMC) |
+ le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) |
+ le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ);
+
+ tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
+ le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
+ le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
+ le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
+ le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA);
+
+ tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) |
+ le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) |
+ le32_encode_bits(pkt_info->ampdu_density, RTW_TX_DESC_W2_AMPDU_DEN) |
+ le32_encode_bits(pkt_info->bt_null, RTW_TX_DESC_W2_BT_NULL);
+
+ tx_desc->w3 = le32_encode_bits(pkt_info->hw_ssn_sel, RTW_TX_DESC_W3_HW_SSN_SEL) |
+ le32_encode_bits(pkt_info->use_rate, RTW_TX_DESC_W3_USE_RATE) |
+ le32_encode_bits(pkt_info->dis_rate_fallback, RTW_TX_DESC_W3_DISDATAFB) |
+ le32_encode_bits(pkt_info->rts, RTW_TX_DESC_W3_USE_RTS) |
+ le32_encode_bits(pkt_info->nav_use_hdr, RTW_TX_DESC_W3_NAVUSEHDR) |
+ le32_encode_bits(pkt_info->ampdu_factor, RTW_TX_DESC_W3_MAX_AGG_NUM);
+
+ tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE);
+
+ tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) |
+ le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) |
+ le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) |
+ le32_encode_bits(pkt_info->stbc, RTW_TX_DESC_W5_DATA_STBC);
+
+ tx_desc->w6 = le32_encode_bits(pkt_info->sn, RTW_TX_DESC_W6_SW_DEFINE);
+
+ tx_desc->w8 = le32_encode_bits(pkt_info->en_hwseq, RTW_TX_DESC_W8_EN_HWSEQ);
+
+ tx_desc->w9 = le32_encode_bits(pkt_info->seq, RTW_TX_DESC_W9_SW_SEQ);
+
if (pkt_info->rts) {
- SET_TX_DESC_RTSRATE(txdesc, DESC_RATE24M);
- SET_TX_DESC_DATA_RTS_SHORT(txdesc, 1);
- }
- SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
- SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
- SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
- SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
- SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
- if (pkt_info->tim_offset) {
- SET_TX_DESC_TIM_EN(txdesc, 1);
- SET_TX_DESC_TIM_OFFSET(txdesc, pkt_info->tim_offset);
+ tx_desc->w4 |= le32_encode_bits(DESC_RATE24M, RTW_TX_DESC_W4_RTSRATE);
+ tx_desc->w5 |= le32_encode_bits(1, RTW_TX_DESC_W5_DATA_RTS_SHORT);
}
+
+ if (pkt_info->tim_offset)
+ tx_desc->w9 |= le32_encode_bits(1, RTW_TX_DESC_W9_TIM_EN) |
+ le32_encode_bits(pkt_info->tim_offset, RTW_TX_DESC_W9_TIM_OFFSET);
}
EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
@@ -635,9 +649,8 @@ static void rtw_txq_push(struct rtw_dev *rtwdev,
rcu_read_unlock();
}
-void rtw_tx_work(struct work_struct *w)
+void __rtw_tx_work(struct rtw_dev *rtwdev)
{
- struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
struct rtw_txq *rtwtxq, *tmp;
spin_lock_bh(&rtwdev->txq_lock);
@@ -658,6 +671,13 @@ void rtw_tx_work(struct work_struct *w)
spin_unlock_bh(&rtwdev->txq_lock);
}
+void rtw_tx_work(struct work_struct *w)
+{
+ struct rtw_dev *rtwdev = container_of(w, struct rtw_dev, tx_work);
+
+ __rtw_tx_work(rtwdev);
+}
+
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
{
struct rtw_txq *rtwtxq;
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 197d5868c8ad..324189606257 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -9,76 +9,53 @@
#define RTW_TX_PROBE_TIMEOUT msecs_to_jiffies(500)
-#define SET_TX_DESC_TXPKTSIZE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(15, 0))
-#define SET_TX_DESC_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, GENMASK(23, 16))
-#define SET_TX_DESC_PKT_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(28, 24))
-#define SET_TX_DESC_QSEL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(12, 8))
-#define SET_TX_DESC_BMC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(24))
-#define SET_TX_DESC_RATE_ID(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(20, 16))
-#define SET_TX_DESC_DATARATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(6, 0))
-#define SET_TX_DESC_DISDATAFB(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(10))
-#define SET_TX_DESC_USE_RATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(8))
-#define SET_TX_DESC_SEC_TYPE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x01, value, GENMASK(23, 22))
-#define SET_TX_DESC_DATA_BW(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(6, 5))
-#define SET_TX_DESC_SW_SEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12))
-#define SET_TX_DESC_TIM_EN(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, BIT(7))
-#define SET_TX_DESC_TIM_OFFSET(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(6, 0))
-#define SET_TX_DESC_MAX_AGG_NUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17))
-#define SET_TX_DESC_USE_RTS(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12))
-#define SET_TX_DESC_RTSRATE(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x04, value, GENMASK(28, 24))
-#define SET_TX_DESC_DATA_RTS_SHORT(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(12))
-#define SET_TX_DESC_AMPDU_DENSITY(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20))
-#define SET_TX_DESC_DATA_STBC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, GENMASK(9, 8))
-#define SET_TX_DESC_DATA_LDPC(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(7))
-#define SET_TX_DESC_AGG_EN(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(12))
-#define SET_TX_DESC_LS(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(26))
-#define SET_TX_DESC_DATA_SHORT(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x05, value, BIT(4))
-#define SET_TX_DESC_SPE_RPT(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19))
-#define SET_TX_DESC_SW_DEFINE(tx_desc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0))
-#define SET_TX_DESC_DISQSELSEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31))
-#define SET_TX_DESC_EN_HWSEQ(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
-#define SET_TX_DESC_HW_SSN_SEL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
-#define SET_TX_DESC_NAVUSEHDR(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
-#define SET_TX_DESC_BT_NULL(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
-#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0))
-#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \
- le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24))
-#define GET_TX_DESC_PKT_OFFSET(txdesc) \
- le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24))
-#define GET_TX_DESC_QSEL(txdesc) \
- le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8))
+struct rtw_tx_desc {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+ __le32 w9;
+} __packed;
+
+#define RTW_TX_DESC_W0_TXPKTSIZE GENMASK(15, 0)
+#define RTW_TX_DESC_W0_OFFSET GENMASK(23, 16)
+#define RTW_TX_DESC_W0_BMC BIT(24)
+#define RTW_TX_DESC_W0_LS BIT(26)
+#define RTW_TX_DESC_W0_DISQSELSEQ BIT(31)
+#define RTW_TX_DESC_W1_QSEL GENMASK(12, 8)
+#define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
+#define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)
+#define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24)
+#define RTW_TX_DESC_W1_MORE_DATA BIT(29)
+#define RTW_TX_DESC_W2_AGG_EN BIT(12)
+#define RTW_TX_DESC_W2_SPE_RPT BIT(19)
+#define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20)
+#define RTW_TX_DESC_W2_BT_NULL BIT(23)
+#define RTW_TX_DESC_W3_HW_SSN_SEL GENMASK(7, 6)
+#define RTW_TX_DESC_W3_USE_RATE BIT(8)
+#define RTW_TX_DESC_W3_DISDATAFB BIT(10)
+#define RTW_TX_DESC_W3_USE_RTS BIT(12)
+#define RTW_TX_DESC_W3_NAVUSEHDR BIT(15)
+#define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17)
+#define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0)
+#define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24)
+#define RTW_TX_DESC_W5_DATA_SHORT BIT(4)
+#define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5)
+#define RTW_TX_DESC_W5_DATA_LDPC BIT(7)
+#define RTW_TX_DESC_W5_DATA_STBC GENMASK(9, 8)
+#define RTW_TX_DESC_W5_DATA_RTS_SHORT BIT(12)
+#define RTW_TX_DESC_W6_SW_DEFINE GENMASK(11, 0)
+#define RTW_TX_DESC_W7_TXDESC_CHECKSUM GENMASK(15, 0)
+#define RTW_TX_DESC_W7_DMA_TXAGG_NUM GENMASK(31, 24)
+#define RTW_TX_DESC_W8_EN_HWSEQ BIT(15)
+#define RTW_TX_DESC_W9_SW_SEQ GENMASK(23, 12)
+#define RTW_TX_DESC_W9_TIM_EN BIT(7)
+#define RTW_TX_DESC_W9_TIM_OFFSET GENMASK(6, 0)
enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_TID0 = 0,
@@ -111,6 +88,7 @@ void rtw_tx(struct rtw_dev *rtwdev,
void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
void rtw_tx_work(struct work_struct *w);
+void __rtw_tx_work(struct rtw_dev *rtwdev);
void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
struct ieee80211_sta *sta,
@@ -139,13 +117,15 @@ void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
{
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+ le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
- SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+ le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
+ RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 44a5fafb9905..c279a500b4bd 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -24,11 +24,12 @@ struct rtw_usb_txcb {
static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
struct sk_buff *skb, int agg_num)
{
+ struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
struct rtw_dev *rtwdev = rtwusb->rtwdev;
struct rtw_tx_pkt_info pkt_info;
- SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num);
- pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data);
+ le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM);
+ pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET);
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
}
@@ -306,11 +307,13 @@ static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *s
static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
{
struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ struct rtw_tx_desc *tx_desc;
struct rtw_usb_txcb *txcb;
struct sk_buff *skb_head;
struct sk_buff *skb_iter;
int agg_num = 0;
unsigned int align_next = 0;
+ u8 qsel;
if (skb_queue_empty(list))
return false;
@@ -363,9 +366,10 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
queue:
skb_queue_tail(&txcb->tx_ack_queue, skb_head);
+ tx_desc = (struct rtw_tx_desc *)skb_head->data;
+ qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
- rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
- rtw_usb_write_port_tx_complete, txcb);
+ rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
return true;
}
@@ -465,6 +469,9 @@ static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb)
if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
qsel = TX_DESC_QSEL_MGMT;
+ else if (is_broadcast_ether_addr(hdr->addr1) ||
+ is_multicast_ether_addr(hdr->addr1))
+ qsel = TX_DESC_QSEL_HIGH;
else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
qsel = skb->priority;
else
@@ -535,7 +542,7 @@ static void rtw_usb_rx_handler(struct work_struct *work)
}
if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
- rtw_err(rtwdev, "failed to get rx_queue, overflow\n");
+ dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n");
dev_kfree_skb_any(skb);
continue;
}
@@ -837,7 +844,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
ret = rtw_core_init(rtwdev);
if (ret)
- goto err_release_hw;
+ goto err_free_rx_bufs;
ret = rtw_usb_intf_init(rtwdev, intf);
if (ret) {
@@ -883,6 +890,9 @@ err_destroy_usb:
err_deinit_core:
rtw_core_deinit(rtwdev);
+err_free_rx_bufs:
+ rtw_usb_free_rx_bufs(rtwusb);
+
err_release_hw:
ieee80211_free_hw(hw);
@@ -920,5 +930,5 @@ void rtw_usb_disconnect(struct usb_interface *intf)
EXPORT_SYMBOL(rtw_usb_disconnect);
MODULE_AUTHOR("Realtek Corporation");
-MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
+MODULE_DESCRIPTION("Realtek USB 802.11ac wireless driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig
index 2b20cf8bbf3a..90ffbab7cc4c 100644
--- a/drivers/net/wireless/realtek/rtw89/Kconfig
+++ b/drivers/net/wireless/realtek/rtw89/Kconfig
@@ -16,6 +16,9 @@ config RTW89_CORE
config RTW89_PCI
tristate
+config RTW89_8851B
+ tristate
+
config RTW89_8852A
tristate
@@ -25,6 +28,17 @@ config RTW89_8852B
config RTW89_8852C
tristate
+config RTW89_8851BE
+ tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter"
+ depends on PCI
+ select RTW89_CORE
+ select RTW89_PCI
+ select RTW89_8851B
+ help
+ Select this option will enable support for 8851BE chipset
+
+ 802.11ax PCIe wireless network (Wi-Fi 6) adapter
+
config RTW89_8852AE
tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter"
depends on PCI
diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile
index 2dc48fa10c6b..41940099af1b 100644
--- a/drivers/net/wireless/realtek/rtw89/Makefile
+++ b/drivers/net/wireless/realtek/rtw89/Makefile
@@ -13,10 +13,20 @@ rtw89_core-y += core.o \
coex.o \
ps.o \
chan.o \
- ser.o
+ ser.o \
+ acpi.o
rtw89_core-$(CONFIG_PM) += wow.o
+obj-$(CONFIG_RTW89_8851B) += rtw89_8851b.o
+rtw89_8851b-objs := rtw8851b.o \
+ rtw8851b_table.o \
+ rtw8851b_rfk.o \
+ rtw8851b_rfk_table.o
+
+obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o
+rtw89_8851be-objs := rtw8851be.o
+
obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
rtw89_8852a-objs := rtw8852a.o \
rtw8852a_table.o \
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c
new file mode 100644
index 000000000000..8aaf83a2a6b4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/acpi.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2021-2023 Realtek Corporation
+ */
+
+#include <linux/acpi.h>
+#include <linux/uuid.h>
+
+#include "acpi.h"
+#include "debug.h"
+
+static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
+ 0x82, 0xBD, 0xFE, 0x86,
+ 0x07, 0x80, 0x3A, 0xA7);
+
+static int rtw89_acpi_dsm_get(struct rtw89_dev *rtwdev, union acpi_object *obj,
+ u8 *value)
+{
+ switch (obj->type) {
+ case ACPI_TYPE_INTEGER:
+ *value = (u8)obj->integer.value;
+ break;
+ case ACPI_TYPE_BUFFER:
+ *value = obj->buffer.pointer[0];
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
+ "acpi dsm return unhandled type: %d\n", obj->type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
+ enum rtw89_acpi_dsm_func func, u8 *value)
+{
+ union acpi_object *obj;
+ int ret;
+
+ obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
+ 0, func, NULL);
+ if (!obj) {
+ rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
+ "acpi dsm fail to evaluate func: %d\n", func);
+ return -ENOENT;
+ }
+
+ ret = rtw89_acpi_dsm_get(rtwdev, obj, value);
+
+ ACPI_FREE(obj);
+ return ret;
+}
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h
new file mode 100644
index 000000000000..ed74d8ceb733
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/acpi.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2021-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_ACPI_H__
+#define __RTW89_ACPI_H__
+
+#include "core.h"
+
+enum rtw89_acpi_dsm_func {
+ RTW89_ACPI_DSM_FUNC_IDN_BAND_SUP = 2,
+ RTW89_ACPI_DSM_FUNC_6G_DIS = 3,
+ RTW89_ACPI_DSM_FUNC_6G_BP = 4,
+ RTW89_ACPI_DSM_FUNC_TAS_EN = 5,
+ RTW89_ACPI_DSM_FUNC_59G_EN = 6,
+};
+
+int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
+ enum rtw89_acpi_dsm_func func, u8 *value);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index acb3fac0c96d..bda0e1e99a8c 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -127,6 +127,13 @@ static const u32 cxtbl[] = {
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
/* firmware version must be in decreasing order for each chip */
+ {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
+ .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
+ .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
+ .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
+ .fwlrole = 1, .frptmap = 3, .fcxctrl = 1,
+ .info_buf = 1800, .max_role_num = 6,
+ },
{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
.fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
.fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
@@ -199,7 +206,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
struct rtw89_btc_btf_tlv {
u8 type;
u8 len;
- u8 val[1];
+ u8 val[];
} __packed;
enum btc_btf_set_report_en {
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index bad864d56bd5..69b181fa2966 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -77,6 +77,9 @@ static struct ieee80211_channel rtw89_channels_5ghz[] = {
RTW89_DEF_CHAN_5G(5785, 157),
RTW89_DEF_CHAN_5G(5805, 161),
RTW89_DEF_CHAN_5G_NO_HT40MINUS(5825, 165),
+ RTW89_DEF_CHAN_5G(5845, 169),
+ RTW89_DEF_CHAN_5G(5865, 173),
+ RTW89_DEF_CHAN_5G(5885, 177),
};
static struct ieee80211_channel rtw89_channels_6ghz[] = {
@@ -333,8 +336,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
sub_entity_idx = RTW89_SUB_ENTITY_0;
phy_idx = RTW89_PHY_0;
chan = rtw89_chan_get(rtwdev, sub_entity_idx);
- if (chip->ops->set_txpwr)
- chip->ops->set_txpwr(rtwdev, chan, phy_idx);
+ chip->ops->set_txpwr(rtwdev, chan, phy_idx);
}
void rtw89_set_channel(struct rtw89_dev *rtwdev)
@@ -370,7 +372,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev)
chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
- rtw89_core_set_chip_txpwr(rtwdev);
+ chip->ops->set_txpwr(rtwdev, &chan, phy_idx);
rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
@@ -1210,14 +1212,15 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev,
struct sk_buff *skb,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_rxinfo *rxinfo = (const struct rtw89_rxinfo *)skb->data;
bool rx_cnt_valid = false;
u8 plcp_size = 0;
u8 usr_num = 0;
u8 *phy_sts;
- rx_cnt_valid = RTW89_GET_RXINFO_RX_CNT_VLD(skb->data);
- plcp_size = RTW89_GET_RXINFO_PLCP_LEN(skb->data) << 3;
- usr_num = RTW89_GET_RXINFO_USR_NUM(skb->data);
+ rx_cnt_valid = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_RX_CNT_VLD);
+ plcp_size = le32_get_bits(rxinfo->w1, RTW89_RXINFO_W1_PLCP_LEN) << 3;
+ usr_num = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_USR_NUM);
if (usr_num > RTW89_PPDU_MAX_USR) {
rtw89_warn(rtwdev, "Invalid user number in mac info\n");
return -EINVAL;
@@ -1244,18 +1247,40 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data,
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data;
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
+ u8 ant_pos = U8_MAX;
+ u8 evm_pos = 0;
int i;
- if (rtwsta->mac_id == phy_ppdu->mac_id && phy_ppdu->to_self) {
- ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg);
+ if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self)
+ return;
+
+ if (hal->ant_diversity && hal->antenna_rx) {
+ ant_pos = __ffs(hal->antenna_rx);
+ evm_pos = ant_pos;
+ }
+
+ ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg);
+
+ if (ant_pos < ant_num) {
+ ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]);
+ } else {
for (i = 0; i < rtwdev->chip->rf_path_num; i++)
ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]);
}
+
+ if (phy_ppdu->ofdm.has) {
+ ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr);
+ ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min);
+ ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max);
+ }
}
#define VAR_LEN 0xff
#define VAR_LEN_UNIT 8
-static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr)
+static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr)
{
static const u8 physts_ie_len_tab[32] = {
16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN,
@@ -1265,45 +1290,58 @@ static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr)
u16 ie_len;
u8 ie;
- ie = RTW89_GET_PHY_STS_IE_TYPE(addr);
+ ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE);
if (physts_ie_len_tab[ie] != VAR_LEN)
ie_len = physts_ie_len_tab[ie];
else
- ie_len = RTW89_GET_PHY_STS_IE_LEN(addr) * VAR_LEN_UNIT;
+ ie_len = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_LEN) * VAR_LEN_UNIT;
return ie_len;
}
-static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr,
+static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_phy_sts_ie0 *ie = (const struct rtw89_phy_sts_ie0 *)iehdr;
s16 cfo;
+ u32 t;
- phy_ppdu->chan_idx = RTW89_GET_PHY_STS_IE01_CH_IDX(addr);
+ phy_ppdu->chan_idx = le32_get_bits(ie->w0, RTW89_PHY_STS_IE01_W0_CH_IDX);
if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6)
return;
if (!phy_ppdu->to_self)
return;
+ phy_ppdu->ofdm.avg_snr = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_AVG_SNR);
+ phy_ppdu->ofdm.evm_max = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MAX);
+ phy_ppdu->ofdm.evm_min = le32_get_bits(ie->w2, RTW89_PHY_STS_IE01_W2_EVM_MIN);
+ phy_ppdu->ofdm.has = true;
+
/* sign conversion for S(12,2) */
- if (rtwdev->chip->cfo_src_fd)
- cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_FD_CFO(addr), 11);
- else
- cfo = sign_extend32(RTW89_GET_PHY_STS_IE01_PREMB_CFO(addr), 11);
+ if (rtwdev->chip->cfo_src_fd) {
+ t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_FD_CFO);
+ cfo = sign_extend32(t, 11);
+ } else {
+ t = le32_get_bits(ie->w1, RTW89_PHY_STS_IE01_W1_PREMB_CFO);
+ cfo = sign_extend32(t, 11);
+ }
rtw89_phy_cfo_parse(rtwdev, cfo, phy_ppdu);
}
-static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr,
+static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev,
+ const struct rtw89_phy_sts_iehdr *iehdr,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
u8 ie;
- ie = RTW89_GET_PHY_STS_IE_TYPE(addr);
+ ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE);
+
switch (ie) {
case RTW89_PHYSTS_IE01_CMN_OFDM:
- rtw89_core_parse_phy_status_ie01(rtwdev, addr, phy_ppdu);
+ rtw89_core_parse_phy_status_ie01(rtwdev, iehdr, phy_ppdu);
break;
default:
break;
@@ -1314,28 +1352,30 @@ static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr,
static void rtw89_core_update_phy_ppdu(struct rtw89_rx_phy_ppdu *phy_ppdu)
{
+ const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf;
u8 *rssi = phy_ppdu->rssi;
- u8 *buf = phy_ppdu->buf;
- phy_ppdu->ie = RTW89_GET_PHY_STS_IE_MAP(buf);
- phy_ppdu->rssi_avg = RTW89_GET_PHY_STS_RSSI_AVG(buf);
- rssi[RF_PATH_A] = RTW89_GET_PHY_STS_RSSI_A(buf);
- rssi[RF_PATH_B] = RTW89_GET_PHY_STS_RSSI_B(buf);
- rssi[RF_PATH_C] = RTW89_GET_PHY_STS_RSSI_C(buf);
- rssi[RF_PATH_D] = RTW89_GET_PHY_STS_RSSI_D(buf);
+ phy_ppdu->ie = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_IE_MAP);
+ phy_ppdu->rssi_avg = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_RSSI_AVG);
+ rssi[RF_PATH_A] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_A);
+ rssi[RF_PATH_B] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_B);
+ rssi[RF_PATH_C] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_C);
+ rssi[RF_PATH_D] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_D);
}
static int rtw89_core_rx_process_phy_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
- if (RTW89_GET_PHY_STS_LEN(phy_ppdu->buf) << 3 != phy_ppdu->len) {
+ const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf;
+ u32 len_from_header;
+
+ len_from_header = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_LEN) << 3;
+
+ if (len_from_header != phy_ppdu->len) {
rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "phy ppdu len mismatch\n");
return -EINVAL;
}
rtw89_core_update_phy_ppdu(phy_ppdu);
- ieee80211_iterate_stations_atomic(rtwdev->hw,
- rtw89_core_rx_process_phy_ppdu_iter,
- phy_ppdu);
return 0;
}
@@ -1344,17 +1384,19 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
u16 ie_len;
- u8 *pos, *end;
+ void *pos, *end;
/* mark invalid reports and bypass them */
if (phy_ppdu->ie < RTW89_CCK_PKT)
return -EINVAL;
- pos = (u8 *)phy_ppdu->buf + PHY_STS_HDR_LEN;
- end = (u8 *)phy_ppdu->buf + phy_ppdu->len;
+ pos = phy_ppdu->buf + PHY_STS_HDR_LEN;
+ end = phy_ppdu->buf + phy_ppdu->len;
while (pos < end) {
- ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, pos);
- rtw89_core_process_phy_status_ie(rtwdev, pos, phy_ppdu);
+ const struct rtw89_phy_sts_iehdr *iehdr = pos;
+
+ ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, iehdr);
+ rtw89_core_process_phy_status_ie(rtwdev, iehdr, phy_ppdu);
pos += ie_len;
if (pos > end || ie_len == 0) {
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
@@ -1363,6 +1405,8 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev,
}
}
+ rtw89_phy_antdiv_parse(rtwdev, phy_ppdu);
+
return 0;
}
@@ -1376,6 +1420,10 @@ static void rtw89_core_rx_process_phy_sts(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXRX, "parse phy sts failed\n");
else
phy_ppdu->valid = true;
+
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_core_rx_process_phy_ppdu_iter,
+ phy_ppdu);
}
static u8 rtw89_rxdesc_to_nl_he_gi(struct rtw89_dev *rtwdev,
@@ -1481,6 +1529,34 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev,
}
}
+static void rtw89_cancel_6ghz_probe_work(struct work_struct *work)
+{
+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
+ cancel_6ghz_probe_work);
+ struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
+ struct rtw89_pktofld_info *info;
+
+ mutex_lock(&rtwdev->mutex);
+
+ if (!rtwdev->scanning)
+ goto out;
+
+ list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) {
+ if (!info->cancel || !test_bit(info->id, rtwdev->pkt_offload))
+ continue;
+
+ rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+
+ /* Don't delete/free info from pkt_list at this moment. Let it
+ * be deleted/freed in rtw89_release_pkt_list() after scanning,
+ * since if during scanning, pkt_list is accessed in bottom half.
+ */
+ }
+
+out:
+ mutex_unlock(&rtwdev->mutex);
+}
+
static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
@@ -1489,6 +1565,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
struct rtw89_pktofld_info *info;
const u8 *ies = mgmt->u.beacon.variable, *ssid_ie;
+ bool queue_work = false;
if (rx_status->band != NL80211_BAND_6GHZ)
return;
@@ -1497,16 +1574,22 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev,
list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) {
if (ether_addr_equal(info->bssid, mgmt->bssid)) {
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+ info->cancel = true;
+ queue_work = true;
continue;
}
if (!ssid_ie || ssid_ie[1] != info->ssid_len || info->ssid_len == 0)
continue;
- if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0)
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
+ if (memcmp(&ssid_ie[2], info->ssid, info->ssid_len) == 0) {
+ info->cancel = true;
+ queue_work = true;
+ }
}
+
+ if (queue_work)
+ ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work);
}
static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
@@ -1722,43 +1805,47 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev,
u8 shift_len, drv_info_len;
rxd_s = (struct rtw89_rxdesc_short *)(data + data_offset);
- desc_info->pkt_size = RTW89_GET_RXWD_PKT_SIZE(rxd_s);
- desc_info->drv_info_size = RTW89_GET_RXWD_DRV_INFO_SIZE(rxd_s);
- desc_info->long_rxdesc = RTW89_GET_RXWD_LONG_RXD(rxd_s);
- desc_info->pkt_type = RTW89_GET_RXWD_RPKT_TYPE(rxd_s);
- desc_info->mac_info_valid = RTW89_GET_RXWD_MAC_INFO_VALID(rxd_s);
+ desc_info->pkt_size = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_LEN_MASK);
+ desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, AX_RXD_DRV_INFO_SIZE_MASK);
+ desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, AX_RXD_LONG_RXD);
+ desc_info->pkt_type = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_TYPE_MASK);
+ desc_info->mac_info_valid = le32_get_bits(rxd_s->dword0, AX_RXD_MAC_INFO_VLD);
if (chip->chip_id == RTL8852C)
- desc_info->bw = RTW89_GET_RXWD_BW_V1(rxd_s);
+ desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_v1_MASK);
else
- desc_info->bw = RTW89_GET_RXWD_BW(rxd_s);
- desc_info->data_rate = RTW89_GET_RXWD_DATA_RATE(rxd_s);
- desc_info->gi_ltf = RTW89_GET_RXWD_GI_LTF(rxd_s);
- desc_info->user_id = RTW89_GET_RXWD_USER_ID(rxd_s);
- desc_info->sr_en = RTW89_GET_RXWD_SR_EN(rxd_s);
- desc_info->ppdu_cnt = RTW89_GET_RXWD_PPDU_CNT(rxd_s);
- desc_info->ppdu_type = RTW89_GET_RXWD_PPDU_TYPE(rxd_s);
- desc_info->free_run_cnt = RTW89_GET_RXWD_FREE_RUN_CNT(rxd_s);
- desc_info->icv_err = RTW89_GET_RXWD_ICV_ERR(rxd_s);
- desc_info->crc32_err = RTW89_GET_RXWD_CRC32_ERR(rxd_s);
- desc_info->hw_dec = RTW89_GET_RXWD_HW_DEC(rxd_s);
- desc_info->sw_dec = RTW89_GET_RXWD_SW_DEC(rxd_s);
- desc_info->addr1_match = RTW89_GET_RXWD_A1_MATCH(rxd_s);
+ desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_MASK);
+ desc_info->data_rate = le32_get_bits(rxd_s->dword1, AX_RXD_RX_DATARATE_MASK);
+ desc_info->gi_ltf = le32_get_bits(rxd_s->dword1, AX_RXD_RX_GI_LTF_MASK);
+ desc_info->user_id = le32_get_bits(rxd_s->dword1, AX_RXD_USER_ID_MASK);
+ desc_info->sr_en = le32_get_bits(rxd_s->dword1, AX_RXD_SR_EN);
+ desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_CNT_MASK);
+ desc_info->ppdu_type = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_TYPE_MASK);
+ desc_info->free_run_cnt = le32_get_bits(rxd_s->dword2, AX_RXD_FREERUN_CNT_MASK);
+ desc_info->icv_err = le32_get_bits(rxd_s->dword3, AX_RXD_ICV_ERR);
+ desc_info->crc32_err = le32_get_bits(rxd_s->dword3, AX_RXD_CRC32_ERR);
+ desc_info->hw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_HW_DEC);
+ desc_info->sw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_SW_DEC);
+ desc_info->addr1_match = le32_get_bits(rxd_s->dword3, AX_RXD_A1_MATCH);
shift_len = desc_info->shift << 1; /* 2-byte unit */
drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */
desc_info->offset = data_offset + shift_len + drv_info_len;
+ if (desc_info->long_rxdesc)
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long);
+ else
+ desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short);
desc_info->ready = true;
if (!desc_info->long_rxdesc)
return;
rxd_l = (struct rtw89_rxdesc_long *)(data + data_offset);
- desc_info->frame_type = RTW89_GET_RXWD_TYPE(rxd_l);
- desc_info->addr_cam_valid = RTW89_GET_RXWD_ADDR_CAM_VLD(rxd_l);
- desc_info->addr_cam_id = RTW89_GET_RXWD_ADDR_CAM_ID(rxd_l);
- desc_info->sec_cam_id = RTW89_GET_RXWD_SEC_CAM_ID(rxd_l);
- desc_info->mac_id = RTW89_GET_RXWD_MAC_ID(rxd_l);
- desc_info->rx_pl_id = RTW89_GET_RXWD_RX_PL_ID(rxd_l);
+ desc_info->frame_type = le32_get_bits(rxd_l->dword4, AX_RXD_TYPE_MASK);
+ desc_info->addr_cam_valid = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_VLD);
+ desc_info->addr_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_MASK);
+ desc_info->sec_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_SEC_CAM_IDX_MASK);
+ desc_info->mac_id = le32_get_bits(rxd_l->dword5, AX_RXD_MAC_ID_MASK);
+ desc_info->rx_pl_id = le32_get_bits(rxd_l->dword5, AX_RXD_RX_PL_ID_MASK);
}
EXPORT_SYMBOL(rtw89_core_query_rxdesc);
@@ -2593,6 +2680,7 @@ static void rtw89_track_work(struct work_struct *work)
rtw89_phy_ra_update(rtwdev);
rtw89_phy_cfo_track(rtwdev);
rtw89_phy_tx_path_div_track(rtwdev);
+ rtw89_phy_antdiv_track(rtwdev);
rtw89_phy_ul_tb_ctrl_track(rtwdev);
if (rtwdev->lps_enabled && !rtwdev->btc.lps)
@@ -2756,6 +2844,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
{
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
int i;
int ret;
@@ -2769,12 +2859,18 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
rtw89_core_txq_init(rtwdev, sta->txq[i]);
ewma_rssi_init(&rtwsta->avg_rssi);
- for (i = 0; i < rtwdev->chip->rf_path_num; i++)
+ ewma_snr_init(&rtwsta->avg_snr);
+ for (i = 0; i < ant_num; i++) {
ewma_rssi_init(&rtwsta->rssi[i]);
+ ewma_evm_init(&rtwsta->evm_min[i]);
+ ewma_evm_init(&rtwsta->evm_max[i]);
+ }
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
/* for station mode, assign the mac_id from itself */
rtwsta->mac_id = rtwvif->mac_id;
+ /* must do rtw89_reg_6ghz_power_recalc() before rfk channel */
+ rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, true);
rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
BTC_ROLE_MSTS_STA_CONN_START);
rtw89_chip_rfk_channel(rtwdev);
@@ -2948,10 +3044,11 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
int ret;
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
+ rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, false);
rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta,
BTC_ROLE_MSTS_STA_DIS_CONN);
- else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
+ } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id);
ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
@@ -3292,8 +3389,10 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev)
{
struct ieee80211_hw *hw = rtwdev->hw;
- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
+ if (hw->wiphy->bands[NL80211_BAND_2GHZ])
+ kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data);
+ if (hw->wiphy->bands[NL80211_BAND_5GHZ])
+ kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data);
if (hw->wiphy->bands[NL80211_BAND_6GHZ])
kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data);
kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
@@ -3430,6 +3529,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
mutex_unlock(&rtwdev->mutex);
cancel_work_sync(&rtwdev->c2h_work);
+ cancel_work_sync(&rtwdev->cancel_6ghz_probe_work);
cancel_work_sync(&btc->eapol_notify_work);
cancel_work_sync(&btc->arp_notify_work);
cancel_work_sync(&btc->dhcp_notify_work);
@@ -3441,6 +3541,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev)
cancel_delayed_work_sync(&rtwdev->coex_rfk_chk_work);
cancel_delayed_work_sync(&rtwdev->cfo_track_work);
cancel_delayed_work_sync(&rtwdev->forbid_ba_work);
+ cancel_delayed_work_sync(&rtwdev->antdiv_work);
mutex_lock(&rtwdev->mutex);
@@ -3476,6 +3577,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
INIT_DELAYED_WORK(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work);
INIT_DELAYED_WORK(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work);
INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work);
+ INIT_DELAYED_WORK(&rtwdev->antdiv_work, rtw89_phy_antdiv_work);
rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0);
if (!rtwdev->txq_wq)
return -ENOMEM;
@@ -3486,10 +3588,12 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
rtwdev->total_sta_assoc = 0;
rtw89_init_wait(&rtwdev->mcc.wait);
+ rtw89_init_wait(&rtwdev->mac.fw_ofld_wait);
INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work);
INIT_WORK(&rtwdev->ips_work, rtw89_ips_work);
INIT_WORK(&rtwdev->load_firmware_work, rtw89_load_firmware_work);
+ INIT_WORK(&rtwdev->cancel_6ghz_probe_work, rtw89_cancel_6ghz_probe_work);
skb_queue_head_init(&rtwdev->c2h_queue);
rtw89_core_ppdu_sts_init(rtwdev);
@@ -3584,7 +3688,7 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev)
if (chip->chip_id == RTL8852B || chip->chip_id == RTL8851B) {
ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val);
- if (!ret)
+ if (ret)
return;
rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK);
@@ -3693,6 +3797,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
{
struct ieee80211_hw *hw = rtwdev->hw;
struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw89_hal *hal = &rtwdev->hal;
int ret;
int tx_headroom = IEEE80211_HT_CTL_LEN;
@@ -3731,8 +3836,13 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
- hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1;
- hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1;
+ if (hal->ant_diversity) {
+ hw->wiphy->available_antennas_tx = 0x3;
+ hw->wiphy->available_antennas_rx = 0x3;
+ } else {
+ hw->wiphy->available_antennas_tx = BIT(rtwdev->chip->rf_path_num) - 1;
+ hw->wiphy->available_antennas_rx = BIT(rtwdev->chip->rf_path_num) - 1;
+ }
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_TDLS_EXTERNAL_SETUP |
@@ -3760,7 +3870,12 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
return ret;
}
- hw->wiphy->reg_notifier = rtw89_regd_notifier;
+ ret = rtw89_regd_setup(rtwdev);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to set up regd\n");
+ goto err_free_supported_band;
+ }
+
hw->wiphy->sar_capa = &rtw89_sar_capa;
ret = ieee80211_register_hw(hw);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 6df386a38fb4..d2c67db97db1 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -122,6 +122,13 @@ enum rtw89_cv {
CHIP_CV_INVALID = CHIP_CV_MAX,
};
+enum rtw89_bacam_ver {
+ RTW89_BACAM_V0,
+ RTW89_BACAM_V1,
+
+ RTW89_BACAM_V0_EXT = 99,
+};
+
enum rtw89_core_tx_type {
RTW89_CORE_TX_TYPE_DATA,
RTW89_CORE_TX_TYPE_MGMT,
@@ -244,7 +251,7 @@ enum rtw89_band {
RTW89_BAND_2G = 0,
RTW89_BAND_5G = 1,
RTW89_BAND_6G = 2,
- RTW89_BAND_MAX,
+ RTW89_BAND_NUM,
};
enum rtw89_hw_rate {
@@ -427,27 +434,27 @@ enum rtw89_rate_section {
RTW89_RS_MCS, /* for HT/VHT/HE */
RTW89_RS_HEDCM,
RTW89_RS_OFFSET,
- RTW89_RS_MAX,
+ RTW89_RS_NUM,
RTW89_RS_LMT_NUM = RTW89_RS_MCS + 1,
RTW89_RS_TX_SHAPE_NUM = RTW89_RS_OFDM + 1,
};
-enum rtw89_rate_max {
- RTW89_RATE_CCK_MAX = 4,
- RTW89_RATE_OFDM_MAX = 8,
- RTW89_RATE_MCS_MAX = 12,
- RTW89_RATE_HEDCM_MAX = 4, /* for HEDCM MCS0/1/3/4 */
- RTW89_RATE_OFFSET_MAX = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */
+enum rtw89_rate_num {
+ RTW89_RATE_CCK_NUM = 4,
+ RTW89_RATE_OFDM_NUM = 8,
+ RTW89_RATE_MCS_NUM = 12,
+ RTW89_RATE_HEDCM_NUM = 4, /* for HEDCM MCS0/1/3/4 */
+ RTW89_RATE_OFFSET_NUM = 5, /* for HE(HEDCM)/VHT/HT/OFDM/CCK offset */
};
enum rtw89_nss {
RTW89_NSS_1 = 0,
RTW89_NSS_2 = 1,
/* HE DCM only support 1ss and 2ss */
- RTW89_NSS_HEDCM_MAX = RTW89_NSS_2 + 1,
+ RTW89_NSS_HEDCM_NUM = RTW89_NSS_2 + 1,
RTW89_NSS_3 = 2,
RTW89_NSS_4 = 3,
- RTW89_NSS_MAX,
+ RTW89_NSS_NUM,
};
enum rtw89_ntx {
@@ -481,6 +488,15 @@ enum rtw89_regulation_type {
RTW89_REGD_NUM,
};
+enum rtw89_reg_6ghz_power {
+ RTW89_REG_6GHZ_POWER_VLP = 0,
+ RTW89_REG_6GHZ_POWER_LPI = 1,
+ RTW89_REG_6GHZ_POWER_STD = 2,
+
+ NUM_OF_RTW89_REG_6GHZ_POWER,
+ RTW89_REG_6GHZ_POWER_DFLT = RTW89_REG_6GHZ_POWER_VLP,
+};
+
enum rtw89_fw_pkt_ofld_type {
RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0,
RTW89_PKT_OFLD_TYPE_PS_POLL = 1,
@@ -496,11 +512,11 @@ enum rtw89_fw_pkt_ofld_type {
};
struct rtw89_txpwr_byrate {
- s8 cck[RTW89_RATE_CCK_MAX];
- s8 ofdm[RTW89_RATE_OFDM_MAX];
- s8 mcs[RTW89_NSS_MAX][RTW89_RATE_MCS_MAX];
- s8 hedcm[RTW89_NSS_HEDCM_MAX][RTW89_RATE_HEDCM_MAX];
- s8 offset[RTW89_RATE_OFFSET_MAX];
+ s8 cck[RTW89_RATE_CCK_NUM];
+ s8 ofdm[RTW89_RATE_OFDM_NUM];
+ s8 mcs[RTW89_NSS_NUM][RTW89_RATE_MCS_NUM];
+ s8 hedcm[RTW89_NSS_HEDCM_NUM][RTW89_RATE_HEDCM_NUM];
+ s8 offset[RTW89_RATE_OFFSET_NUM];
};
enum rtw89_bandwidth_section_num {
@@ -543,7 +559,7 @@ struct rtw89_rate_desc {
#define RF_PATH_MAX 4
#define RTW89_MAX_PPDU_CNT 8
struct rtw89_rx_phy_ppdu {
- u8 *buf;
+ void *buf;
u32 len;
u8 rssi_avg;
u8 rssi[RF_PATH_MAX];
@@ -551,6 +567,12 @@ struct rtw89_rx_phy_ppdu {
u8 chan_idx;
u8 ie;
u16 rate;
+ struct {
+ bool has;
+ u8 avg_snr;
+ u8 evm_max;
+ u8 evm_min;
+ } ofdm;
bool to_self;
bool valid;
};
@@ -763,6 +785,7 @@ struct rtw89_rx_desc_info {
u8 sec_cam_id;
u8 mac_id;
u16 offset;
+ u16 rxd_len;
bool ready;
};
@@ -1382,7 +1405,6 @@ struct rtw89_btc_wl_nhm {
u8 current_status;
u8 refresh;
bool start_flag;
- u8 last_ccx_rpt_stamp;
s8 pwr_max;
s8 pwr_min;
};
@@ -2533,6 +2555,8 @@ struct rtw89_ra_report {
};
DECLARE_EWMA(rssi, 10, 16);
+DECLARE_EWMA(evm, 10, 16);
+DECLARE_EWMA(snr, 10, 16);
struct rtw89_ba_cam_entry {
struct list_head list;
@@ -2595,6 +2619,9 @@ struct rtw89_sta {
u8 prev_rssi;
struct ewma_rssi avg_rssi;
struct ewma_rssi rssi[RF_PATH_MAX];
+ struct ewma_snr avg_snr;
+ struct ewma_evm evm_min[RF_PATH_MAX];
+ struct ewma_evm evm_max[RF_PATH_MAX];
struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
struct ieee80211_rx_status rx_status;
u16 rx_hw_rate;
@@ -2663,6 +2690,7 @@ struct rtw89_vif {
struct rtw89_dev *rtwdev;
struct rtw89_roc roc;
enum rtw89_sub_entity_idx sub_entity_idx;
+ enum rtw89_reg_6ghz_power reg_6ghz_power;
u8 mac_id;
u8 port;
@@ -2781,6 +2809,7 @@ struct rtw89_chip_ops {
int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map);
int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
void (*fem_setup)(struct rtw89_dev *rtwdev);
+ void (*rfe_gpio)(struct rtw89_dev *rtwdev);
void (*rfk_init)(struct rtw89_dev *rtwdev);
void (*rfk_channel)(struct rtw89_dev *rtwdev);
void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
@@ -2805,6 +2834,9 @@ struct rtw89_chip_ops {
s8 pw_ofst, enum rtw89_mac_idx mac_idx);
int (*pwr_on_func)(struct rtw89_dev *rtwdev);
int (*pwr_off_func)(struct rtw89_dev *rtwdev);
+ void (*query_rxdesc)(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset);
void (*fill_txdesc)(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc);
@@ -3013,9 +3045,11 @@ struct rtw89_txpwr_rule_5ghz {
struct rtw89_txpwr_rule_6ghz {
const s8 (*lmt)[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM];
const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM];
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM];
};
struct rtw89_rfe_parms {
@@ -3090,6 +3124,12 @@ struct rtw89_imr_info {
u32 tmac_imr_set;
};
+struct rtw89_xtal_info {
+ u32 xcap_reg;
+ u32 sc_xo_mask;
+ u32 sc_xi_mask;
+};
+
struct rtw89_rrsr_cfgs {
struct rtw89_reg3_def ref_rate;
struct rtw89_reg3_def rsc;
@@ -3116,6 +3156,25 @@ struct rtw89_phy_ul_tb_info {
u8 def_if_bandedge;
};
+struct rtw89_antdiv_stats {
+ struct ewma_rssi cck_rssi_avg;
+ struct ewma_rssi ofdm_rssi_avg;
+ struct ewma_rssi non_legacy_rssi_avg;
+ u16 pkt_cnt_cck;
+ u16 pkt_cnt_ofdm;
+ u16 pkt_cnt_non_legacy;
+ u32 evm;
+};
+
+struct rtw89_antdiv_info {
+ struct rtw89_antdiv_stats target_stats;
+ struct rtw89_antdiv_stats main_stats;
+ struct rtw89_antdiv_stats aux_stats;
+ u8 training_count;
+ u8 rssi_pre;
+ bool get_stats;
+};
+
struct rtw89_chip_info {
enum rtw89_core_chip_id chip_id;
const struct rtw89_chip_ops *ops;
@@ -3123,6 +3182,7 @@ struct rtw89_chip_info {
u8 fw_format_max;
bool try_ce_fw;
u32 fifo_size;
+ bool small_fifo_size;
u32 dle_scc_rsvd_size;
u16 max_amsdu_limit;
bool dis_2g_40m_ul_ofdma;
@@ -3135,6 +3195,7 @@ struct rtw89_chip_info {
u8 support_chanctx_num;
u8 support_bands;
bool support_bw160;
+ bool support_unii4;
bool support_ul_tb_ctrl;
bool hw_sec_hdr;
u8 rf_path_num;
@@ -3145,7 +3206,7 @@ struct rtw89_chip_info {
u8 scam_num;
u8 bacam_num;
u8 bacam_dynamic_num;
- bool bacam_v1;
+ enum rtw89_bacam_ver bacam_ver;
u8 sec_ctrl_efuse_size;
u32 physical_efuse_size;
@@ -3162,6 +3223,7 @@ struct rtw89_chip_info {
const struct rtw89_phy_table *bb_gain_table;
const struct rtw89_phy_table *rf_table[RF_PATH_MAX];
const struct rtw89_phy_table *nctl_table;
+ const struct rtw89_rfk_tbl *nctl_post_table;
const struct rtw89_txpwr_table *byr_table;
const struct rtw89_phy_dig_gain_table *dig_table;
const struct rtw89_dig_regs *dig_regs;
@@ -3215,6 +3277,7 @@ struct rtw89_chip_info {
u32 dma_ch_mask;
u32 edcca_lvl_reg;
const struct wiphy_wowlan_support *wowlan_stub;
+ const struct rtw89_xtal_info *xtal_info;
};
union rtw89_bus_info {
@@ -3237,7 +3300,6 @@ enum rtw89_hcifc_mode {
struct rtw89_dle_info {
enum rtw89_qta_mode qta_mode;
- u16 wde_pg_size;
u16 ple_pg_size;
u16 c0_rx_qta;
u16 c1_rx_qta;
@@ -3248,14 +3310,6 @@ enum rtw89_host_rpr_mode {
RTW89_RPR_MODE_STF
};
-struct rtw89_mac_info {
- struct rtw89_dle_info dle_info;
- struct rtw89_hfc_param hfc_param;
- enum rtw89_qta_mode qta_mode;
- u8 rpwm_seq_num;
- u8 cpwm_seq_num;
-};
-
#define RTW89_COMPLETION_BUF_SIZE 24
#define RTW89_WAIT_COND_IDLE UINT_MAX
@@ -3278,6 +3332,17 @@ static inline void rtw89_init_wait(struct rtw89_wait_info *wait)
atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE);
}
+struct rtw89_mac_info {
+ struct rtw89_dle_info dle_info;
+ struct rtw89_hfc_param hfc_param;
+ enum rtw89_qta_mode qta_mode;
+ u8 rpwm_seq_num;
+ u8 cpwm_seq_num;
+
+ /* see RTW89_FW_OFLD_WAIT_COND series for wait condition */
+ struct rtw89_wait_info fw_ofld_wait;
+};
+
enum rtw89_fw_type {
RTW89_FW_NORMAL = 1,
RTW89_FW_WOWLAN = 3,
@@ -3322,10 +3387,10 @@ struct rtw89_fw_suit {
(mfw_hdr)->ver.idx)
#define RTW89_FW_HDR_VER_CODE(fw_hdr) \
- RTW89_FW_VER_CODE(GET_FW_HDR_MAJOR_VERSION(fw_hdr), \
- GET_FW_HDR_MINOR_VERSION(fw_hdr), \
- GET_FW_HDR_SUBVERSION(fw_hdr), \
- GET_FW_HDR_SUBINDEX(fw_hdr))
+ RTW89_FW_VER_CODE(le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MAJOR_VERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_MINOR_VERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBVERSION), \
+ le32_get_bits((fw_hdr)->w1, FW_HDR_W1_SUBINDEX))
struct rtw89_fw_req_info {
const struct firmware *firmware;
@@ -3417,12 +3482,13 @@ struct rtw89_hal {
u32 rx_fltr;
u8 cv;
u8 acv;
- u32 sw_amsdu_max_size;
u32 antenna_tx;
u32 antenna_rx;
u8 tx_nss;
u8 rx_nss;
bool tx_path_diversity;
+ bool ant_diversity;
+ bool ant_diversity_fixed;
bool support_cckpd;
bool support_igi;
atomic_t roc_entity_idx;
@@ -3452,6 +3518,7 @@ enum rtw89_flags {
RTW89_FLAG_LOW_POWER_MODE,
RTW89_FLAG_INACTIVE_PS,
RTW89_FLAG_CRASH_SIMULATING,
+ RTW89_FLAG_SER_HANDLING,
RTW89_FLAG_WOWLAN,
RTW89_FLAG_FORBIDDEN_TRACK_WROK,
RTW89_FLAG_CHANGING_INTERFACE,
@@ -3543,7 +3610,6 @@ struct rtw89_iqk_info {
u8 iqk_band[RTW89_IQK_PATH_NR];
u8 iqk_ch[RTW89_IQK_PATH_NR];
u8 iqk_bw[RTW89_IQK_PATH_NR];
- u8 kcount;
u8 iqk_times;
u8 version;
u32 nb_txcfir[RTW89_IQK_PATH_NR];
@@ -3558,8 +3624,6 @@ struct rtw89_iqk_info {
bool iqk_xym_en;
bool iqk_sram_en;
bool iqk_cfir_en;
- u8 thermal[RTW89_IQK_PATH_NR];
- bool thermal_rek_en;
u32 syn1to2;
u8 iqk_mcc_ch[RTW89_IQK_CHS_NR][RTW89_IQK_PATH_NR];
u8 iqk_table_idx[RTW89_IQK_PATH_NR];
@@ -3749,9 +3813,14 @@ struct rtw89_power_trim_info {
u8 pa_bias_trim[RF_PATH_MAX];
};
-struct rtw89_regulatory {
+struct rtw89_regd {
char alpha2[3];
- u8 txpwr_regd[RTW89_BAND_MAX];
+ u8 txpwr_regd[RTW89_BAND_NUM];
+};
+
+struct rtw89_regulatory_info {
+ const struct rtw89_regd *regd;
+ enum rtw89_reg_6ghz_power reg_6ghz_power;
};
enum rtw89_ifs_clm_application {
@@ -3815,35 +3884,16 @@ enum rtw89_ccx_edcca_opt_bw_idx {
#define RTW89_FAHM_RPT_NUM 12
#define RTW89_IFS_CLM_NUM 4
struct rtw89_env_monitor_info {
- u32 ccx_trigger_time;
- u64 start_time;
- u8 ccx_rpt_stamp;
u8 ccx_watchdog_result;
bool ccx_ongoing;
u8 ccx_rac_lv;
bool ccx_manual_ctrl;
- u8 ccx_pre_rssi;
- u16 clm_mntr_time;
- u16 nhm_mntr_time;
u16 ifs_clm_mntr_time;
enum rtw89_ifs_clm_application ifs_clm_app;
- u16 fahm_mntr_time;
- u16 edcca_clm_mntr_time;
u16 ccx_period;
u8 ccx_unit_idx;
- enum rtw89_ccx_edcca_opt_bw_idx ccx_edcca_opt_bw_idx;
- u8 nhm_th[RTW89_NHM_TH_NUM];
u16 ifs_clm_th_l[RTW89_IFS_CLM_NUM];
u16 ifs_clm_th_h[RTW89_IFS_CLM_NUM];
- u8 fahm_numer_opt;
- u8 fahm_denom_opt;
- u8 fahm_th[RTW89_FAHM_TH_NUM];
- u16 clm_result;
- u16 nhm_result[RTW89_NHM_RPT_NUM];
- u8 nhm_wgt[RTW89_NHM_RPT_NUM];
- u16 nhm_tx_cnt;
- u16 nhm_cca_cnt;
- u16 nhm_idle_cnt;
u16 ifs_clm_tx;
u16 ifs_clm_edcca_excl_cca;
u16 ifs_clm_ofdmfa;
@@ -3854,17 +3904,6 @@ struct rtw89_env_monitor_info {
u8 ifs_clm_his[RTW89_IFS_CLM_NUM];
u16 ifs_clm_avg[RTW89_IFS_CLM_NUM];
u16 ifs_clm_cca[RTW89_IFS_CLM_NUM];
- u16 fahm_result[RTW89_FAHM_RPT_NUM];
- u16 fahm_denom_result;
- u16 edcca_clm_result;
- u8 clm_ratio;
- u8 nhm_rpt[RTW89_NHM_RPT_NUM];
- u8 nhm_tx_ratio;
- u8 nhm_cca_ratio;
- u8 nhm_idle_ratio;
- u8 nhm_ratio;
- u16 nhm_result_sum;
- u8 nhm_pwr;
u8 ifs_clm_tx_ratio;
u8 ifs_clm_edcca_excl_cca_ratio;
u8 ifs_clm_cck_fa_ratio;
@@ -3875,12 +3914,6 @@ struct rtw89_env_monitor_info {
u16 ifs_clm_ofdm_fa_permil;
u32 ifs_clm_ifs_avg[RTW89_IFS_CLM_NUM];
u32 ifs_clm_cca_avg[RTW89_IFS_CLM_NUM];
- u8 fahm_rpt[RTW89_FAHM_RPT_NUM];
- u16 fahm_result_sum;
- u8 fahm_ratio;
- u8 fahm_denom_ratio;
- u8 fahm_pwr;
- u8 edcca_clm_ratio;
};
enum rtw89_ser_rcvy_step {
@@ -3888,12 +3921,14 @@ enum rtw89_ser_rcvy_step {
RTW89_SER_DRV_STOP_RX,
RTW89_SER_DRV_STOP_RUN,
RTW89_SER_HAL_STOP_DMA,
+ RTW89_SER_SUPPRESS_LOG,
RTW89_NUM_OF_SER_FLAGS
};
struct rtw89_ser {
u8 state;
u8 alarm_event;
+ bool prehandle_l1;
struct work_struct ser_hdl_work;
struct delayed_work ser_alarm_work;
@@ -4054,6 +4089,7 @@ struct rtw89_dev {
struct work_struct c2h_work;
struct work_struct ips_work;
struct work_struct load_firmware_work;
+ struct work_struct cancel_6ghz_probe_work;
struct list_head early_h2c_list;
@@ -4075,7 +4111,7 @@ struct rtw89_dev {
bool is_bt_iqk_timeout;
struct rtw89_fem_info fem;
- struct rtw89_txpwr_byrate byr[RTW89_BAND_MAX];
+ struct rtw89_txpwr_byrate byr[RTW89_BAND_NUM];
struct rtw89_tssi_info tssi;
struct rtw89_power_trim_info pwr_trim;
@@ -4086,6 +4122,7 @@ struct rtw89_dev {
struct rtw89_phy_bb_gain_info bb_gain;
struct rtw89_phy_efuse_gain efuse_gain;
struct rtw89_phy_ul_tb_info ul_tb_info;
+ struct rtw89_antdiv_info antdiv;
struct delayed_work track_work;
struct delayed_work coex_act1_work;
@@ -4094,11 +4131,12 @@ struct rtw89_dev {
struct delayed_work cfo_track_work;
struct delayed_work forbid_ba_work;
struct delayed_work roc_work;
+ struct delayed_work antdiv_work;
struct rtw89_ppdu_sts_info ppdu_sts;
u8 total_sta_assoc;
bool scanning;
- const struct rtw89_regulatory *regd;
+ struct rtw89_regulatory_info regulatory;
struct rtw89_sar_info sar;
struct rtw89_btc btc;
@@ -4643,6 +4681,14 @@ static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
chip->ops->fem_setup(rtwdev);
}
+static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->ops->rfe_gpio)
+ chip->ops->rfe_gpio(rtwdev);
+}
+
static inline void rtw89_chip_bb_sethw(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -4777,7 +4823,9 @@ static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev,
static inline u8 rtw89_regd_get(struct rtw89_dev *rtwdev, u8 band)
{
- return rtwdev->regd->txpwr_regd[band];
+ const struct rtw89_regd *regd = rtwdev->regulatory.regd;
+
+ return regd->txpwr_regd[band];
}
static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
@@ -4789,6 +4837,16 @@ static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
}
static inline
+void rtw89_chip_query_rxdesc(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ u8 *data, u32 data_offset)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ chip->ops->query_rxdesc(rtwdev, desc_info, data, data_offset);
+}
+
+static inline
void rtw89_chip_fill_txdesc(struct rtw89_dev *rtwdev,
struct rtw89_tx_desc_info *desc_info,
void *txdesc)
@@ -4990,6 +5048,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc);
int rtw89_chip_info_setup(struct rtw89_dev *rtwdev);
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
+int rtw89_regd_setup(struct rtw89_dev *rtwdev);
int rtw89_regd_init(struct rtw89_dev *rtwdev,
void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request));
void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
@@ -5008,5 +5067,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
const u8 *mac_addr, bool hw_scan);
void rtw89_core_scan_complete(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif, bool hw_scan);
+void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool active);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 1e5b7a998716..ce5a9ac08145 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -30,7 +30,7 @@ struct rtw89_debugfs_priv {
u32 cb_data;
struct {
u32 addr;
- u8 len;
+ u32 len;
} read_reg;
struct {
u32 addr;
@@ -164,12 +164,15 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v)
{
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
- u32 addr, data;
- u8 len;
+ u32 addr, end, data, k;
+ u32 len;
len = debugfs_priv->read_reg.len;
addr = debugfs_priv->read_reg.addr;
+ if (len > 4)
+ goto ndata;
+
switch (len) {
case 1:
data = rtw89_read8(rtwdev, addr);
@@ -188,6 +191,20 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v)
seq_printf(m, "get %d bytes at 0x%08x=0x%08x\n", len, addr, data);
return 0;
+
+ndata:
+ end = addr + len;
+
+ for (; addr < end; addr += 16) {
+ seq_printf(m, "%08xh : ", 0x18600000 + addr);
+ for (k = 0; k < 16; k += 4) {
+ data = rtw89_read32(rtwdev, addr + k);
+ seq_printf(m, "%08x ", data);
+ }
+ seq_puts(m, "\n");
+ }
+
+ return 0;
}
static ssize_t rtw89_debug_priv_write_reg_set(struct file *filp,
@@ -359,6 +376,7 @@ struct txpwr_map {
u8 size;
u32 addr_from;
u32 addr_to;
+ u32 addr_to_1ss;
};
#define __GEN_TXPWR_ENT2(_t, _e0, _e1) \
@@ -396,6 +414,7 @@ static const struct txpwr_map __txpwr_map_byr = {
.size = ARRAY_SIZE(__txpwr_ent_byr),
.addr_from = R_AX_PWR_BY_RATE,
.addr_to = R_AX_PWR_BY_RATE_MAX,
+ .addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt[] = {
@@ -451,6 +470,7 @@ static const struct txpwr_map __txpwr_map_lmt = {
.size = ARRAY_SIZE(__txpwr_ent_lmt),
.addr_from = R_AX_PWR_LMT,
.addr_to = R_AX_PWR_LMT_MAX,
+ .addr_to_1ss = R_AX_PWR_LMT_1SS_MAX,
};
static const struct txpwr_ent __txpwr_ent_lmt_ru[] = {
@@ -478,6 +498,7 @@ static const struct txpwr_map __txpwr_map_lmt_ru = {
.size = ARRAY_SIZE(__txpwr_ent_lmt_ru),
.addr_from = R_AX_PWR_RU_LMT,
.addr_to = R_AX_PWR_RU_LMT_MAX,
+ .addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX,
};
static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent,
@@ -510,6 +531,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
const struct txpwr_map *map)
{
u8 fct = rtwdev->chip->txpwr_factor_mac;
+ u8 path_num = rtwdev->chip->rf_path_num;
+ u32 max_valid_addr;
u32 val, addr;
s8 *buf, tmp;
u8 cur, i;
@@ -519,7 +542,12 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
if (!buf)
return -ENOMEM;
- for (addr = map->addr_from; addr <= map->addr_to; addr += 4) {
+ if (path_num == 1)
+ max_valid_addr = map->addr_to_1ss;
+ else
+ max_valid_addr = map->addr_to;
+
+ for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) {
ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val);
if (ret)
val = MASKDWORD;
@@ -2998,17 +3026,18 @@ static ssize_t rtw89_debug_priv_send_h2c_set(struct file *filp,
struct rtw89_debugfs_priv *debugfs_priv = filp->private_data;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
u8 *h2c;
+ int ret;
u16 h2c_len = count / 2;
h2c = rtw89_hex2bin_user(rtwdev, user_buf, count);
if (IS_ERR(h2c))
return -EFAULT;
- rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
+ ret = rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
kfree(h2c);
- return count;
+ return ret ? ret : count;
}
static int
@@ -3164,12 +3193,14 @@ static ssize_t rtw89_debug_priv_btc_manual_set(struct file *filp,
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw89_btc *btc = &rtwdev->btc;
bool btc_manual;
+ int ret;
- if (kstrtobool_from_user(user_buf, count, &btc_manual))
- goto out;
+ ret = kstrtobool_from_user(user_buf, count, &btc_manual);
+ if (ret)
+ return ret;
btc->ctrl.manual = btc_manual;
-out:
+
return count;
}
@@ -3206,7 +3237,11 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
struct seq_file *m = (struct seq_file *)data;
struct rtw89_dev *rtwdev = rtwsta->rtwdev;
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num;
+ bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity;
+ u8 evm_min, evm_max;
u8 rssi;
+ u8 snr;
int i;
seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id);
@@ -3256,13 +3291,27 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
rssi = ewma_rssi_read(&rtwsta->avg_rssi);
seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [",
RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi);
- for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
+ for (i = 0; i < ant_num; i++) {
rssi = ewma_rssi_read(&rtwsta->rssi[i]);
seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi),
- hal->tx_path_diversity && (hal->antenna_tx & BIT(i)) ? "*" : "",
- i + 1 == rtwdev->chip->rf_path_num ? "" : ", ");
+ ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "",
+ i + 1 == ant_num ? "" : ", ");
}
seq_puts(m, "]\n");
+
+ seq_puts(m, "EVM: [");
+ for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) {
+ evm_min = ewma_evm_read(&rtwsta->evm_min[i]);
+ evm_max = ewma_evm_read(&rtwsta->evm_max[i]);
+
+ seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ",
+ evm_min >> 2, (evm_min & 0x3) * 25,
+ evm_max >> 2, (evm_max & 0x3) * 25);
+ }
+ seq_puts(m, "]\t");
+
+ snr = ewma_snr_read(&rtwsta->avg_snr);
+ seq_printf(m, "SNR: %u\n", snr);
}
static void
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index 7bd4f8558e03..2aaf4d013e46 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -7,6 +7,10 @@
#include "mac.h"
#include "reg.h"
+#define EF_FV_OFSET 0x5ea
+#define EF_CV_MASK GENMASK(7, 4)
+#define EF_CV_INV 15
+
enum rtw89_efuse_bank {
RTW89_EFUSE_BANK_WIFI,
RTW89_EFUSE_BANK_BT,
@@ -328,3 +332,20 @@ out_free:
return ret;
}
+
+int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv)
+{
+ int ret;
+ u8 val;
+
+ ret = rtw89_dump_physical_efuse_map(rtwdev, &val, EF_FV_OFSET, 1, false);
+ if (ret)
+ return ret;
+
+ *ecv = u8_get_bits(val, EF_CV_MASK);
+ if (*ecv == EF_CV_INV)
+ return -ENOENT;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtw89_read_efuse_ver);
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index 622ff95e7476..79071aff28de 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -9,5 +9,6 @@
int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev);
int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev);
+int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index b9b675bf9d05..d44628a90046 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -14,6 +14,8 @@
static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
struct sk_buff *skb);
+static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
+ struct rtw89_wait_info *wait, unsigned int cond);
static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
bool header)
@@ -87,9 +89,11 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev)
static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
struct rtw89_fw_bin_info *info)
{
+ const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw;
struct rtw89_fw_hdr_section_info *section_info;
+ const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
+ const struct rtw89_fw_hdr_section *section;
const u8 *fw_end = fw + len;
- const u8 *fwdynhdr;
const u8 *bin;
u32 base_hdr_len;
u32 mssc_len = 0;
@@ -98,16 +102,15 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
if (!info)
return -EINVAL;
- info->section_num = GET_FW_HDR_SEC_NUM(fw);
- base_hdr_len = RTW89_FW_HDR_SIZE +
- info->section_num * RTW89_FW_SECTION_HDR_SIZE;
- info->dynamic_hdr_en = GET_FW_HDR_DYN_HDR(fw);
+ info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_W6_SEC_NUM);
+ base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
+ info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR);
if (info->dynamic_hdr_en) {
- info->hdr_len = GET_FW_HDR_LEN(fw);
+ info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN);
info->dynamic_hdr_len = info->hdr_len - base_hdr_len;
- fwdynhdr = fw + base_hdr_len;
- if (GET_FW_DYNHDR_LEN(fwdynhdr) != info->dynamic_hdr_len) {
+ fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len);
+ if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) {
rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n");
return -EINVAL;
}
@@ -119,26 +122,27 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
bin = fw + info->hdr_len;
/* jump to section header */
- fw += RTW89_FW_HDR_SIZE;
section_info = info->section_info;
for (i = 0; i < info->section_num; i++) {
- section_info->type = GET_FWSECTION_HDR_SECTIONTYPE(fw);
+ section = &fw_hdr->sections[i];
+ section_info->type =
+ le32_get_bits(section->w1, FWSECTION_HDR_W1_SECTIONTYPE);
if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
- section_info->mssc = GET_FWSECTION_HDR_MSSC(fw);
+ section_info->mssc =
+ le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC);
mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
} else {
section_info->mssc = 0;
}
- section_info->len = GET_FWSECTION_HDR_SEC_SIZE(fw);
- if (GET_FWSECTION_HDR_CHECKSUM(fw))
+ section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE);
+ if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM))
section_info->len += FWDL_SECTION_CHKSUM_LEN;
- section_info->redl = GET_FWSECTION_HDR_REDL(fw);
+ section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL);
section_info->dladdr =
- GET_FWSECTION_HDR_DL_ADDR(fw) & 0x1fffffff;
+ le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
section_info->addr = bin;
bin += section_info->len;
- fw += RTW89_FW_SECTION_HDR_SIZE;
section_info++;
}
@@ -193,18 +197,18 @@ static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev,
enum rtw89_fw_type type,
struct rtw89_fw_suit *fw_suit)
{
- const u8 *hdr = fw_suit->data;
-
- fw_suit->major_ver = GET_FW_HDR_MAJOR_VERSION(hdr);
- fw_suit->minor_ver = GET_FW_HDR_MINOR_VERSION(hdr);
- fw_suit->sub_ver = GET_FW_HDR_SUBVERSION(hdr);
- fw_suit->sub_idex = GET_FW_HDR_SUBINDEX(hdr);
- fw_suit->build_year = GET_FW_HDR_YEAR(hdr);
- fw_suit->build_mon = GET_FW_HDR_MONTH(hdr);
- fw_suit->build_date = GET_FW_HDR_DATE(hdr);
- fw_suit->build_hour = GET_FW_HDR_HOUR(hdr);
- fw_suit->build_min = GET_FW_HDR_MIN(hdr);
- fw_suit->cmd_ver = GET_FW_HDR_CMD_VERSERION(hdr);
+ const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data;
+
+ fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION);
+ fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION);
+ fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION);
+ fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX);
+ fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR);
+ fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH);
+ fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE);
+ fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR);
+ fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN);
+ fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION);
rtw89_info(rtwdev,
"Firmware version %u.%u.%u.%u, cmd version %u, type %u\n",
@@ -254,6 +258,9 @@ struct __fw_feat_cfg {
}
static const struct __fw_feat_cfg fw_feat_tbl[] = {
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER),
__CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
@@ -305,31 +312,17 @@ rtw89_early_fw_feature_recognize(struct device *device,
struct rtw89_fw_info *early_fw,
int *used_fw_format)
{
- union rtw89_compat_fw_hdr buf = {};
const struct firmware *firmware;
- bool full_req = false;
char fw_name[64];
int fw_format;
u32 ver_code;
int ret;
- /* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will
- * be denied (-EPERM). Then, we don't get right firmware things as
- * expected. So, in this case, we have to request full firmware here.
- */
- if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE))
- full_req = true;
-
for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) {
rtw89_fw_get_filename(fw_name, sizeof(fw_name),
chip->fw_basename, fw_format);
- if (full_req)
- ret = request_firmware(&firmware, fw_name, device);
- else
- ret = request_partial_firmware_into_buf(&firmware, fw_name,
- device, &buf, sizeof(buf),
- 0);
+ ret = request_firmware(&firmware, fw_name, device);
if (!ret) {
dev_info(device, "loaded firmware %s\n", fw_name);
*used_fw_format = fw_format;
@@ -342,10 +335,7 @@ rtw89_early_fw_feature_recognize(struct device *device,
return NULL;
}
- if (full_req)
- ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data);
- else
- ver_code = rtw89_compat_fw_hdr_ver_code(&buf);
+ ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data);
if (!ver_code)
goto out;
@@ -353,11 +343,7 @@ rtw89_early_fw_feature_recognize(struct device *device,
rtw89_fw_iterate_feature_cfg(early_fw, chip, ver_code);
out:
- if (full_req)
- return firmware;
-
- release_firmware(firmware);
- return NULL;
+ return firmware;
}
int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
@@ -807,7 +793,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
}
skb_put(skb, H2C_BA_CAM_LEN);
SET_BA_CAM_MACID(skb->data, macid);
- if (chip->bacam_v1)
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT)
SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
else
SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
@@ -823,7 +809,7 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
SET_BA_CAM_INIT_REQ(skb->data, 1);
SET_BA_CAM_SSN(skb->data, params->ssn);
- if (chip->bacam_v1) {
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT) {
SET_BA_CAM_STD_EN(skb->data, 1);
SET_BA_CAM_BAND(skb->data, rtwvif->mac_idx);
}
@@ -848,8 +834,8 @@ fail:
return ret;
}
-static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
- u8 entry_idx, u8 uid)
+static int rtw89_fw_h2c_init_ba_cam_v0_ext(struct rtw89_dev *rtwdev,
+ u8 entry_idx, u8 uid)
{
struct sk_buff *skb;
int ret;
@@ -886,7 +872,7 @@ fail:
return ret;
}
-void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
+void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u8 entry_idx = chip->bacam_num;
@@ -894,7 +880,7 @@ void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
int i;
for (i = 0; i < chip->bacam_dynamic_num; i++) {
- rtw89_fw_h2c_init_dynamic_ba_cam_v1(rtwdev, entry_idx, uid);
+ rtw89_fw_h2c_init_ba_cam_v0_ext(rtwdev, entry_idx, uid);
entry_idx++;
uid++;
}
@@ -997,8 +983,8 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
list_for_each_entry_safe(info, tmp, pkt_list, list) {
if (notify_fw)
rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
- rtw89_core_release_bit_map(rtwdev->pkt_offload,
- info->id);
+ else
+ rtw89_core_release_bit_map(rtwdev->pkt_offload, info->id);
list_del(&info->list);
kfree(info);
}
@@ -2440,7 +2426,9 @@ fail:
#define H2C_LEN_PKT_OFLD 4
int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct sk_buff *skb;
+ unsigned int cond;
u8 *cmd;
int ret;
@@ -2460,23 +2448,26 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
- if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(id, RTW89_PKT_OFLD_OP_DEL);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
+ if (ret < 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "failed to del pkt ofld: id %d, ret %d\n",
+ id, ret);
+ return ret;
}
+ rtw89_core_release_bit_map(rtwdev->pkt_offload, id);
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
struct sk_buff *skb_ofld)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct sk_buff *skb;
+ unsigned int cond;
u8 *cmd;
u8 alloc_id;
int ret;
@@ -2507,27 +2498,29 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD + skb_ofld->len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
- if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(alloc_id, RTW89_PKT_OFLD_OP_ADD);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
+ if (ret < 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "failed to add pkt ofld: id %d, ret %d\n",
+ alloc_id, ret);
rtw89_core_release_bit_map(rtwdev->pkt_offload, alloc_id);
- goto fail;
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
#define H2C_LEN_SCAN_LIST_OFFLOAD 4
int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
struct list_head *chan_list)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_mac_chinfo *ch_info;
struct sk_buff *skb;
int skb_len = H2C_LEN_SCAN_LIST_OFFLOAD + len * RTW89_MAC_CHINFO_SIZE;
+ unsigned int cond;
u8 *cmd;
int ret;
@@ -2574,27 +2567,27 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
H2C_FUNC_ADD_SCANOFLD_CH, 1, 1, skb_len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
+ cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_ADD_SCANOFLD_CH);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to add scan ofld ch\n");
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
struct rtw89_scan_option *option,
struct rtw89_vif *rtwvif)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
struct rtw89_h2c_scanofld *h2c;
u32 len = sizeof(*h2c);
struct sk_buff *skb;
+ unsigned int cond;
int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
@@ -2633,17 +2626,15 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
H2C_FUNC_SCANOFLD, 1, 1,
len);
- ret = rtw89_h2c_tx(rtwdev, skb, false);
+ cond = RTW89_FW_OFLD_WAIT_COND(0, H2C_FUNC_SCANOFLD);
+
+ ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
if (ret) {
- rtw89_err(rtwdev, "failed to send h2c\n");
- goto fail;
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to scan ofld\n");
+ return ret;
}
return 0;
-fail:
- dev_kfree_skb_any(skb);
-
- return ret;
}
int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
@@ -2909,12 +2900,13 @@ static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev,
}
len = DIV_ROUND_UP(info->content_len + RTW89_H2CREG_HDR_LEN,
- sizeof(info->h2creg[0]));
+ sizeof(info->u.h2creg[0]));
+
+ u32p_replace_bits(&info->u.hdr.w0, info->id, RTW89_H2CREG_HDR_FUNC_MASK);
+ u32p_replace_bits(&info->u.hdr.w0, len, RTW89_H2CREG_HDR_LEN_MASK);
- RTW89_SET_H2CREG_HDR_FUNC(&info->h2creg[0], info->id);
- RTW89_SET_H2CREG_HDR_LEN(&info->h2creg[0], len);
for (i = 0; i < RTW89_H2CREG_MAX; i++)
- rtw89_write32(rtwdev, h2c_reg[i], info->h2creg[i]);
+ rtw89_write32(rtwdev, h2c_reg[i], info->u.h2creg[i]);
fw_info->h2c_counter++;
rtw89_write8_mask(rtwdev, chip->h2c_counter_reg.addr,
@@ -2944,13 +2936,14 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev,
}
for (i = 0; i < RTW89_C2HREG_MAX; i++)
- info->c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]);
+ info->u.c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]);
rtw89_write8(rtwdev, chip->c2h_ctrl_reg, 0);
- info->id = RTW89_GET_C2H_HDR_FUNC(*info->c2hreg);
- info->content_len = (RTW89_GET_C2H_HDR_LEN(*info->c2hreg) << 2) -
- RTW89_C2HREG_HDR_LEN;
+ info->id = u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_FUNC_MASK);
+ info->content_len =
+ (u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_LEN_MASK) << 2) -
+ RTW89_C2HREG_HDR_LEN;
fw_info->c2h_counter++;
rtw89_write8_mask(rtwdev, chip->c2h_counter_reg.addr,
@@ -3019,9 +3012,8 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
continue;
list_for_each_entry_safe(info, tmp, &pkt_list[idx], list) {
- rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
- rtw89_core_release_bit_map(rtwdev->pkt_offload,
- info->id);
+ if (test_bit(info->id, rtwdev->pkt_offload))
+ rtw89_fw_h2c_del_pkt_offload(rtwdev, info->id);
list_del(&info->list);
kfree(info);
}
@@ -3786,6 +3778,11 @@ fail:
return ret;
}
+/* Return < 0, if failures happen during waiting for the condition.
+ * Return 0, when waiting for the condition succeeds.
+ * Return > 0, if the wait is considered unreachable due to driver/FW design,
+ * where 1 means during SER.
+ */
static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
struct rtw89_wait_info *wait, unsigned int cond)
{
@@ -3798,6 +3795,9 @@ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
return -EBUSY;
}
+ if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
+ return 1;
+
return rtw89_wait_for_cond(wait, cond);
}
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 675f85c41471..45f927dc212e 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -18,15 +18,51 @@ enum rtw89_fw_dl_status {
RTW89_FWDL_WCPU_FW_INIT_RDY = 7
};
-#define RTW89_GET_C2H_HDR_FUNC(info) \
- u32_get_bits(info, GENMASK(6, 0))
-#define RTW89_GET_C2H_HDR_LEN(info) \
- u32_get_bits(info, GENMASK(11, 8))
+struct rtw89_c2hreg_hdr {
+ u32 w0;
+};
+
+#define RTW89_C2HREG_HDR_FUNC_MASK GENMASK(6, 0)
+#define RTW89_C2HREG_HDR_ACK BIT(7)
+#define RTW89_C2HREG_HDR_LEN_MASK GENMASK(11, 8)
+#define RTW89_C2HREG_HDR_SEQ_MASK GENMASK(15, 12)
+
+struct rtw89_c2hreg_phycap {
+ u32 w0;
+ u32 w1;
+ u32 w2;
+ u32 w3;
+} __packed;
+
+#define RTW89_C2HREG_PHYCAP_W0_FUNC GENMASK(6, 0)
+#define RTW89_C2HREG_PHYCAP_W0_ACK BIT(7)
+#define RTW89_C2HREG_PHYCAP_W0_LEN GENMASK(11, 8)
+#define RTW89_C2HREG_PHYCAP_W0_SEQ GENMASK(15, 12)
+#define RTW89_C2HREG_PHYCAP_W0_RX_NSS GENMASK(23, 16)
+#define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24)
+#define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0)
+#define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8)
+#define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16)
+#define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24)
+#define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0)
+#define RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM GENMASK(15, 8)
+#define RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM GENMASK(23, 16)
+
+struct rtw89_h2creg_hdr {
+ u32 w0;
+};
+
+#define RTW89_H2CREG_HDR_FUNC_MASK GENMASK(6, 0)
+#define RTW89_H2CREG_HDR_LEN_MASK GENMASK(11, 8)
-#define RTW89_SET_H2CREG_HDR_FUNC(info, val) \
- u32p_replace_bits(info, val, GENMASK(6, 0))
-#define RTW89_SET_H2CREG_HDR_LEN(info, val) \
- u32p_replace_bits(info, val, GENMASK(11, 8))
+struct rtw89_h2creg_sch_tx_en {
+ u32 w0;
+ u32 w1;
+} __packed;
+
+#define RTW89_H2CREG_SCH_TX_EN_W0_EN GENMASK(31, 16)
+#define RTW89_H2CREG_SCH_TX_EN_W1_MASK GENMASK(15, 0)
+#define RTW89_H2CREG_SCH_TX_EN_W1_BAND BIT(16)
#define RTW89_H2CREG_MAX 4
#define RTW89_C2HREG_MAX 4
@@ -36,13 +72,21 @@ enum rtw89_fw_dl_status {
struct rtw89_mac_c2h_info {
u8 id;
u8 content_len;
- u32 c2hreg[RTW89_C2HREG_MAX];
+ union {
+ u32 c2hreg[RTW89_C2HREG_MAX];
+ struct rtw89_c2hreg_hdr hdr;
+ struct rtw89_c2hreg_phycap phycap;
+ } u;
};
struct rtw89_mac_h2c_info {
u8 id;
u8 content_len;
- u32 h2creg[RTW89_H2CREG_MAX];
+ union {
+ u32 h2creg[RTW89_H2CREG_MAX];
+ struct rtw89_h2creg_hdr hdr;
+ struct rtw89_h2creg_sch_tx_en sch_tx_en;
+ } u;
};
enum rtw89_mac_h2c_type {
@@ -63,33 +107,6 @@ enum rtw89_mac_c2h_type {
RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF
};
-#define RTW89_GET_C2H_PHYCAP_FUNC(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(6, 0))
-#define RTW89_GET_C2H_PHYCAP_ACK(info) \
- u32_get_bits(*((const u32 *)(info)), BIT(7))
-#define RTW89_GET_C2H_PHYCAP_LEN(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(11, 8))
-#define RTW89_GET_C2H_PHYCAP_SEQ(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(15, 12))
-#define RTW89_GET_C2H_PHYCAP_RX_NSS(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(23, 16))
-#define RTW89_GET_C2H_PHYCAP_BW(info) \
- u32_get_bits(*((const u32 *)(info)), GENMASK(31, 24))
-#define RTW89_GET_C2H_PHYCAP_TX_NSS(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(7, 0))
-#define RTW89_GET_C2H_PHYCAP_PROT(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(15, 8))
-#define RTW89_GET_C2H_PHYCAP_NIC(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(23, 16))
-#define RTW89_GET_C2H_PHYCAP_WL_FUNC(info) \
- u32_get_bits(*((const u32 *)(info) + 1), GENMASK(31, 24))
-#define RTW89_GET_C2H_PHYCAP_HW_TYPE(info) \
- u32_get_bits(*((const u32 *)(info) + 2), GENMASK(7, 0))
-#define RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(info) \
- u32_get_bits(*((const u32 *)(info) + 3), GENMASK(15, 8))
-#define RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(info) \
- u32_get_bits(*((const u32 *)(info) + 3), GENMASK(23, 16))
-
enum rtw89_fw_c2h_category {
RTW89_C2H_CAT_TEST,
RTW89_C2H_CAT_MAC,
@@ -138,8 +155,13 @@ enum rtw89_pkt_offload_op {
RTW89_PKT_OFLD_OP_ADD,
RTW89_PKT_OFLD_OP_DEL,
RTW89_PKT_OFLD_OP_READ,
+
+ NUM_OF_RTW89_PKT_OFFLOAD_OP,
};
+#define RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op) \
+ ((pkt_id) * NUM_OF_RTW89_PKT_OFFLOAD_OP + (pkt_op))
+
enum rtw89_scanofld_notify_reason {
RTW89_SCAN_DWELL_NOTIFY,
RTW89_SCAN_PRE_TX_NOTIFY,
@@ -209,17 +231,6 @@ struct rtw89_fw_macid_pause_grp {
__le32 mask_grp[4];
} __packed;
-struct rtw89_h2creg_sch_tx_en {
- u8 func:7;
- u8 ack:1;
- u8 total_len:4;
- u8 seq_num:4;
- u16 tx_en:16;
- u16 mask:16;
- u8 band:1;
- u16 rsvd:15;
-} __packed;
-
#define RTW89_H2C_MAX_SIZE 2048
#define RTW89_CHANNEL_TIME 45
#define RTW89_CHANNEL_TIME_6G 20
@@ -232,7 +243,7 @@ struct rtw89_h2creg_sch_tx_en {
#define RTW89_SCANOFLD_MAX_IE_LEN 512
#define RTW89_SCANOFLD_PKT_NONE 0xFF
#define RTW89_SCANOFLD_DEBUG_MASK 0x1F
-#define RTW89_MAC_CHINFO_SIZE 24
+#define RTW89_MAC_CHINFO_SIZE 28
#define RTW89_SCAN_LIST_GUARD 4
#define RTW89_SCAN_LIST_LIMIT \
((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD)
@@ -277,6 +288,7 @@ struct rtw89_pktofld_info {
u8 ssid_len;
u8 bssid[ETH_ALEN];
u16 channel_6ghz;
+ bool cancel;
};
static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val)
@@ -516,50 +528,58 @@ static inline void RTW89_SET_EDCA_PARAM(void *cmd, u32 val)
#define FWDL_SECURITY_SECTION_TYPE 9
#define FWDL_SECURITY_SIGLEN 512
-#define GET_FWSECTION_HDR_DL_ADDR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr)), GENMASK(31, 0))
-#define GET_FWSECTION_HDR_SECTIONTYPE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(27, 24))
-#define GET_FWSECTION_HDR_SEC_SIZE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 0))
-#define GET_FWSECTION_HDR_CHECKSUM(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(28))
-#define GET_FWSECTION_HDR_REDL(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), BIT(29))
-#define GET_FWSECTION_HDR_MSSC(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 2), GENMASK(31, 0))
-
-#define GET_FW_HDR_MAJOR_VERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(7, 0))
-#define GET_FW_HDR_MINOR_VERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(15, 8))
-#define GET_FW_HDR_SUBVERSION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 16))
-#define GET_FW_HDR_SUBINDEX(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(31, 24))
-#define GET_FW_HDR_LEN(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 3), GENMASK(23, 16))
-#define GET_FW_HDR_MONTH(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(7, 0))
-#define GET_FW_HDR_DATE(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(15, 8))
-#define GET_FW_HDR_HOUR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(23, 16))
-#define GET_FW_HDR_MIN(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(31, 24))
-#define GET_FW_HDR_YEAR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 5), GENMASK(31, 0))
-#define GET_FW_HDR_SEC_NUM(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 6), GENMASK(15, 8))
-#define GET_FW_HDR_DYN_HDR(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 7), BIT(16))
-#define GET_FW_HDR_CMD_VERSERION(fwhdr) \
- le32_get_bits(*((const __le32 *)(fwhdr) + 7), GENMASK(31, 24))
-
-#define GET_FW_DYNHDR_LEN(fwdynhdr) \
- le32_get_bits(*((const __le32 *)(fwdynhdr)), GENMASK(31, 0))
-#define GET_FW_DYNHDR_COUNT(fwdynhdr) \
- le32_get_bits(*((const __le32 *)(fwdynhdr) + 1), GENMASK(31, 0))
+struct rtw89_fw_dynhdr_sec {
+ __le32 w0;
+ u8 content[];
+} __packed;
+
+struct rtw89_fw_dynhdr_hdr {
+ __le32 hdr_len;
+ __le32 setcion_count;
+ /* struct rtw89_fw_dynhdr_sec (nested flexible structures) */
+} __packed;
+
+struct rtw89_fw_hdr_section {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+} __packed;
+
+#define FWSECTION_HDR_W0_DL_ADDR GENMASK(31, 0)
+#define FWSECTION_HDR_W1_METADATA GENMASK(31, 24)
+#define FWSECTION_HDR_W1_SECTIONTYPE GENMASK(27, 24)
+#define FWSECTION_HDR_W1_SEC_SIZE GENMASK(23, 0)
+#define FWSECTION_HDR_W1_CHECKSUM BIT(28)
+#define FWSECTION_HDR_W1_REDL BIT(29)
+#define FWSECTION_HDR_W2_MSSC GENMASK(31, 0)
+
+struct rtw89_fw_hdr {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ struct rtw89_fw_hdr_section sections[];
+ /* struct rtw89_fw_dynhdr_hdr (optional) */
+} __packed;
+
+#define FW_HDR_W1_MAJOR_VERSION GENMASK(7, 0)
+#define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8)
+#define FW_HDR_W1_SUBVERSION GENMASK(23, 16)
+#define FW_HDR_W1_SUBINDEX GENMASK(31, 24)
+#define FW_HDR_W3_LEN GENMASK(23, 16)
+#define FW_HDR_W4_MONTH GENMASK(7, 0)
+#define FW_HDR_W4_DATE GENMASK(15, 8)
+#define FW_HDR_W4_HOUR GENMASK(23, 16)
+#define FW_HDR_W4_MIN GENMASK(31, 24)
+#define FW_HDR_W5_YEAR GENMASK(31, 0)
+#define FW_HDR_W6_SEC_NUM GENMASK(15, 8)
+#define FW_HDR_W7_DYN_HDR BIT(16)
+#define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24)
static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val)
{
@@ -3215,16 +3235,17 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb)
#define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2)
#define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN)
-#define RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0))
-#define RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(7, 2))
-#define RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 8))
-#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16))
-#define RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h) \
- le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(31, 24))
+struct rtw89_c2h_done_ack {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_DONE_ACK_W2_CAT GENMASK(1, 0)
+#define RTW89_C2H_DONE_ACK_W2_CLASS GENMASK(7, 2)
+#define RTW89_C2H_DONE_ACK_W2_FUNC GENMASK(15, 8)
+#define RTW89_C2H_DONE_ACK_W2_H2C_RETURN GENMASK(23, 16)
+#define RTW89_C2H_DONE_ACK_W2_H2C_SEQ GENMASK(31, 24)
#define RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0))
@@ -3339,6 +3360,16 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE)
#define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0))
+struct rtw89_c2h_pkt_ofld_rsp {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID GENMASK(7, 0)
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP GENMASK(10, 8)
+#define RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN GENMASK(31, 16)
+
struct rtw89_h2c_bcnfltr {
__le32 w0;
} __packed;
@@ -3369,9 +3400,6 @@ struct rtw89_h2c_ofld {
#define RTW89_H2C_OFLD_W0_TX_TP GENMASK(17, 8)
#define RTW89_H2C_OFLD_W0_RX_TP GENMASK(27, 18)
-#define RTW89_FW_HDR_SIZE 32
-#define RTW89_FW_SECTION_HDR_SIZE 16
-
#define RTW89_MFW_SIG 0xFF
struct rtw89_mfw_info {
@@ -3405,7 +3433,7 @@ struct fwcmd_hdr {
union rtw89_compat_fw_hdr {
struct rtw89_mfw_hdr mfw_hdr;
- u8 fw_hdr[RTW89_FW_HDR_SIZE];
+ struct rtw89_fw_hdr fw_hdr;
};
static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf)
@@ -3497,17 +3525,28 @@ struct rtw89_fw_h2c_rf_reg_info {
/* CLASS 9 - FW offload */
#define H2C_CL_MAC_FW_OFLD 0x9
-#define H2C_FUNC_PACKET_OFLD 0x1
-#define H2C_FUNC_MAC_MACID_PAUSE 0x8
-#define H2C_FUNC_USR_EDCA 0xF
-#define H2C_FUNC_TSF32_TOGL 0x10
-#define H2C_FUNC_OFLD_CFG 0x14
-#define H2C_FUNC_ADD_SCANOFLD_CH 0x16
-#define H2C_FUNC_SCANOFLD 0x17
-#define H2C_FUNC_PKT_DROP 0x1b
-#define H2C_FUNC_CFG_BCNFLTR 0x1e
-#define H2C_FUNC_OFLD_RSSI 0x1f
-#define H2C_FUNC_OFLD_TP 0x20
+enum rtw89_fw_ofld_h2c_func {
+ H2C_FUNC_PACKET_OFLD = 0x1,
+ H2C_FUNC_MAC_MACID_PAUSE = 0x8,
+ H2C_FUNC_USR_EDCA = 0xF,
+ H2C_FUNC_TSF32_TOGL = 0x10,
+ H2C_FUNC_OFLD_CFG = 0x14,
+ H2C_FUNC_ADD_SCANOFLD_CH = 0x16,
+ H2C_FUNC_SCANOFLD = 0x17,
+ H2C_FUNC_PKT_DROP = 0x1b,
+ H2C_FUNC_CFG_BCNFLTR = 0x1e,
+ H2C_FUNC_OFLD_RSSI = 0x1f,
+ H2C_FUNC_OFLD_TP = 0x20,
+
+ NUM_OF_RTW89_FW_OFLD_H2C_FUNC,
+};
+
+#define RTW89_FW_OFLD_WAIT_COND(tag, func) \
+ ((tag) * NUM_OF_RTW89_FW_OFLD_H2C_FUNC + (func))
+
+#define RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op) \
+ RTW89_FW_OFLD_WAIT_COND(RTW89_PKT_OFLD_WAIT_TAG(pkt_id, pkt_op), \
+ H2C_FUNC_PACKET_OFLD)
/* CLASS 10 - Security CAM */
#define H2C_CL_MAC_SEC_CAM 0xa
@@ -3648,7 +3687,7 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw);
int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
bool valid, struct ieee80211_ampdu_params *params);
-void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev);
+void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev);
int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
struct rtw89_lps_parm *lps_param);
@@ -3711,8 +3750,8 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- if (chip->bacam_v1)
- rtw89_fw_h2c_init_ba_cam_v1(rtwdev);
+ if (chip->bacam_ver == RTW89_BACAM_V0_EXT)
+ rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(rtwdev);
}
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 512de491a064..c93e6250cb8b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -644,6 +644,39 @@ static void rtw89_mac_dump_err_status(struct rtw89_dev *rtwdev,
rtw89_info(rtwdev, "<---\n");
}
+static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
+{
+ struct rtw89_ser *ser = &rtwdev->ser;
+ u32 dmac_err, imr, isr;
+ int ret;
+
+ if (rtwdev->chip->chip_id == RTL8852C) {
+ ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
+ if (ret)
+ return true;
+
+ if (err == MAC_AX_ERR_L1_ERR_DMAC) {
+ dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
+ imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR);
+ isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR);
+
+ if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) &&
+ ((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) {
+ set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags);
+ return true;
+ }
+ } else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) {
+ if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
+ return true;
+ } else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) {
+ if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
+ return true;
+ }
+ }
+
+ return false;
+}
+
u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
{
u32 err, err_scnr;
@@ -667,6 +700,9 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
else if (err_scnr == RTW89_RXI300_ERROR)
err = MAC_AX_ERR_RXI300;
+ if (rtw89_mac_suppress_log(rtwdev, err))
+ return err;
+
rtw89_fw_st_dbg_dump(rtwdev);
rtw89_mac_dump_err_status(rtwdev, err);
@@ -676,6 +712,7 @@ EXPORT_SYMBOL(rtw89_mac_get_err_status);
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
{
+ struct rtw89_ser *ser = &rtwdev->ser;
u32 halt;
int ret = 0;
@@ -692,6 +729,11 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
}
rtw89_write32(rtwdev, R_AX_HALT_H2C, err);
+
+ if (ser->prehandle_l1 &&
+ (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
+ return 0;
+
rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);
return 0;
@@ -716,11 +758,8 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev)
if (param_ini.pub_cfg)
param->pub_cfg = *param_ini.pub_cfg;
- if (param_ini.prec_cfg) {
+ if (param_ini.prec_cfg)
param->prec_cfg = *param_ini.prec_cfg;
- rtwdev->hal.sw_amsdu_max_size =
- param->prec_cfg.wp_ch07_prec * HFC_PAGE_UNIT;
- }
if (param_ini.ch_cfg)
param->ch_cfg = param_ini.ch_cfg;
@@ -1479,6 +1518,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
/* 8852B PCIE WOW */
.ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
+ /* 8851B PCIE WOW */
+ .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
};
EXPORT_SYMBOL(rtw89_mac_size);
@@ -1497,7 +1538,6 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
return NULL;
}
- mac->dle_info.wde_pg_size = cfg->wde_size->pge_size;
mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
mac->dle_info.qta_mode = mode;
mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma;
@@ -2484,7 +2524,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx)
u32 reg;
int ret;
- if (chip_id != RTL8852A && chip_id != RTL8852B)
+ if (chip_id != RTL8852B)
return 0;
ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
@@ -2602,9 +2642,11 @@ static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev,
int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_hal *hal = &rtwdev->hal;
const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_mac_c2h_info c2h_info = {0};
+ const struct rtw89_c2hreg_phycap *phycap;
u8 tx_nss;
u8 rx_nss;
u8 tx_ant;
@@ -2615,10 +2657,12 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
if (ret)
return ret;
- tx_nss = RTW89_GET_C2H_PHYCAP_TX_NSS(c2h_info.c2hreg);
- rx_nss = RTW89_GET_C2H_PHYCAP_RX_NSS(c2h_info.c2hreg);
- tx_ant = RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(c2h_info.c2hreg);
- rx_ant = RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(c2h_info.c2hreg);
+ phycap = &c2h_info.u.phycap;
+
+ tx_nss = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_TX_NSS);
+ rx_nss = u32_get_bits(phycap->w0, RTW89_C2HREG_PHYCAP_W0_RX_NSS);
+ tx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM);
+ rx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM);
hal->tx_nss = tx_nss ? min_t(u8, tx_nss, chip->tx_nss) : chip->tx_nss;
hal->rx_nss = rx_nss ? min_t(u8, rx_nss, chip->rx_nss) : chip->rx_nss;
@@ -2633,6 +2677,13 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
hal->tx_path_diversity = true;
}
+ if (chip->rf_path_num == 1) {
+ hal->antenna_tx = RF_A;
+ hal->antenna_rx = RF_A;
+ if ((efuse->rfe_type % 3) == 2)
+ hal->ant_diversity = true;
+ }
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"phycap hal/phy/chip: tx_nss=0x%x/0x%x/0x%x rx_nss=0x%x/0x%x/0x%x\n",
hal->tx_nss, tx_nss, chip->tx_nss,
@@ -2641,6 +2692,7 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
"ant num/bitmap: tx=%d/0x%x rx=%d/0x%x\n",
tx_ant, hal->antenna_tx, rx_ant, hal->antenna_rx);
rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity);
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity);
return 0;
}
@@ -2651,14 +2703,14 @@ static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band,
u32 ret;
struct rtw89_mac_c2h_info c2h_info = {0};
struct rtw89_mac_h2c_info h2c_info = {0};
- struct rtw89_h2creg_sch_tx_en *h2creg =
- (struct rtw89_h2creg_sch_tx_en *)h2c_info.h2creg;
+ struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en;
h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN;
- h2c_info.content_len = sizeof(*h2creg) - RTW89_H2CREG_HDR_LEN;
- h2creg->tx_en = tx_en_u16;
- h2creg->mask = mask_u16;
- h2creg->band = band;
+ h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN;
+
+ u32p_replace_bits(&sch_tx_en->w0, tx_en_u16, RTW89_H2CREG_SCH_TX_EN_W0_EN);
+ u32p_replace_bits(&sch_tx_en->w1, mask_u16, RTW89_H2CREG_SCH_TX_EN_W1_MASK);
+ u32p_replace_bits(&sch_tx_en->w1, band, RTW89_H2CREG_SCH_TX_EN_W1_BAND);
ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
if (ret)
@@ -4331,6 +4383,8 @@ rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
static void
rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
{
+ /* N.B. This will run in interrupt context. */
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"C2H rev ack recv, cat: %d, class: %d, func: %d, seq : %d\n",
RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h->data),
@@ -4340,15 +4394,44 @@ rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
}
static void
-rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
-{
+rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len)
+{
+ /* N.B. This will run in interrupt context. */
+ struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
+ const struct rtw89_c2h_done_ack *c2h =
+ (const struct rtw89_c2h_done_ack *)skb_c2h->data;
+ u8 h2c_cat = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CAT);
+ u8 h2c_class = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CLASS);
+ u8 h2c_func = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_FUNC);
+ u8 h2c_return = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_RETURN);
+ u8 h2c_seq = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_SEQ);
+ struct rtw89_completion_data data = {};
+ unsigned int cond;
+
rtw89_debug(rtwdev, RTW89_DBG_FW,
"C2H done ack recv, cat: %d, class: %d, func: %d, ret: %d, seq : %d\n",
- RTW89_GET_MAC_C2H_DONE_ACK_CAT(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_CLASS(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_FUNC(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_H2C_RETURN(c2h->data),
- RTW89_GET_MAC_C2H_DONE_ACK_H2C_SEQ(c2h->data));
+ h2c_cat, h2c_class, h2c_func, h2c_return, h2c_seq);
+
+ if (h2c_cat != H2C_CAT_MAC)
+ return;
+
+ switch (h2c_class) {
+ default:
+ return;
+ case H2C_CL_MAC_FW_OFLD:
+ switch (h2c_func) {
+ default:
+ return;
+ case H2C_FUNC_ADD_SCANOFLD_CH:
+ case H2C_FUNC_SCANOFLD:
+ cond = RTW89_FW_OFLD_WAIT_COND(0, h2c_func);
+ break;
+ }
+
+ data.err = !!h2c_return;
+ rtw89_complete_cond(fw_ofld_wait, cond, &data);
+ return;
+ }
}
static void
@@ -4364,9 +4447,25 @@ rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
}
static void
-rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
+rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h,
u32 len)
{
+ struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
+ const struct rtw89_c2h_pkt_ofld_rsp *c2h =
+ (const struct rtw89_c2h_pkt_ofld_rsp *)skb_c2h->data;
+ u16 pkt_len = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN);
+ u8 pkt_id = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID);
+ u8 pkt_op = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP);
+ struct rtw89_completion_data data = {};
+ unsigned int cond;
+
+ rtw89_debug(rtwdev, RTW89_DBG_FW, "pkt ofld rsp: id %d op %d len %d\n",
+ pkt_id, pkt_op, pkt_len);
+
+ data.err = !pkt_len;
+ cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op);
+
+ rtw89_complete_cond(wait, cond, &data);
}
static void
@@ -4574,6 +4673,21 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
switch (class) {
default:
return false;
+ case RTW89_MAC_C2H_CLASS_INFO:
+ switch (func) {
+ default:
+ return false;
+ case RTW89_MAC_C2H_FUNC_REC_ACK:
+ case RTW89_MAC_C2H_FUNC_DONE_ACK:
+ return true;
+ }
+ case RTW89_MAC_C2H_CLASS_OFLD:
+ switch (func) {
+ default:
+ return false;
+ case RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP:
+ return true;
+ }
case RTW89_MAC_C2H_CLASS_MCC:
return true;
}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 6ba633ccdd03..0e1570451c2c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -642,6 +642,7 @@ enum mac_ax_err_info {
MAC_AX_ERR_L0_PROMOTE_TO_L1 = 0x0010,
/* L1 */
+ MAC_AX_ERR_L1_PREERR_DMAC = 0x999,
MAC_AX_ERR_L1_ERR_DMAC = 0x1000,
MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE = 0x1001,
MAC_AX_ERR_L1_RESET_RECOVERY_DONE = 0x1002,
@@ -780,6 +781,7 @@ enum mac_ax_err_info {
MAC_AX_ERR_L1_RCVY_EN = 0x0002,
MAC_AX_ERR_L1_RCVY_STOP_REQ = 0x0003,
MAC_AX_ERR_L1_RCVY_START_REQ = 0x0004,
+ MAC_AX_ERR_L1_RESET_START_DMAC = 0x000A,
MAC_AX_ERR_L0_CFG_NOTIFY = 0x0010,
MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011,
MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012,
@@ -819,6 +821,7 @@ struct rtw89_mac_size_set {
const struct rtw89_ple_quota ple_qt58;
const struct rtw89_ple_quota ple_qt_52a_wow;
const struct rtw89_ple_quota ple_qt_52b_wow;
+ const struct rtw89_ple_quota ple_qt_51b_wow;
};
extern const struct rtw89_mac_size_set rtw89_mac_size;
@@ -1115,6 +1118,8 @@ enum rtw89_mac_xtal_si_offset {
XTAL_SI_PWR_CUT = 0x10,
#define XTAL_SI_SMALL_PWR_CUT BIT(0)
#define XTAL_SI_BIG_PWR_CUT BIT(1)
+ XTAL_SI_XTAL_DRV = 0x15,
+#define XTAL_SI_DRV_LATCH BIT(4)
XTAL_SI_XTAL_XMD_2 = 0x24,
#define XTAL_SI_LDO_LPS GENMASK(6, 4)
XTAL_SI_XTAL_XMD_4 = 0x26,
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index c42e31069035..a66503eb35b8 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -146,6 +146,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
rtwvif->phy_idx = RTW89_PHY_0;
rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
rtwvif->hit_rule = 0;
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
ether_addr_copy(rtwvif->mac_addr, vif->addr);
INIT_LIST_HEAD(&rtwvif->general_pkt_list);
@@ -457,8 +458,16 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
{
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ const struct rtw89_chan *chan;
mutex_lock(&rtwdev->mutex);
+
+ chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
+ if (chan->band_type == RTW89_BAND_6G) {
+ mutex_unlock(&rtwdev->mutex);
+ return -EOPNOTSUPP;
+ }
+
ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid);
rtw89_cam_bssid_changed(rtwdev, rtwvif);
rtw89_mac_port_update(rtwdev, rtwvif);
@@ -759,13 +768,18 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
struct rtw89_dev *rtwdev = hw->priv;
struct rtw89_hal *hal = &rtwdev->hal;
- if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx)
+ if (hal->ant_diversity) {
+ if (tx_ant != rx_ant || hweight32(tx_ant) != 1)
+ return -EINVAL;
+ } else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) {
return -EINVAL;
+ }
mutex_lock(&rtwdev->mutex);
hal->antenna_tx = tx_ant;
hal->antenna_rx = rx_ant;
hal->tx_path_diversity = false;
+ hal->ant_diversity_fixed = true;
mutex_unlock(&rtwdev->mutex);
return 0;
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 70b4754667c9..3a4bfc44142b 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -265,7 +265,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
goto err_sync_device;
}
- rtw89_core_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size);
+ rtw89_chip_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size);
new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size);
if (!new)
@@ -274,9 +274,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
rx_ring->diliver_skb = new;
/* first segment has RX desc */
- offset = desc_info->offset;
- offset += desc_info->long_rxdesc ? sizeof(struct rtw89_rxdesc_long) :
- sizeof(struct rtw89_rxdesc_short);
+ offset = desc_info->offset + desc_info->rxd_len;
} else {
offset = sizeof(struct rtw89_pci_rxbd_info);
if (!new) {
@@ -546,12 +544,10 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev,
return cnt;
}
- rtw89_core_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size);
+ rtw89_chip_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size);
/* first segment has RX desc */
- offset = desc_info.offset;
- offset += desc_info.long_rxdesc ? sizeof(struct rtw89_rxdesc_long) :
- sizeof(struct rtw89_rxdesc_short);
+ offset = desc_info.offset + desc_info.rxd_len;
for (; offset + rpp_size <= rx_info->len; offset += rpp_size) {
rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset);
rtw89_pci_release_rpp(rtwdev, rpp);
@@ -1003,10 +999,10 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev,
min_cnt = min(bd_cnt, wd_cnt);
if (min_cnt == 0) {
/* This message can be frequently shown in low power mode or
- * high traffic with 8852B, and we have recognized it as normal
+ * high traffic with small FIFO chips, and we have recognized it as normal
* behavior, so print with mask RTW89_DBG_TXRX in these situations.
*/
- if (rtwpci->low_power || chip->chip_id == RTL8852B)
+ if (rtwpci->low_power || chip->small_fifo_size)
debug_mask = RTW89_DBG_TXRX;
else
debug_mask = RTW89_DBG_UNEXP;
@@ -3216,11 +3212,16 @@ static void rtw89_pci_clear_resource(struct rtw89_dev *rtwdev,
void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev)
{
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u32 hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN;
+
+ if (chip->chip_id == RTL8851B)
+ hs0isr_ind_int_en = B_AX_HS0ISR_IND_INT_EN_WKARND;
rtwpci->halt_c2h_intrs = B_AX_HALT_C2H_INT_EN | 0;
if (rtwpci->under_recovery) {
- rtwpci->intrs[0] = B_AX_HS0ISR_IND_INT_EN;
+ rtwpci->intrs[0] = hs0isr_ind_int_en;
rtwpci->intrs[1] = 0;
} else {
rtwpci->intrs[0] = B_AX_TXDMA_STUCK_INT_EN |
@@ -3230,7 +3231,7 @@ void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev)
B_AX_RXDMA_STUCK_INT_EN |
B_AX_RDU_INT_EN |
B_AX_RPQBD_FULL_INT_EN |
- B_AX_HS0ISR_IND_INT_EN;
+ hs0isr_ind_int_en;
rtwpci->intrs[1] = B_AX_HC10ISR_IND_INT_EN;
}
@@ -3938,5 +3939,5 @@ void rtw89_pci_remove(struct pci_dev *pdev)
EXPORT_SYMBOL(rtw89_pci_remove);
MODULE_AUTHOR("Realtek Corporation");
-MODULE_DESCRIPTION("Realtek 802.11ax wireless PCI driver");
+MODULE_DESCRIPTION("Realtek PCI 802.11ax wireless driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 0e4bd210b100..2f3d1ad3b0f7 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -150,6 +150,7 @@
#define B_AX_HD1ISR_IND_INT_EN BIT(26)
#define B_AX_HD0ISR_IND_INT_EN BIT(25)
#define B_AX_HS0ISR_IND_INT_EN BIT(24)
+#define B_AX_HS0ISR_IND_INT_EN_WKARND BIT(23)
#define B_AX_RETRAIN_INT_EN BIT(21)
#define B_AX_RPQBD_FULL_INT_EN BIT(20)
#define B_AX_RDU_INT_EN BIT(19)
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index c7e906123416..fb15c852fdd4 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -10,6 +10,7 @@
#include "ps.h"
#include "reg.h"
#include "sar.h"
+#include "txrx.h"
#include "util.h"
static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
@@ -1400,7 +1401,8 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x3);
rtw89_phy_write32_set(rtwdev, R_GNT_BT_WGT_EN, 0x1);
rtw89_phy_write32_set(rtwdev, R_P0_PATH_RST, 0x8000000);
- rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
+ if (chip->chip_id != RTL8851B)
+ rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
if (chip->chip_id == RTL8852B)
rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x2);
@@ -1414,6 +1416,9 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
nctl_table = chip->nctl_table;
rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL);
+
+ if (chip->nctl_post_table)
+ rtw89_rfk_parser(rtwdev, chip->nctl_post_table);
}
static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr)
@@ -1489,19 +1494,19 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
-static const u8 rtw89_rs_idx_max[] = {
- [RTW89_RS_CCK] = RTW89_RATE_CCK_MAX,
- [RTW89_RS_OFDM] = RTW89_RATE_OFDM_MAX,
- [RTW89_RS_MCS] = RTW89_RATE_MCS_MAX,
- [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_MAX,
- [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_MAX,
+static const u8 rtw89_rs_idx_num[] = {
+ [RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
+ [RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
+ [RTW89_RS_MCS] = RTW89_RATE_MCS_NUM,
+ [RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_NUM,
+ [RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM,
};
-static const u8 rtw89_rs_nss_max[] = {
+static const u8 rtw89_rs_nss_num[] = {
[RTW89_RS_CCK] = 1,
[RTW89_RS_OFDM] = 1,
- [RTW89_RS_MCS] = RTW89_NSS_MAX,
- [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_MAX,
+ [RTW89_RS_MCS] = RTW89_NSS_NUM,
+ [RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_NUM,
[RTW89_RS_OFFSET] = 1,
};
@@ -1514,9 +1519,9 @@ static const u8 _byr_of_rs[] = {
};
#define _byr_seek(rs, raw) ((s8 *)(raw) + _byr_of_rs[rs])
-#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_max[rs] + (idx))
+#define _byr_idx(rs, nss, idx) ((nss) * rtw89_rs_idx_num[rs] + (idx))
#define _byr_chk(rs, nss, idx) \
- ((nss) < rtw89_rs_nss_max[rs] && (idx) < rtw89_rs_idx_max[rs])
+ ((nss) < rtw89_rs_nss_num[rs] && (idx) < rtw89_rs_idx_num[rs])
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl)
@@ -1621,8 +1626,10 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 reg6 = regulatory->reg_6ghz_power;
s8 lmt = 0, sar;
switch (band) {
@@ -1641,11 +1648,13 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
if (lmt)
break;
- lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
+ lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW]
+ [RTW89_REG_6GHZ_POWER_DFLT]
+ [ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -1872,8 +1881,10 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 reg6 = regulatory->reg_6ghz_power;
s8 lmt_ru = 0, sar;
switch (band) {
@@ -1892,11 +1903,13 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
break;
case RTW89_BAND_6G:
- lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
if (lmt_ru)
break;
- lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
+ lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW]
+ [RTW89_REG_6GHZ_POWER_DFLT]
+ [ch_idx];
break;
default:
rtw89_warn(rtwdev, "unknown band type: %d\n", band);
@@ -2071,19 +2084,19 @@ void rtw89_phy_set_txpwr_byrate(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] set txpwr byrate with ch=%d\n", ch);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_CCK] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_OFDM] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_MCS] % 4);
- BUILD_BUG_ON(rtw89_rs_idx_max[RTW89_RS_HEDCM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_CCK] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_OFDM] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_MCS] % 4);
+ BUILD_BUG_ON(rtw89_rs_idx_num[RTW89_RS_HEDCM] % 4);
addr = R_AX_PWR_BY_RATE;
for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) {
for (i = 0; i < ARRAY_SIZE(rs); i++) {
- if (cur.nss >= rtw89_rs_nss_max[rs[i]])
+ if (cur.nss >= rtw89_rs_nss_num[rs[i]])
continue;
cur.rs = rs[i];
- for (cur.idx = 0; cur.idx < rtw89_rs_idx_max[rs[i]];
+ for (cur.idx = 0; cur.idx < rtw89_rs_idx_num[rs[i]];
cur.idx++) {
v[cur.idx % 4] =
rtw89_phy_read_txpwr_byrate(rtwdev,
@@ -2116,15 +2129,15 @@ void rtw89_phy_set_txpwr_offset(struct rtw89_dev *rtwdev,
.rs = RTW89_RS_OFFSET,
};
u8 band = chan->band_type;
- s8 v[RTW89_RATE_OFFSET_MAX] = {};
+ s8 v[RTW89_RATE_OFFSET_NUM] = {};
u32 val;
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
- for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++)
+ for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM; desc.idx++)
v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
- BUILD_BUG_ON(RTW89_RATE_OFFSET_MAX != 5);
+ BUILD_BUG_ON(RTW89_RATE_OFFSET_NUM != 5);
val = FIELD_PREP(GENMASK(3, 0), v[0]) |
FIELD_PREP(GENMASK(7, 4), v[1]) |
FIELD_PREP(GENMASK(11, 8), v[2]) |
@@ -2338,27 +2351,29 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
static u8 rtw89_phy_cfo_get_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo)
{
+ const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
u32 reg_mask;
if (sc_xo)
- reg_mask = B_AX_XTAL_SC_XO_MASK;
+ reg_mask = xtal->sc_xo_mask;
else
- reg_mask = B_AX_XTAL_SC_XI_MASK;
+ reg_mask = xtal->sc_xi_mask;
- return (u8)rtw89_read32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask);
+ return (u8)rtw89_read32_mask(rtwdev, xtal->xcap_reg, reg_mask);
}
static void rtw89_phy_cfo_set_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo,
u8 val)
{
+ const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
u32 reg_mask;
if (sc_xo)
- reg_mask = B_AX_XTAL_SC_XO_MASK;
+ reg_mask = xtal->sc_xo_mask;
else
- reg_mask = B_AX_XTAL_SC_XI_MASK;
+ reg_mask = xtal->sc_xi_mask;
- rtw89_write32_mask(rtwdev, R_AX_XTAL_ON_CTRL0, reg_mask, val);
+ rtw89_write32_mask(rtwdev, xtal->xcap_reg, reg_mask, val);
}
static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
@@ -2371,7 +2386,7 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
if (!force && cfo->crystal_cap == crystal_cap)
return;
crystal_cap = clamp_t(u8, crystal_cap, 0, 127);
- if (chip->chip_id == RTL8852A) {
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) {
rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
@@ -2946,6 +2961,126 @@ static void rtw89_phy_ul_tb_info_init(struct rtw89_dev *rtwdev)
rtw89_phy_read32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN);
}
+static
+void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts)
+{
+ ewma_rssi_init(&antdiv_sts->cck_rssi_avg);
+ ewma_rssi_init(&antdiv_sts->ofdm_rssi_avg);
+ ewma_rssi_init(&antdiv_sts->non_legacy_rssi_avg);
+ antdiv_sts->pkt_cnt_cck = 0;
+ antdiv_sts->pkt_cnt_ofdm = 0;
+ antdiv_sts->pkt_cnt_non_legacy = 0;
+ antdiv_sts->evm = 0;
+}
+
+static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct rtw89_antdiv_stats *stats)
+{
+ if (GET_DATA_RATE_MODE(phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) {
+ if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) {
+ ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_cck++;
+ } else {
+ ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_ofdm++;
+ stats->evm += phy_ppdu->ofdm.evm_min;
+ }
+ } else {
+ ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg);
+ stats->pkt_cnt_non_legacy++;
+ stats->evm += phy_ppdu->ofdm.evm_min;
+ }
+}
+
+static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stats)
+{
+ if (stats->pkt_cnt_non_legacy >= stats->pkt_cnt_cck &&
+ stats->pkt_cnt_non_legacy >= stats->pkt_cnt_ofdm)
+ return ewma_rssi_read(&stats->non_legacy_rssi_avg);
+ else if (stats->pkt_cnt_ofdm >= stats->pkt_cnt_cck &&
+ stats->pkt_cnt_ofdm >= stats->pkt_cnt_non_legacy)
+ return ewma_rssi_read(&stats->ofdm_rssi_avg);
+ else
+ return ewma_rssi_read(&stats->cck_rssi_avg);
+}
+
+static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats)
+{
+ return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm);
+}
+
+void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (!hal->ant_diversity || hal->ant_diversity_fixed)
+ return;
+
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->target_stats);
+
+ if (!antdiv->get_stats)
+ return;
+
+ if (hal->antenna_rx == RF_A)
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->main_stats);
+ else if (hal->antenna_rx == RF_B)
+ rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->aux_stats);
+}
+
+static void rtw89_phy_antdiv_reg_init(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_ANT_TRAIN_EN,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_TX_ANT_SEL,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_TRSW_TX_EXTEND,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_HW_ANTSW_DIS_BY_GNT_BT,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_BT_FORCE_ANTIDX_EN,
+ 0x0, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_RFSW_CTRL_ANT0_BASE, B_RFSW_CTRL_ANT_MAPPING,
+ 0x0100, RTW89_PHY_0);
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_BTG_TRX,
+ 0x1, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_HW_CTRL,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_2G,
+ 0x0, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_5G,
+ 0x0, RTW89_PHY_0);
+}
+
+static void rtw89_phy_antdiv_sts_reset(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->main_stats);
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->aux_stats);
+}
+
+static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ if (!hal->ant_diversity)
+ return;
+
+ antdiv->get_stats = false;
+ antdiv->rssi_pre = 0;
+ rtw89_phy_antdiv_sts_reset(rtwdev);
+ rtw89_phy_antdiv_reg_init(rtwdev);
+}
+
static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
{
struct rtw89_phy_stat *phystat = &rtwdev->phystat;
@@ -3053,11 +3188,8 @@ static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev)
env->ccx_manual_ctrl = false;
env->ccx_ongoing = false;
env->ccx_rac_lv = RTW89_RAC_RELEASE;
- env->ccx_rpt_stamp = 0;
env->ccx_period = 0;
env->ccx_unit_idx = RTW89_CCX_32_US;
- env->ccx_trigger_time = 0;
- env->ccx_edcca_opt_bw_idx = RTW89_CCX_EDCCA_BW20_0;
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_EN_MSK, 1);
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_CCX_TRIG_OPT_MSK, 1);
@@ -3265,7 +3397,6 @@ static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev)
rtw89_phy_set_phy_regs(rtwdev, R_IFS_COUNTER, B_IFS_COUNTER_CLR_MSK, 1);
rtw89_phy_set_phy_regs(rtwdev, R_CCX, B_MEASUREMENT_TRIG_MSK, 1);
- env->ccx_rpt_stamp++;
env->ccx_ongoing = true;
}
@@ -4114,6 +4245,144 @@ void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
&done);
}
+#define ANTDIV_MAIN 0
+#define ANTDIV_AUX 1
+
+static void rtw89_phy_antdiv_set_ant(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 default_ant, optional_ant;
+
+ if (!hal->ant_diversity || hal->antenna_tx == 0)
+ return;
+
+ if (hal->antenna_tx == RF_B) {
+ default_ant = ANTDIV_AUX;
+ optional_ant = ANTDIV_MAIN;
+ } else {
+ default_ant = ANTDIV_MAIN;
+ optional_ant = ANTDIV_AUX;
+ }
+
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_CGCS_CTRL,
+ default_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ORI,
+ default_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ALT,
+ optional_ant, RTW89_PHY_0);
+ rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_TX_ORI,
+ default_ant, RTW89_PHY_0);
+}
+
+static void rtw89_phy_swap_hal_antenna(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+
+ hal->antenna_rx = hal->antenna_rx == RF_A ? RF_B : RF_A;
+ hal->antenna_tx = hal->antenna_rx;
+}
+
+static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ bool no_change = false;
+ u8 main_rssi, aux_rssi;
+ u8 main_evm, aux_evm;
+ u32 candidate;
+
+ antdiv->get_stats = false;
+ antdiv->training_count = 0;
+
+ main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats);
+ main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats);
+ aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats);
+ aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats);
+
+ if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH)
+ candidate = RF_A;
+ else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH)
+ candidate = RF_B;
+ else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_A;
+ else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_B;
+ else
+ no_change = true;
+
+ if (no_change) {
+ /* swap back from training antenna to original */
+ rtw89_phy_swap_hal_antenna(rtwdev);
+ return;
+ }
+
+ hal->antenna_tx = candidate;
+ hal->antenna_rx = candidate;
+}
+
+static void rtw89_phy_antdiv_training_state(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ u64 state_period;
+
+ if (antdiv->training_count % 2 == 0) {
+ if (antdiv->training_count == 0)
+ rtw89_phy_antdiv_sts_reset(rtwdev);
+
+ antdiv->get_stats = true;
+ state_period = msecs_to_jiffies(ANTDIV_TRAINNING_INTVL);
+ } else {
+ antdiv->get_stats = false;
+ state_period = msecs_to_jiffies(ANTDIV_DELAY);
+
+ rtw89_phy_swap_hal_antenna(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
+ }
+
+ antdiv->training_count++;
+ ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work,
+ state_period);
+}
+
+void rtw89_phy_antdiv_work(struct work_struct *work)
+{
+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
+ antdiv_work.work);
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+
+ mutex_lock(&rtwdev->mutex);
+
+ if (antdiv->training_count <= ANTDIV_TRAINNING_CNT) {
+ rtw89_phy_antdiv_training_state(rtwdev);
+ } else {
+ rtw89_phy_antdiv_decision_state(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
+ }
+
+ mutex_unlock(&rtwdev->mutex);
+}
+
+void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u8 rssi, rssi_pre;
+
+ if (!hal->ant_diversity || hal->ant_diversity_fixed)
+ return;
+
+ rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->target_stats);
+ rssi_pre = antdiv->rssi_pre;
+ antdiv->rssi_pre = rssi;
+ rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
+
+ if (abs((int)rssi - (int)rssi_pre) < ANTDIV_RSSI_DIFF_TH)
+ return;
+
+ antdiv->training_count = 0;
+ ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work, 0);
+}
+
static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
{
rtw89_phy_ccx_top_setting_init(rtwdev);
@@ -4133,6 +4402,9 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
rtw89_phy_dig_init(rtwdev);
rtw89_phy_cfo_init(rtwdev);
rtw89_phy_ul_tb_info_init(rtwdev);
+ rtw89_phy_antdiv_init(rtwdev);
+ rtw89_chip_rfe_gpio(rtwdev);
+ rtw89_phy_antdiv_set_ant(rtwdev);
rtw89_phy_init_rf_nctl(rtwdev);
rtw89_chip_rfk_init(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 7535867d0f48..ab174a0ba488 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -67,6 +67,14 @@
#define UL_TB_TF_CNT_L2H_TH 100
#define UL_TB_TF_CNT_H2L_TH 70
+#define ANTDIV_TRAINNING_CNT 2
+#define ANTDIV_TRAINNING_INTVL 30
+#define ANTDIV_DELAY 110
+#define ANTDIV_TP_DIFF_TH_HIGH 100
+#define ANTDIV_TP_DIFF_TH_LOW 5
+#define ANTDIV_EVM_DIFF_TH 8
+#define ANTDIV_RSSI_DIFF_TH 3
+
#define CCX_MAX_PERIOD 2097
#define CCX_MAX_PERIOD_UNIT 32
#define MS_TO_4US_RATIO 250
@@ -549,6 +557,10 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev);
void rtw89_phy_dig(struct rtw89_dev *rtwdev);
void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev);
+void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu);
+void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev);
+void rtw89_phy_antdiv_work(struct work_struct *work);
void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
enum rtw89_mac_idx mac_idx,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 266e4231b5f3..55595fde7494 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -19,6 +19,8 @@
#define B_AX_FEN_BBRSTB BIT(0)
#define R_AX_SYS_PW_CTRL 0x0004
+#define B_AX_SOP_ASWRM BIT(31)
+#define B_AX_SOP_PWMM_DSWR BIT(29)
#define B_AX_XTAL_OFF_A_DIE BIT(22)
#define B_AX_DIS_WLBT_PDNSUSEN_SOPC BIT(18)
#define B_AX_RDY_SYSPWR BIT(17)
@@ -134,6 +136,8 @@
#define B_AX_PLATFORM_EN BIT(0)
#define R_AX_WLLPS_CTRL 0x0090
+#define B_AX_LPSOP_ASWRM BIT(17)
+#define B_AX_LPSOP_DSWRM BIT(9)
#define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1)
#define SW_LPS_OPTION 0x0001A0B2
@@ -222,9 +226,14 @@
#define B_AX_OCP_L1_MASK GENMASK(15, 13)
#define B_AX_VOL_L1_MASK GENMASK(3, 0)
+#define R_AX_SPSLDO_ON_CTRL1 0x0204
+#define B_AX_FPWMDELAY BIT(3)
+
#define R_AX_LDO_AON_CTRL0 0x0218
#define B_AX_PD_REGU_L BIT(16)
+#define R_AX_SPSANA_ON_CTRL1 0x0224
+
#define R_AX_WLAN_XTAL_SI_CTRL 0x0270
#define B_AX_WL_XTAL_SI_CMD_POLL BIT(31)
#define B_AX_BT_XTAL_SI_ERR_FLAG BIT(30)
@@ -237,17 +246,30 @@
#define B_AX_WL_XTAL_SI_DATA_MASK GENMASK(15, 8)
#define B_AX_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0)
+#define R_AX_WLAN_XTAL_SI_CONFIG 0x0274
+#define B_AX_XTAL_SI_ADDR_NOT_CHK BIT(0)
+
#define R_AX_XTAL_ON_CTRL0 0x0280
#define B_AX_XTAL_SC_LPS BIT(31)
#define B_AX_XTAL_SC_XO_MASK GENMASK(23, 17)
#define B_AX_XTAL_SC_XI_MASK GENMASK(16, 10)
#define B_AX_XTAL_SC_MASK GENMASK(6, 0)
+#define R_AX_XTAL_ON_CTRL3 0x028C
+#define B_AX_XTAL_SC_INIT_A_BLOCK_MASK GENMASK(30, 24)
+#define B_AX_XTAL_SC_LPS_A_BLOCK_MASK GENMASK(22, 16)
+#define B_AX_XTAL_SC_XO_A_BLOCK_MASK GENMASK(14, 8)
+#define B_AX_XTAL_SC_XI_A_BLOCK_MASK GENMASK(6, 0)
+
#define R_AX_GPIO0_7_FUNC_SEL 0x02D0
#define R_AX_EECS_EESK_FUNC_SEL 0x02D8
#define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4)
+#define R_AX_GPIO16_23_FUNC_SEL 0x02D8
+#define B_AX_PINMUX_GPIO17_FUNC_SEL_MASK GENMASK(7, 4)
+#define B_AX_PINMUX_GPIO16_FUNC_SEL_MASK GENMASK(3, 0)
+
#define R_AX_LED1_FUNC_SEL 0x02DC
#define B_AX_PINMUX_EESK_FUNC_SEL_V1_MASK GENMASK(27, 24)
#define PINMUX_EESK_FUNC_SEL_BT_LOG 0x1
@@ -257,6 +279,10 @@
#define B_AX_EESK_PULL_LOW_EN BIT(17)
#define B_AX_EECS_PULL_LOW_EN BIT(16)
+#define R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN 0x02E4
+#define B_AX_GPIO16_PULL_LOW_EN_V1 BIT(19)
+#define B_AX_GPIO10_PULL_LOW_EN BIT(10)
+
#define R_AX_WLRF_CTRL 0x02F0
#define B_AX_AFC_AFEDIG BIT(17)
#define B_AX_WLRF1_CTRL_7 BIT(15)
@@ -3299,10 +3325,36 @@
#define B_AX_TXAGC_BT_EN BIT(1)
#define B_AX_TXAGC_BT_MASK GENMASK(11, 3)
+#define R_AX_PWR_SWING_OTHER_CTRL0 0xD230
+#define R_AX_PWR_SWING_OTHER_CTRL0_C1 0xF230
+#define B_AX_CFIR_BY_RATE_OFF_MASK GENMASK(17, 0)
+
#define R_AX_PWR_UL_CTRL0 0xD240
#define R_AX_PWR_UL_CTRL2 0xD248
#define B_AX_PWR_UL_CFO_MASK GENMASK(2, 0)
#define B_AX_PWR_UL_CTRL2_MASK 0x07700007
+
+#define R_AX_PWR_NORM_FORCE1 0xD260
+#define R_AX_PWR_NORM_FORCE1_C1 0xF260
+#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_EN BIT(29)
+#define B_AX_TXAGC_BF_PWR_BOOST_FORCE_VAL_MASK GENMASK(28, 24)
+#define B_AX_FORCE_HE_ER_SU_EN_EN BIT(23)
+#define B_AX_FORCE_HE_ER_SU_EN_VALUE BIT(22)
+#define B_AX_FORCE_MACID_CCA_TH_EN_EN BIT(21)
+#define B_AX_FORCE_MACID_CCA_TH_EN_VALUE BIT(20)
+#define B_AX_FORCE_BT_GRANT_EN BIT(19)
+#define B_AX_FORCE_BT_GRANT_VALUE BIT(18)
+#define B_AX_FORCE_RX_LTE_EN BIT(17)
+#define B_AX_FORCE_RX_LTE_VALUE BIT(16)
+#define B_AX_FORCE_TXBF_EN_EN BIT(15)
+#define B_AX_FORCE_TXBF_EN_VALUE BIT(14)
+#define B_AX_FORCE_TXSC_EN BIT(13)
+#define B_AX_FORCE_TXSC_VALUE_MASK GENMASK(12, 9)
+#define B_AX_FORCE_NTX_EN BIT(6)
+#define B_AX_FORCE_NTX_VALUE BIT(5)
+#define B_AX_FORCE_PWR_MODE_EN BIT(3)
+#define B_AX_FORCE_PWR_MODE_VALUE_MASK GENMASK(2, 0)
+
#define R_AX_PWR_UL_TB_CTRL 0xD288
#define B_AX_PWR_UL_TB_CTRL_EN BIT(31)
#define R_AX_PWR_UL_TB_1T 0xD28C
@@ -3312,16 +3364,22 @@
#define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0)
#define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0)
#define R_AX_PWR_BY_RATE_TABLE0 0xD2C0
+#define R_AX_PWR_BY_RATE_TABLE6 0xD2D8
#define R_AX_PWR_BY_RATE_TABLE10 0xD2E8
#define R_AX_PWR_BY_RATE R_AX_PWR_BY_RATE_TABLE0
+#define R_AX_PWR_BY_RATE_1SS_MAX R_AX_PWR_BY_RATE_TABLE6
#define R_AX_PWR_BY_RATE_MAX R_AX_PWR_BY_RATE_TABLE10
#define R_AX_PWR_LMT_TABLE0 0xD2EC
+#define R_AX_PWR_LMT_TABLE9 0xD310
#define R_AX_PWR_LMT_TABLE19 0xD338
#define R_AX_PWR_LMT R_AX_PWR_LMT_TABLE0
+#define R_AX_PWR_LMT_1SS_MAX R_AX_PWR_LMT_TABLE9
#define R_AX_PWR_LMT_MAX R_AX_PWR_LMT_TABLE19
#define R_AX_PWR_RU_LMT_TABLE0 0xD33C
+#define R_AX_PWR_RU_LMT_TABLE5 0xD350
#define R_AX_PWR_RU_LMT_TABLE11 0xD368
#define R_AX_PWR_RU_LMT R_AX_PWR_RU_LMT_TABLE0
+#define R_AX_PWR_RU_LMT_1SS_MAX R_AX_PWR_RU_LMT_TABLE5
#define R_AX_PWR_RU_LMT_MAX R_AX_PWR_RU_LMT_TABLE11
#define R_AX_PWR_MACID_LMT_TABLE0 0xD36C
#define R_AX_PWR_MACID_LMT_TABLE127 0xD568
@@ -3574,6 +3632,7 @@
#define RR_MOD_MASK GENMASK(19, 16)
#define RR_MOD_DCK GENMASK(14, 10)
#define RR_MOD_RGM GENMASK(13, 4)
+#define RR_MOD_RXB GENMASK(9, 5)
#define RR_MOD_V_DOWN 0x0
#define RR_MOD_V_STANDBY 0x1
#define RR_TXAGC 0x10001
@@ -3713,6 +3772,7 @@
#define RR_RXBB 0x83
#define RR_RXBB_VOBUF GENMASK(15, 12)
#define RR_RXBB_C2G GENMASK(16, 10)
+#define RR_RXBB_C2 GENMASK(11, 8)
#define RR_RXBB_C1G GENMASK(9, 8)
#define RR_RXBB_FATT GENMASK(7, 0)
#define RR_RXBB_ATTR GENMASK(7, 4)
@@ -3727,6 +3787,7 @@
#define RR_RXA_DPK GENMASK(9, 8)
#define RR_RXA_LNA 0x8b
#define RR_RXA2 0x8c
+#define RR_RAA2_SATT GENMASK(15, 13)
#define RR_RAA2_SWATT GENMASK(15, 9)
#define RR_RXA2_C1 GENMASK(12, 10)
#define RR_RXA2_C2 GENMASK(9, 3)
@@ -3776,19 +3837,26 @@
#define RR_LOGEN 0xa3
#define RR_LOGEN_RPT GENMASK(19, 16)
#define RR_SX 0xaf
+#define RR_IBD 0xc9
+#define RR_IBD_VAL GENMASK(4, 0)
#define RR_LDO 0xb1
#define RR_LDO_SEL GENMASK(8, 6)
#define RR_VCO 0xb2
+#define RR_VCO_SEL GENMASK(9, 8)
+#define RR_VCI 0xb3
+#define RR_VCI_ON BIT(7)
#define RR_LPF 0xb7
#define RR_LPF_BUSY BIT(8)
#define RR_XTALX2 0xb8
#define RR_MALSEL 0xbe
#define RR_SYNFB 0xc5
#define RR_SYNFB_LK BIT(15)
+#define RR_AACK 0xca
#define RR_LCKST 0xcf
#define RR_LCKST_BIN BIT(0)
#define RR_LCK_TRG 0xd3
#define RR_LCK_TRGSEL BIT(8)
+#define RR_LCK_ST BIT(4)
#define RR_MMD 0xd5
#define RR_MMD_RST_EN BIT(8)
#define RR_MMD_RST_SYN BIT(6)
@@ -3807,6 +3875,7 @@
#define RR_CAL_RW BIT(19)
#define RR_LUTWE2 0xee
#define RR_LUTWE2_RTXBW BIT(2)
+#define RR_LUTWE2_DIS BIT(6)
#define RR_LUTWE 0xef
#define RR_LUTWE_LOK BIT(2)
#define RR_RFC 0xf0
@@ -3832,6 +3901,7 @@
#define R_RFE_E_A2 0x0334
#define R_RFE_O_SEL_A2 0x0338
#define R_RFE_SEL0_A2 0x033C
+#define B_RFE_SEL0_MASK GENMASK(1, 0)
#define R_RFE_SEL32_A2 0x0340
#define R_CIRST 0x035c
#define B_CIRST_SYN GENMASK(11, 10)
@@ -3852,6 +3922,9 @@
#define B_ENABLE_CCK BIT(5)
#define R_RSTB_ASYNC 0x0704
#define B_RSTB_ASYNC_ALL BIT(1)
+#define R_P0_ANT_SW 0x0728
+#define B_P0_HW_ANTSW_DIS_BY_GNT_BT BIT(12)
+#define B_P0_TRSW_TX_EXTEND GENMASK(3, 0)
#define R_MAC_PIN_SEL 0x0734
#define B_CH_IDX_SEG0 GENMASK(23, 16)
#define R_PLCP_HISTOGRAM 0x0738
@@ -3961,6 +4034,7 @@
#define R_S0_HW_SI_DIS 0x1200
#define B_S0_HW_SI_DIS_W_R_TRIG GENMASK(30, 28)
#define R_P0_RXCK 0x12A0
+#define B_P0_RXCK_ADJ GENMASK(31, 23)
#define B_P0_RXCK_BW3 BIT(30)
#define B_P0_TXCK_ALL GENMASK(19, 12)
#define B_P0_RXCK_ON BIT(19)
@@ -4034,6 +4108,7 @@
#define R_TXAGC_BB 0x1C60
#define B_TXAGC_BB_OFT GENMASK(31, 16)
#define B_TXAGC_BB GENMASK(31, 24)
+#define B_TXAGC_RF GENMASK(5, 0)
#define R_S0_ADDCK 0x1E00
#define B_S0_ADDCK_I GENMASK(9, 0)
#define B_S0_ADDCK_Q GENMASK(19, 10)
@@ -4117,8 +4192,10 @@
#define R_DCFO 0x4264
#define B_DCFO GENMASK(7, 0)
#define R_SEG0CSI 0x42AC
+#define R_SEG0CSI_V1 0x42B0
#define B_SEG0CSI_IDX GENMASK(10, 0)
#define R_SEG0CSI_EN 0x42C4
+#define R_SEG0CSI_EN_V1 0x42C8
#define B_SEG0CSI_EN BIT(23)
#define R_BSS_CLR_MAP 0x43ac
#define R_BSS_CLR_MAP_V1 0x43B0
@@ -4350,6 +4427,14 @@
#define B_PATH0_BT_BACKOFF_V1 GENMASK(23, 0)
#define R_PATH1_BT_BACKOFF_V1 0x4AEC
#define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0)
+#define R_DCFO_COMP_S0_V2 0x4B20
+#define B_DCFO_COMP_S0_MSK_V2 GENMASK(13, 0)
+#define R_PATH0_TX_CFR 0x4B30
+#define B_PATH0_TX_CFR_LGC1 GENMASK(19, 10)
+#define B_PATH0_TX_CFR_LGC0 GENMASK(9, 0)
+#define R_PATH0_TX_POLAR_CLIPPING 0x4B3C
+#define B_PATH0_TX_POLAR_CLIPPING_LGC1 GENMASK(19, 16)
+#define B_PATH0_TX_POLAR_CLIPPING_LGC0 GENMASK(15, 12)
#define R_PATH0_FRC_FIR_TYPE_V1 0x4C00
#define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
#define R_PATH0_NOTCH 0x4C14
@@ -4455,10 +4540,29 @@
#define B_P0_RFCTM_VAL GENMASK(25, 20)
#define R_P0_RFCTM_RDY BIT(26)
#define R_P0_TRSW 0x5868
-#define B_P0_TRSW_B BIT(0)
-#define B_P0_TRSW_A BIT(1)
+#define B_P0_BT_FORCE_ANTIDX_EN BIT(12)
#define B_P0_TRSW_X BIT(2)
+#define B_P0_TRSW_A BIT(1)
+#define B_P0_TX_ANT_SEL BIT(1)
+#define B_P0_TRSW_B BIT(0)
+#define B_P0_ANT_TRAIN_EN BIT(0)
#define B_P0_TRSW_SO_A2 GENMASK(7, 5)
+#define R_P0_ANTSEL 0x586C
+#define B_P0_ANTSEL_SW_5G BIT(25)
+#define B_P0_ANTSEL_SW_2G BIT(23)
+#define B_P0_ANTSEL_BTG_TRX BIT(21)
+#define B_P0_ANTSEL_CGCS_CTRL BIT(17)
+#define B_P0_ANTSEL_HW_CTRL BIT(16)
+#define B_P0_ANTSEL_TX_ORI GENMASK(15, 12)
+#define B_P0_ANTSEL_RX_ALT GENMASK(11, 8)
+#define B_P0_ANTSEL_RX_ORI GENMASK(7, 4)
+#define R_RFSW_CTRL_ANT0_BASE 0x5870
+#define B_RFSW_CTRL_ANT_MAPPING GENMASK(15, 0)
+#define R_RFE_SEL0_BASE 0x5880
+#define B_RFE_SEL0_SRC_MASK GENMASK(3, 0)
+#define R_RFE_SEL32_BASE 0x5884
+#define RFE_SEL0_SRC_ANTSEL_0 8
+#define R_RFE_INV0 0x5890
#define R_P0_RFM 0x5894
#define B_P0_RFM_DIS_WL BIT(7)
#define B_P0_RFM_TX_OPT BIT(6)
@@ -4572,12 +4676,15 @@
#define IQK_DF4_TXT_8_25MHZ 0x021
#define R_IQK_CFG 0x8034
#define B_IQK_CFG_SET GENMASK(5, 4)
+#define R_IQK_RXA 0x8044
+#define B_IQK_RXAGC GENMASK(15, 13)
#define R_TPG_SEL 0x8068
#define R_TPG_MOD 0x806C
#define B_TPG_MOD_F GENMASK(2, 1)
#define R_MDPK_SYNC 0x8070
#define B_MDPK_SYNC_SEL BIT(31)
#define B_MDPK_SYNC_MAN GENMASK(31, 28)
+#define B_MDPK_SYNC_DMAN GENMASK(30, 28)
#define R_MDPK_RX_DCK 0x8074
#define B_MDPK_RX_DCK_EN BIT(31)
#define R_KIP_MOD 0x8078
@@ -4586,6 +4693,7 @@
#define R_KIP_SYSCFG 0x8088
#define R_KIP_CLK 0x808C
#define R_DPK_IDL 0x809C
+#define B_DPK_IDL_SEL GENMASK(10, 9)
#define B_DPK_IDL BIT(8)
#define R_LDL_NORM 0x80A0
#define B_LDL_NORM_MA BIT(16)
@@ -4604,6 +4712,10 @@
#define B_KIP_RPT1_SEL GENMASK(21, 16)
#define B_KIP_RPT1_SEL_V1 GENMASK(19, 16)
#define R_SRAM_IQRX 0x80D8
+#define R_IDL_MPA 0x80DC
+#define B_IDL_DN BIT(31)
+#define B_IDL_MD530 BIT(1)
+#define B_IDL_MD500 BIT(0)
#define R_GAPK 0x80E0
#define B_GAPK_ADR BIT(0)
#define R_SRAM_IQRX2 0x80E8
@@ -4619,6 +4731,7 @@
#define B_PRT_COM_SYNERR BIT(30)
#define B_PRT_COM_DCI GENMASK(27, 16)
#define B_PRT_COM_CORV GENMASK(15, 8)
+#define B_RPT_COM_RDY GENMASK(15, 0)
#define B_PRT_COM_DCQ GENMASK(11, 0)
#define B_PRT_COM_RXOV BIT(8)
#define B_PRT_COM_GL GENMASK(7, 4)
@@ -4690,6 +4803,7 @@
#define B_DPK_GL_A0 GENMASK(31, 28)
#define B_DPK_GL_A1 GENMASK(17, 0)
#define R_RPT_PER 0x81FC
+#define B_RPT_PER_KSET GENMASK(31, 29)
#define B_RPT_PER_TSSI GENMASK(28, 16)
#define B_RPT_PER_OF GENMASK(15, 8)
#define B_RPT_PER_TH GENMASK(5, 0)
@@ -4730,11 +4844,15 @@
#define B_IQKINF2_KCNT GENMASK(15, 8)
#define B_IQKINF2_NCTLV GENMASK(7, 0)
#define R_DCOF0 0xC000
+#define B_DCOF0_RST BIT(17)
#define B_DCOF0_V GENMASK(4, 1)
#define R_DCOF1 0xC004
+#define B_DCOF1_RST BIT(17)
#define B_DCOF1_S BIT(0)
#define R_DCOF8 0xC020
#define B_DCOF8_V GENMASK(4, 1)
+#define R_DCOF9 0xC024
+#define B_DCOF9_RST BIT(17)
#define R_DACK_S0P0 0xC040
#define B_DACK_S0P0_OK BIT(31)
#define R_DACK_BIAS00 0xc048
@@ -4779,13 +4897,19 @@
#define R_P0_CFCH_BW1 0xC0D8
#define B_P0_CFCH_EX BIT(13)
#define B_P0_CFCH_BW1 GENMASK(8, 5)
+#define R_WDADC 0xC0E4
+#define B_WDADC_SEL GENMASK(5, 4)
#define R_ADCMOD 0xC0E8
#define B_ADCMOD_LP GENMASK(31, 16)
+#define R_DCIM 0xC0EC
+#define B_DCIM_FR GENMASK(14, 13)
#define R_ADDCK0D 0xC0F0
#define B_ADDCK0D_VAL2 GENMASK(31, 26)
#define B_ADDCK0D_VAL GENMASK(25, 16)
+#define B_ADDCK_DS BIT(16)
#define R_ADDCK0 0xC0F4
#define B_ADDCK0_TRG BIT(11)
+#define B_ADDCK0_IQ BIT(10)
#define B_ADDCK0 GENMASK(9, 8)
#define B_ADDCK0_MAN GENMASK(5, 4)
#define B_ADDCK0_EN BIT(4)
@@ -4797,6 +4921,7 @@
#define B_ADDCK0_RL0 GENMASK(17, 8)
#define R_ADDCKR0 0xC0FC
#define B_ADDCKR0_A0 GENMASK(19, 10)
+#define B_ADDCKR0_DC GENMASK(15, 4)
#define B_ADDCKR0_A1 GENMASK(9, 0)
#define R_DACK10 0xC100
#define B_DACK10 GENMASK(4, 1)
@@ -4847,6 +4972,11 @@
#define R_ADDCKR1 0xC1fC
#define B_ADDCKR1_A0 GENMASK(19, 10)
#define B_ADDCKR1_A1 GENMASK(9, 0)
+#define R_DACKN0_CTL 0xC210
+#define B_DACKN0_EN BIT(0)
+#define B_DACKN0_V GENMASK(21, 14)
+#define R_DACKN1_CTL 0xC224
+#define B_DACKN1_V GENMASK(21, 14)
/* WiFi CPU local domain */
#define R_AX_WDT_CTRL 0x0040
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index 6e5a740b128f..34c4d40cfa02 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -2,33 +2,35 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
+#include "acpi.h"
#include "debug.h"
#include "ps.h"
+#include "util.h"
#define COUNTRY_REGD(_alpha2, _txpwr_regd...) \
{.alpha2 = (_alpha2), \
.txpwr_regd = {_txpwr_regd}, \
}
-static const struct rtw89_regulatory rtw89_ww_regd =
+static const struct rtw89_regd rtw89_ww_regd =
COUNTRY_REGD("00", RTW89_WW, RTW89_WW);
-static const struct rtw89_regulatory rtw89_regd_map[] = {
+static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
- COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE),
- COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA),
COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA),
@@ -65,37 +67,37 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK),
COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR),
- COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE),
COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -103,11 +105,11 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN),
- COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC),
- COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -115,55 +117,55 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
+ COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
+ COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC),
- COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_NA),
- COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK),
+ COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("CC", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
+ COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -173,17 +175,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GY", RTW89_NCC, RTW89_NCC, RTW89_NA),
+ COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -194,17 +196,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -218,26 +220,26 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("ST", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -245,7 +247,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA),
COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -254,7 +256,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = {
COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
};
-static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2)
+static const struct rtw89_regd *rtw89_regd_find_reg_by_name(char *alpha2)
{
u32 i;
@@ -266,7 +268,7 @@ static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2)
return &rtw89_ww_regd;
}
-static bool rtw89_regd_is_ww(const struct rtw89_regulatory *regd)
+static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
{
return regd == &rtw89_ww_regd;
}
@@ -282,25 +284,139 @@ do { \
__r->txpwr_regd[RTW89_BAND_6G]); \
} while (0)
+static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
+ struct wiphy *wiphy)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool regd_allow_unii_4 = chip->support_unii4;
+ struct ieee80211_supported_band *sband;
+ int ret;
+ u8 val;
+
+ if (!chip->support_unii4)
+ goto bottom;
+
+ ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_59G_EN, &val);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: cannot eval unii 4: %d\n", ret);
+ goto bottom;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: eval if allow unii 4: %d\n", val);
+
+ switch (val) {
+ case 0:
+ regd_allow_unii_4 = false;
+ break;
+ case 1:
+ regd_allow_unii_4 = true;
+ break;
+ default:
+ break;
+ }
+
+bottom:
+ rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow unii 4: %d\n",
+ regd_allow_unii_4);
+
+ if (regd_allow_unii_4)
+ return;
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+ if (!sband)
+ return;
+
+ sband->n_channels -= 3;
+}
+
+static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
+ bool regd_allow_6ghz = chip_support_6ghz;
+ struct ieee80211_supported_band *sband;
+ int ret;
+ u8 val;
+
+ if (!chip_support_6ghz)
+ goto bottom;
+
+ ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &val);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: cannot eval 6ghz: %d\n", ret);
+ goto bottom;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "acpi: eval if disallow 6ghz: %d\n", val);
+
+ switch (val) {
+ case 0:
+ regd_allow_6ghz = true;
+ break;
+ case 1:
+ regd_allow_6ghz = false;
+ break;
+ default:
+ break;
+ }
+
+bottom:
+ rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
+ regd_allow_6ghz);
+
+ if (regd_allow_6ghz)
+ return;
+
+ sband = wiphy->bands[NL80211_BAND_6GHZ];
+ if (!sband)
+ return;
+
+ wiphy->bands[NL80211_BAND_6GHZ] = NULL;
+ kfree(sband->iftype_data);
+ kfree(sband);
+}
+
+int rtw89_regd_setup(struct rtw89_dev *rtwdev)
+{
+ struct wiphy *wiphy = rtwdev->hw->wiphy;
+
+ if (!wiphy)
+ return -EINVAL;
+
+ rtw89_regd_setup_unii4(rtwdev, wiphy);
+ rtw89_regd_setup_6ghz(rtwdev, wiphy);
+
+ wiphy->reg_notifier = rtw89_regd_notifier;
+ return 0;
+}
+
int rtw89_regd_init(struct rtw89_dev *rtwdev,
void (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{
- const struct rtw89_regulatory *chip_regd;
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ const struct rtw89_regd *chip_regd;
struct wiphy *wiphy = rtwdev->hw->wiphy;
int ret;
+ regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+
if (!wiphy)
return -EINVAL;
chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code);
if (!rtw89_regd_is_ww(chip_regd)) {
- rtwdev->regd = chip_regd;
+ rtwdev->regulatory.regd = chip_regd;
/* Ignore country ie if there is a country domain programmed in chip */
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
- ret = regulatory_hint(rtwdev->hw->wiphy, rtwdev->regd->alpha2);
+ ret = regulatory_hint(rtwdev->hw->wiphy,
+ rtwdev->regulatory.regd->alpha2);
if (ret)
rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
@@ -308,7 +424,7 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev,
return 0;
}
- rtw89_debug_regd(rtwdev, rtwdev->regd,
+ rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
"worldwide roaming chip, follow the setting of stack");
return 0;
}
@@ -317,13 +433,13 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
struct wiphy *wiphy,
struct regulatory_request *request)
{
- rtwdev->regd = rtw89_regd_find_reg_by_name(request->alpha2);
+ rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2);
/* This notification might be set from the system of distros,
* and it does not expect the regulatory will be modified by
* connecting to an AP (i.e. country ie).
*/
if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
- !rtw89_regd_is_ww(rtwdev->regd))
+ !rtw89_regd_is_ww(rtwdev->regulatory.regd))
wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
else
wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
@@ -343,7 +459,8 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
goto exit;
}
rtw89_regd_notifier_apply(rtwdev, wiphy, request);
- rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2",
+ rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
+ "get from initiator %d, alpha2",
request->initiator);
rtw89_core_set_chip_txpwr(rtwdev);
@@ -351,3 +468,66 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
exit:
mutex_unlock(&rtwdev->mutex);
}
+
+static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
+ enum rtw89_reg_6ghz_power sel;
+ const struct rtw89_chan *chan;
+ struct rtw89_vif *rtwvif;
+ int count = 0;
+
+ rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+ chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
+ if (chan->band_type != RTW89_BAND_6G)
+ continue;
+
+ if (count != 0 && rtwvif->reg_6ghz_power == sel)
+ continue;
+
+ sel = rtwvif->reg_6ghz_power;
+ count++;
+ }
+
+ if (count != 1)
+ sel = RTW89_REG_6GHZ_POWER_DFLT;
+
+ if (regulatory->reg_6ghz_power == sel)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_REGD,
+ "recalc 6 GHz reg power type to %d\n", sel);
+
+ regulatory->reg_6ghz_power = sel;
+
+ rtw89_core_set_chip_txpwr(rtwdev);
+}
+
+void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool active)
+{
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+
+ lockdep_assert_held(&rtwdev->mutex);
+
+ if (active) {
+ switch (vif->bss_conf.power_type) {
+ case IEEE80211_REG_VLP_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
+ break;
+ case IEEE80211_REG_LPI_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
+ break;
+ case IEEE80211_REG_SP_AP:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
+ break;
+ default:
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ break;
+ }
+ } else {
+ rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+ }
+
+ __rtw89_reg_6ghz_power_recalc(rtwdev);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
new file mode 100644
index 000000000000..c3ffcb645ebf
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -0,0 +1,2442 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "coex.h"
+#include "efuse.h"
+#include "fw.h"
+#include "mac.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw8851b.h"
+#include "rtw8851b_rfk.h"
+#include "rtw8851b_rfk_table.h"
+#include "rtw8851b_table.h"
+#include "txrx.h"
+#include "util.h"
+
+#define RTW8851B_FW_FORMAT_MAX 0
+#define RTW8851B_FW_BASENAME "rtw89/rtw8851b_fw"
+#define RTW8851B_MODULE_FIRMWARE \
+ RTW8851B_FW_BASENAME ".bin"
+
+static const struct rtw89_hfc_ch_cfg rtw8851b_hfc_chcfg_pcie[] = {
+ {5, 343, grp_0}, /* ACH 0 */
+ {5, 343, grp_0}, /* ACH 1 */
+ {5, 343, grp_0}, /* ACH 2 */
+ {5, 343, grp_0}, /* ACH 3 */
+ {0, 0, grp_0}, /* ACH 4 */
+ {0, 0, grp_0}, /* ACH 5 */
+ {0, 0, grp_0}, /* ACH 6 */
+ {0, 0, grp_0}, /* ACH 7 */
+ {4, 344, grp_0}, /* B0MGQ */
+ {4, 344, grp_0}, /* B0HIQ */
+ {0, 0, grp_0}, /* B1MGQ */
+ {0, 0, grp_0}, /* B1HIQ */
+ {40, 0, 0} /* FWCMDQ */
+};
+
+static const struct rtw89_hfc_pub_cfg rtw8851b_hfc_pubcfg_pcie = {
+ 448, /* Group 0 */
+ 0, /* Group 1 */
+ 448, /* Public Max */
+ 0 /* WP threshold */
+};
+
+static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_pcie[] = {
+ [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_pcie, &rtw8851b_hfc_pubcfg_pcie,
+ &rtw89_mac_size.hfc_preccfg_pcie, RTW89_HCIFC_POH},
+ [RTW89_QTA_DLFW] = {NULL, NULL, &rtw89_mac_size.hfc_preccfg_pcie,
+ RTW89_HCIFC_POH},
+ [RTW89_QTA_INVALID] = {NULL},
+};
+
+static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
+ [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
+ &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+ &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+ &rtw89_mac_size.ple_qt58},
+ [RTW89_QTA_WOW] = {RTW89_QTA_WOW, &rtw89_mac_size.wde_size6,
+ &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+ &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
+ &rtw89_mac_size.ple_qt_51b_wow},
+ [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
+ &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
+ &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13,
+ &rtw89_mac_size.ple_qt13},
+ [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL,
+ NULL},
+};
+
+static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = {
+ {0x46D0, GENMASK(1, 0), 0x3},
+ {0x4AD4, GENMASK(31, 0), 0xf},
+ {0x4688, GENMASK(23, 16), 0x80},
+ {0x4688, GENMASK(31, 24), 0x80},
+ {0x4694, GENMASK(7, 0), 0x80},
+ {0x4694, GENMASK(15, 8), 0x80},
+ {0x4AE4, GENMASK(11, 6), 0x34},
+ {0x4AE4, GENMASK(17, 12), 0x0},
+ {0x469C, GENMASK(31, 26), 0x34},
+};
+
+static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_en_defs);
+
+static const struct rtw89_reg3_def rtw8851b_btc_preagc_dis_defs[] = {
+ {0x46D0, GENMASK(1, 0), 0x0},
+ {0x4AD4, GENMASK(31, 0), 0x60},
+ {0x4688, GENMASK(23, 16), 0x10},
+ {0x4690, GENMASK(31, 24), 0x2a},
+ {0x4694, GENMASK(15, 8), 0x2a},
+ {0x4AE4, GENMASK(11, 6), 0x26},
+ {0x4AE4, GENMASK(17, 12), 0x1e},
+ {0x469C, GENMASK(31, 26), 0x26},
+};
+
+static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_dis_defs);
+
+static const u32 rtw8851b_h2c_regs[RTW89_H2CREG_MAX] = {
+ R_AX_H2CREG_DATA0, R_AX_H2CREG_DATA1, R_AX_H2CREG_DATA2,
+ R_AX_H2CREG_DATA3
+};
+
+static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = {
+ R_AX_C2HREG_DATA0, R_AX_C2HREG_DATA1, R_AX_C2HREG_DATA2,
+ R_AX_C2HREG_DATA3
+};
+
+static const struct rtw89_page_regs rtw8851b_page_regs = {
+ .hci_fc_ctrl = R_AX_HCI_FC_CTRL,
+ .ch_page_ctrl = R_AX_CH_PAGE_CTRL,
+ .ach_page_ctrl = R_AX_ACH0_PAGE_CTRL,
+ .ach_page_info = R_AX_ACH0_PAGE_INFO,
+ .pub_page_info3 = R_AX_PUB_PAGE_INFO3,
+ .pub_page_ctrl1 = R_AX_PUB_PAGE_CTRL1,
+ .pub_page_ctrl2 = R_AX_PUB_PAGE_CTRL2,
+ .pub_page_info1 = R_AX_PUB_PAGE_INFO1,
+ .pub_page_info2 = R_AX_PUB_PAGE_INFO2,
+ .wp_page_ctrl1 = R_AX_WP_PAGE_CTRL1,
+ .wp_page_ctrl2 = R_AX_WP_PAGE_CTRL2,
+ .wp_page_info1 = R_AX_WP_PAGE_INFO1,
+};
+
+static const struct rtw89_reg_def rtw8851b_dcfo_comp = {
+ R_DCFO_COMP_S0_V2, B_DCFO_COMP_S0_MSK_V2
+};
+
+static const struct rtw89_imr_info rtw8851b_imr_info = {
+ .wdrls_imr_set = B_AX_WDRLS_IMR_SET,
+ .wsec_imr_reg = R_AX_SEC_DEBUG,
+ .wsec_imr_set = B_AX_IMR_ERROR,
+ .mpdu_tx_imr_set = 0,
+ .mpdu_rx_imr_set = 0,
+ .sta_sch_imr_set = B_AX_STA_SCHEDULER_IMR_SET,
+ .txpktctl_imr_b0_reg = R_AX_TXPKTCTL_ERR_IMR_ISR,
+ .txpktctl_imr_b0_clr = B_AX_TXPKTCTL_IMR_B0_CLR,
+ .txpktctl_imr_b0_set = B_AX_TXPKTCTL_IMR_B0_SET,
+ .txpktctl_imr_b1_reg = R_AX_TXPKTCTL_ERR_IMR_ISR_B1,
+ .txpktctl_imr_b1_clr = B_AX_TXPKTCTL_IMR_B1_CLR,
+ .txpktctl_imr_b1_set = B_AX_TXPKTCTL_IMR_B1_SET,
+ .wde_imr_clr = B_AX_WDE_IMR_CLR,
+ .wde_imr_set = B_AX_WDE_IMR_SET,
+ .ple_imr_clr = B_AX_PLE_IMR_CLR,
+ .ple_imr_set = B_AX_PLE_IMR_SET,
+ .host_disp_imr_clr = B_AX_HOST_DISP_IMR_CLR,
+ .host_disp_imr_set = B_AX_HOST_DISP_IMR_SET,
+ .cpu_disp_imr_clr = B_AX_CPU_DISP_IMR_CLR,
+ .cpu_disp_imr_set = B_AX_CPU_DISP_IMR_SET,
+ .other_disp_imr_clr = B_AX_OTHER_DISP_IMR_CLR,
+ .other_disp_imr_set = 0,
+ .bbrpt_com_err_imr_reg = R_AX_BBRPT_COM_ERR_IMR_ISR,
+ .bbrpt_chinfo_err_imr_reg = R_AX_BBRPT_CHINFO_ERR_IMR_ISR,
+ .bbrpt_err_imr_set = 0,
+ .bbrpt_dfs_err_imr_reg = R_AX_BBRPT_DFS_ERR_IMR_ISR,
+ .ptcl_imr_clr = B_AX_PTCL_IMR_CLR_ALL,
+ .ptcl_imr_set = B_AX_PTCL_IMR_SET,
+ .cdma_imr_0_reg = R_AX_DLE_CTRL,
+ .cdma_imr_0_clr = B_AX_DLE_IMR_CLR,
+ .cdma_imr_0_set = B_AX_DLE_IMR_SET,
+ .cdma_imr_1_reg = 0,
+ .cdma_imr_1_clr = 0,
+ .cdma_imr_1_set = 0,
+ .phy_intf_imr_reg = R_AX_PHYINFO_ERR_IMR,
+ .phy_intf_imr_clr = 0,
+ .phy_intf_imr_set = 0,
+ .rmac_imr_reg = R_AX_RMAC_ERR_ISR,
+ .rmac_imr_clr = B_AX_RMAC_IMR_CLR,
+ .rmac_imr_set = B_AX_RMAC_IMR_SET,
+ .tmac_imr_reg = R_AX_TMAC_ERR_IMR_ISR,
+ .tmac_imr_clr = B_AX_TMAC_IMR_CLR,
+ .tmac_imr_set = B_AX_TMAC_IMR_SET,
+};
+
+static const struct rtw89_xtal_info rtw8851b_xtal_info = {
+ .xcap_reg = R_AX_XTAL_ON_CTRL3,
+ .sc_xo_mask = B_AX_XTAL_SC_XO_A_BLOCK_MASK,
+ .sc_xi_mask = B_AX_XTAL_SC_XI_A_BLOCK_MASK,
+};
+
+static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = {
+ .ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0},
+ .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
+};
+
+static const struct rtw89_dig_regs rtw8851b_dig_regs = {
+ .seg0_pd_reg = R_SEG0R_PD_V1,
+ .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
+ .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
+ .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
+ .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
+ .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
+ .p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1},
+ .p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1},
+ .p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1},
+ .p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+ .p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V2,
+ B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_ul[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {6, 1, 0, 7},
+ {13, 1, 0, 7},
+ {13, 1, 0, 7}
+};
+
+static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_dl[] = {
+ {255, 0, 0, 7}, /* 0 -> original */
+ {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */
+ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */
+ {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */
+ {255, 1, 0, 7},
+ {255, 1, 0, 7},
+ {255, 1, 0, 7}
+};
+
+static const struct rtw89_btc_fbtc_mreg rtw89_btc_8851b_mon_reg[] = {
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda28),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda2c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda10),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda20),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xcef4),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x8424),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200),
+ RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4738),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4688),
+ RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4694),
+};
+
+static const u8 rtw89_btc_8851b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {70, 60, 50, 40};
+static const u8 rtw89_btc_8851b_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20};
+
+static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ u8 val8;
+ u32 ret;
+
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN |
+ B_AX_AFSM_PCIE_SUS_EN);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_DIS_WLBT_PDNSUSEN_SOPC);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_DIS_WLBT_LPSEN_LOPC);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
+
+ ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR,
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFN_ONMAC),
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+
+ rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_WEI,
+ XTAL_SI_OFF_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_EI,
+ XTAL_SI_OFF_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_RFC2RF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_WEI,
+ XTAL_SI_PON_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_EI,
+ XTAL_SI_PON_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, XTAL_SI_SRAM_DIS);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_DRV, 0, XTAL_SI_DRV_LATCH);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
+ rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE);
+ rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15);
+
+ fsleep(1000);
+
+ rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14);
+ rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK);
+ rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN,
+ B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1);
+
+ if (rtwdev->hal.cv == CHIP_CAV) {
+ ret = rtw89_read_efuse_ver(rtwdev, &val8);
+ if (!ret)
+ rtwdev->hal.cv = val8;
+ }
+
+ rtw89_write32_clr(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG,
+ B_AX_XTAL_SI_ADDR_NOT_CHK);
+ if (rtwdev->hal.cv != CHIP_CAV) {
+ rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY);
+ rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY);
+ }
+
+ rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN,
+ B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN |
+ B_AX_WD_RLS_EN | B_AX_DLE_WDE_EN | B_AX_TXPKT_CTRL_EN |
+ B_AX_STA_SCH_EN | B_AX_DLE_PLE_EN | B_AX_PKT_BUF_EN |
+ B_AX_DMAC_TBL_EN | B_AX_PKT_IN_EN | B_AX_DLE_CPUIO_EN |
+ B_AX_DISPATCHER_EN | B_AX_BBRPT_EN | B_AX_MAC_SEC_EN |
+ B_AX_DMACREG_GCKEN);
+ rtw89_write32_set(rtwdev, R_AX_CMAC_FUNC_EN,
+ B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN |
+ B_AX_FORCE_CMACREG_GCKEN | B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN |
+ B_AX_PTCLTOP_EN | B_AX_SCHEDULER_EN | B_AX_TMAC_EN |
+ B_AX_RMAC_EN);
+
+ rtw89_write32_mask(rtwdev, R_AX_EECS_EESK_FUNC_SEL, B_AX_PINMUX_EESK_FUNC_SEL_MASK,
+ PINMUX_EESK_FUNC_SEL_BT_LOG);
+
+ return 0;
+}
+
+static void rtw8851b_patch_swr_pfm2pwm(struct rtw89_dev *rtwdev)
+{
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_PWMM_DSWR);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_ASWRM);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_DSWRM);
+ rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_ASWRM);
+}
+
+static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev)
+{
+ u32 val32;
+ u32 ret;
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF,
+ XTAL_SI_RFC2RF);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_WEI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, XTAL_SI_RF00);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_SRAM2RFC,
+ XTAL_SI_SRAM2RFC);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_EI);
+ if (ret)
+ return ret;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_WEI);
+ if (ret)
+ return ret;
+
+ rtw89_write32_set(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG,
+ B_AX_XTAL_SI_ADDR_NOT_CHK);
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON);
+ rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB);
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_OFFMAC);
+
+ ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFM_OFFMAC),
+ 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL);
+ if (ret)
+ return ret;
+
+ rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION);
+
+ if (rtwdev->hal.cv == CHIP_CAV) {
+ rtw8851b_patch_swr_pfm2pwm(rtwdev);
+ } else {
+ rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY);
+ rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY);
+ }
+
+ rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS);
+
+ return 0;
+}
+
+static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse,
+ struct rtw8851b_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->e.mac_addr);
+ efuse->rfe_type = map->rfe_type;
+ efuse->xtal_cap = map->xtal_k;
+}
+
+static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
+ struct rtw8851b_efuse *map)
+{
+ struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+ struct rtw8851b_tssi_offset *ofst[] = {&map->path_a_tssi};
+ u8 i, j;
+
+ tssi->thermal[RF_PATH_A] = map->path_a_therm;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi,
+ sizeof(ofst[i]->cck_tssi));
+
+ for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n",
+ i, j, tssi->tssi_cck[i][j]);
+
+ memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi,
+ sizeof(ofst[i]->bw40_tssi));
+ memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM,
+ ofst[i]->bw40_1s_tssi_5g, sizeof(ofst[i]->bw40_1s_tssi_5g));
+
+ for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n",
+ i, j, tssi->tssi_mcs[i][j]);
+ }
+}
+
+static bool _decode_efuse_gain(u8 data, s8 *high, s8 *low)
+{
+ if (high)
+ *high = sign_extend32(u8_get_bits(data, GENMASK(7, 4)), 3);
+ if (low)
+ *low = sign_extend32(u8_get_bits(data, GENMASK(3, 0)), 3);
+
+ return data != 0xff;
+}
+
+static void rtw8851b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+ struct rtw8851b_efuse *map)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ bool valid = false;
+
+ valid |= _decode_efuse_gain(map->rx_gain_2g_cck,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_CCK],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_2g_ofdm,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_OFDM],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_low,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_LOW],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_mid,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_MID],
+ NULL);
+ valid |= _decode_efuse_gain(map->rx_gain_5g_high,
+ &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH],
+ NULL);
+
+ gain->offset_valid = valid;
+}
+
+static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
+ struct rtw8851b_efuse *map;
+
+ map = (struct rtw8851b_efuse *)log_map;
+
+ efuse->country_code[0] = map->country_code[0];
+ efuse->country_code[1] = map->country_code[1];
+ rtw8851b_efuse_parsing_tssi(rtwdev, map);
+ rtw8851b_efuse_parsing_gain_offset(rtwdev, map);
+
+ switch (rtwdev->hci.type) {
+ case RTW89_HCI_TYPE_PCIE:
+ rtw8851b_efuse_parsing(efuse, map);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
+
+ return 0;
+}
+
+static void rtw8851b_phycap_parsing_tssi(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+ static const u32 tssi_trim_addr[RF_PATH_NUM_8851B] = {0x5D6};
+ u32 addr = rtwdev->chip->phycap_addr;
+ bool pg = false;
+ u32 ofst;
+ u8 i, j;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) {
+ /* addrs are in decreasing order */
+ ofst = tssi_trim_addr[i] - addr - j;
+ tssi->tssi_trim[i][j] = phycap_map[ofst];
+
+ if (phycap_map[ofst] != 0xff)
+ pg = true;
+ }
+ }
+
+ if (!pg) {
+ memset(tssi->tssi_trim, 0, sizeof(tssi->tssi_trim));
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM] no PG, set all trim info to 0\n");
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++)
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] path=%d idx=%d trim=0x%x addr=0x%x\n",
+ i, j, tssi->tssi_trim[i][j],
+ tssi_trim_addr[i] - j);
+}
+
+static void rtw8851b_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ static const u32 thm_trim_addr[RF_PATH_NUM_8851B] = {0x5DF};
+ u32 addr = rtwdev->chip->phycap_addr;
+ u8 i;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ info->thermal_trim[i] = phycap_map[thm_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] path=%d thermal_trim=0x%x\n",
+ i, info->thermal_trim[i]);
+
+ if (info->thermal_trim[i] != 0xff)
+ info->pg_thermal_trim = true;
+ }
+}
+
+static void rtw8851b_thermal_trim(struct rtw89_dev *rtwdev)
+{
+#define __thm_setting(raw) \
+({ \
+ u8 __v = (raw); \
+ ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \
+})
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 i, val;
+
+ if (!info->pg_thermal_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] no PG, do nothing\n");
+
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ val = __thm_setting(info->thermal_trim[i]);
+ rtw89_write_rf(rtwdev, i, RR_TM2, RR_TM2_OFF, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[THERMAL][TRIM] path=%d thermal_setting=0x%x\n",
+ i, val);
+ }
+#undef __thm_setting
+}
+
+static void rtw8851b_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev,
+ u8 *phycap_map)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ static const u32 pabias_trim_addr[] = {0x5DE};
+ u32 addr = rtwdev->chip->phycap_addr;
+ u8 i;
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n",
+ i, info->pa_bias_trim[i]);
+
+ if (info->pa_bias_trim[i] != 0xff)
+ info->pg_pa_bias_trim = true;
+ }
+}
+
+static void rtw8851b_pa_bias_trim(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+ u8 pabias_2g, pabias_5g;
+ u8 i;
+
+ if (!info->pg_pa_bias_trim) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] no PG, do nothing\n");
+
+ return;
+ }
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++) {
+ pabias_2g = u8_get_bits(info->pa_bias_trim[i], GENMASK(3, 0));
+ pabias_5g = u8_get_bits(info->pa_bias_trim[i], GENMASK(7, 4));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n",
+ i, pabias_2g, pabias_5g);
+
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG, pabias_2g);
+ rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA, pabias_5g);
+ }
+}
+
+static void rtw8851b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ static const u32 comp_addrs[][RTW89_SUBBAND_2GHZ_5GHZ_NR] = {
+ {0x5BB, 0x5BA, 0, 0x5B9, 0x5B8},
+ };
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+ u32 phycap_addr = rtwdev->chip->phycap_addr;
+ bool valid = false;
+ int path, i;
+ u8 data;
+
+ for (path = 0; path < BB_PATH_NUM_8851B; path++)
+ for (i = 0; i < RTW89_SUBBAND_2GHZ_5GHZ_NR; i++) {
+ if (comp_addrs[path][i] == 0)
+ continue;
+
+ data = phycap_map[comp_addrs[path][i] - phycap_addr];
+ valid |= _decode_efuse_gain(data, NULL,
+ &gain->comp[path][i]);
+ }
+
+ gain->comp_valid = valid;
+}
+
+static int rtw8851b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map)
+{
+ rtw8851b_phycap_parsing_tssi(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_thermal_trim(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map);
+ rtw8851b_phycap_parsing_gain_comp(rtwdev, phycap_map);
+
+ return 0;
+}
+
+static void rtw8851b_set_bb_gpio(struct rtw89_dev *rtwdev, u8 gpio_idx, bool inv,
+ u8 src_sel)
+{
+ u32 addr, mask;
+
+ if (gpio_idx >= 32)
+ return;
+
+ /* 2 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 2 bits */
+ addr = R_RFE_SEL0_A2 + (gpio_idx / 16) * sizeof(u32);
+ mask = B_RFE_SEL0_MASK << (gpio_idx % 16) * 2;
+
+ rtw89_phy_write32_mask(rtwdev, addr, mask, RF_PATH_A);
+ rtw89_phy_write32_mask(rtwdev, R_RFE_INV0, BIT(gpio_idx), inv);
+
+ /* 4 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 4 bits */
+ addr = R_RFE_SEL0_BASE + (gpio_idx / 8) * sizeof(u32);
+ mask = B_RFE_SEL0_SRC_MASK << (gpio_idx % 8) * 4;
+
+ rtw89_phy_write32_mask(rtwdev, addr, mask, src_sel);
+}
+
+static void rtw8851b_set_mac_gpio(struct rtw89_dev *rtwdev, u8 func)
+{
+ static const struct rtw89_reg3_def func16 = {
+ R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO16_FUNC_SEL_MASK, BIT(3)
+ };
+ static const struct rtw89_reg3_def func17 = {
+ R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO17_FUNC_SEL_MASK, BIT(7) >> 4,
+ };
+ const struct rtw89_reg3_def *def;
+
+ switch (func) {
+ case 16:
+ def = &func16;
+ break;
+ case 17:
+ def = &func17;
+ break;
+ default:
+ rtw89_warn(rtwdev, "undefined gpio func %d\n", func);
+ return;
+ }
+
+ rtw89_write8_mask(rtwdev, def->addr, def->mask, def->data);
+}
+
+static void rtw8851b_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+ u8 rfe_type = rtwdev->efuse.rfe_type;
+
+ if (rfe_type > 50)
+ return;
+
+ if (rfe_type % 3 == 2) {
+ rtw8851b_set_bb_gpio(rtwdev, 16, true, RFE_SEL0_SRC_ANTSEL_0);
+ rtw8851b_set_bb_gpio(rtwdev, 17, false, RFE_SEL0_SRC_ANTSEL_0);
+
+ rtw8851b_set_mac_gpio(rtwdev, 16);
+ rtw8851b_set_mac_gpio(rtwdev, 17);
+ }
+}
+
+static void rtw8851b_power_trim(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_thermal_trim(rtwdev);
+ rtw8851b_pa_bias_trim(rtwdev);
+}
+
+static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ u8 mac_idx)
+{
+ u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
+ u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
+ u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
+ u8 txsc20 = 0, txsc40 = 0;
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_80:
+ txsc40 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_40);
+ fallthrough;
+ case RTW89_CHANNEL_WIDTH_40:
+ txsc20 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_20);
+ break;
+ default:
+ break;
+ }
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1));
+ rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4));
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(0));
+ rtw89_write32(rtwdev, sub_carr, txsc20);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_write8_clr(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK);
+ rtw89_write32(rtwdev, sub_carr, 0);
+ break;
+ default:
+ break;
+ }
+
+ if (chan->channel > 14) {
+ rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE);
+ rtw89_write8_set(rtwdev, chk_rate,
+ B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+ } else {
+ rtw89_write8_set(rtwdev, chk_rate, B_AX_BAND_MODE);
+ rtw89_write8_clr(rtwdev, chk_rate,
+ B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+ }
+}
+
+static const u32 rtw8851b_sco_barker_threshold[14] = {
+ 0x1cfea, 0x1d0e1, 0x1d1d7, 0x1d2cd, 0x1d3c3, 0x1d4b9, 0x1d5b0, 0x1d6a6,
+ 0x1d79c, 0x1d892, 0x1d988, 0x1da7f, 0x1db75, 0x1ddc4
+};
+
+static const u32 rtw8851b_sco_cck_threshold[14] = {
+ 0x27de3, 0x27f35, 0x28088, 0x281da, 0x2832d, 0x2847f, 0x285d2, 0x28724,
+ 0x28877, 0x289c9, 0x28b1c, 0x28c6e, 0x28dc1, 0x290ed
+};
+
+static void rtw8851b_ctrl_sco_cck(struct rtw89_dev *rtwdev, u8 primary_ch)
+{
+ u8 ch_element = primary_ch - 1;
+
+ rtw89_phy_write32_mask(rtwdev, R_RXSCOBC, B_RXSCOBC_TH,
+ rtw8851b_sco_barker_threshold[ch_element]);
+ rtw89_phy_write32_mask(rtwdev, R_RXSCOCCK, B_RXSCOCCK_TH,
+ rtw8851b_sco_cck_threshold[ch_element]);
+}
+
+static u8 rtw8851b_sco_mapping(u8 central_ch)
+{
+ if (central_ch == 1)
+ return 109;
+ else if (central_ch >= 2 && central_ch <= 6)
+ return 108;
+ else if (central_ch >= 7 && central_ch <= 10)
+ return 107;
+ else if (central_ch >= 11 && central_ch <= 14)
+ return 106;
+ else if (central_ch == 36 || central_ch == 38)
+ return 51;
+ else if (central_ch >= 40 && central_ch <= 58)
+ return 50;
+ else if (central_ch >= 60 && central_ch <= 64)
+ return 49;
+ else if (central_ch == 100 || central_ch == 102)
+ return 48;
+ else if (central_ch >= 104 && central_ch <= 126)
+ return 47;
+ else if (central_ch >= 128 && central_ch <= 151)
+ return 46;
+ else if (central_ch >= 153 && central_ch <= 177)
+ return 45;
+ else
+ return 0;
+}
+
+struct rtw8851b_bb_gain {
+ u32 gain_g[BB_PATH_NUM_8851B];
+ u32 gain_a[BB_PATH_NUM_8851B];
+ u32 gain_mask;
+};
+
+static const struct rtw8851b_bb_gain bb_gain_lna[LNA_GAIN_NUM] = {
+ { .gain_g = {0x4678}, .gain_a = {0x45DC},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x4678}, .gain_a = {0x45DC},
+ .gain_mask = 0xff000000 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x000000ff },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x0000ff00 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x467C}, .gain_a = {0x4660},
+ .gain_mask = 0xff000000 },
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0x000000ff },
+};
+
+static const struct rtw8851b_bb_gain bb_gain_tia[TIA_GAIN_NUM] = {
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0x00ff0000 },
+ { .gain_g = {0x4680}, .gain_a = {0x4664},
+ .gain_mask = 0xff000000 },
+};
+
+static void rtw8851b_set_gain_error(struct rtw89_dev *rtwdev,
+ enum rtw89_subband subband,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
+ u8 gain_band = rtw89_subband_to_bb_gain_band(subband);
+ s32 val;
+ u32 reg;
+ u32 mask;
+ int i;
+
+ for (i = 0; i < LNA_GAIN_NUM; i++) {
+ if (subband == RTW89_CH_2G)
+ reg = bb_gain_lna[i].gain_g[path];
+ else
+ reg = bb_gain_lna[i].gain_a[path];
+
+ mask = bb_gain_lna[i].gain_mask;
+ val = gain->lna_gain[gain_band][path][i];
+ rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+ }
+
+ for (i = 0; i < TIA_GAIN_NUM; i++) {
+ if (subband == RTW89_CH_2G)
+ reg = bb_gain_tia[i].gain_g[path];
+ else
+ reg = bb_gain_tia[i].gain_a[path];
+
+ mask = bb_gain_tia[i].gain_mask;
+ val = gain->tia_gain[gain_band][path][i];
+ rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+ }
+}
+
+static void rtw8851b_set_gain_offset(struct rtw89_dev *rtwdev,
+ enum rtw89_subband subband,
+ enum rtw89_phy_idx phy_idx)
+{
+ static const u32 rssi_ofst_addr[] = {R_PATH0_G_TIA1_LNA6_OP1DB_V1};
+ static const u32 gain_err_addr[] = {R_P0_AGC_RSVD};
+ struct rtw89_phy_efuse_gain *efuse_gain = &rtwdev->efuse_gain;
+ enum rtw89_gain_offset gain_ofdm_band;
+ s32 offset_ofdm, offset_cck;
+ s32 offset_a;
+ s32 tmp;
+ u8 path;
+
+ if (!efuse_gain->comp_valid)
+ goto next;
+
+ for (path = RF_PATH_A; path < BB_PATH_NUM_8851B; path++) {
+ tmp = efuse_gain->comp[path][subband];
+ tmp = clamp_t(s32, tmp << 2, S8_MIN, S8_MAX);
+ rtw89_phy_write32_mask(rtwdev, gain_err_addr[path], MASKBYTE0, tmp);
+ }
+
+next:
+ if (!efuse_gain->offset_valid)
+ return;
+
+ gain_ofdm_band = rtw89_subband_to_gain_offset_band_of_ofdm(subband);
+
+ offset_a = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+
+ tmp = -((offset_a << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2));
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_A], B_PATH0_R_G_OFST_MASK, tmp);
+
+ offset_ofdm = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+ offset_cck = -efuse_gain->offset[RF_PATH_A][0];
+
+ tmp = (offset_ofdm << 4) + efuse_gain->offset_base[RTW89_PHY_0];
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_idx(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+ tmp = (offset_ofdm << 4) + efuse_gain->rssi_base[RTW89_PHY_0];
+ tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+ rtw89_phy_write32_idx(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+ if (subband == RTW89_CH_2G) {
+ tmp = (offset_cck << 3) + (efuse_gain->offset_base[RTW89_PHY_0] >> 1);
+ tmp = clamp_t(s32, tmp, S8_MIN >> 1, S8_MAX >> 1);
+ rtw89_phy_write32_mask(rtwdev, R_RX_RPL_OFST,
+ B_RX_RPL_OFST_CCK_MASK, tmp);
+ }
+}
+
+static
+void rtw8851b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband)
+{
+ const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
+ u8 band = rtw89_subband_to_bb_gain_band(subband);
+ u32 val;
+
+ val = u32_encode_bits(gain->rpl_ofst_20[band][RF_PATH_A], B_P0_RPL1_20_MASK) |
+ u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][0], B_P0_RPL1_40_MASK) |
+ u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][1], B_P0_RPL1_41_MASK);
+ val >>= B_P0_RPL1_SHIFT;
+ rtw89_phy_write32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_MASK, val);
+
+ val = u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][2], B_P0_RTL2_42_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][0], B_P0_RTL2_80_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][1], B_P0_RTL2_81_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][10], B_P0_RTL2_8A_MASK);
+ rtw89_phy_write32(rtwdev, R_P0_RPL2, val);
+ rtw89_phy_write32(rtwdev, R_P1_RPL2, val);
+
+ val = u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][2], B_P0_RTL3_82_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][3], B_P0_RTL3_83_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][4], B_P0_RTL3_84_MASK) |
+ u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][9], B_P0_RTL3_89_MASK);
+ rtw89_phy_write32(rtwdev, R_P0_RPL3, val);
+ rtw89_phy_write32(rtwdev, R_P1_RPL3, val);
+}
+
+static void rtw8851b_ctrl_ch(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 subband = chan->subband_type;
+ u8 central_ch = chan->channel;
+ bool is_2g = central_ch <= 14;
+ u8 sco_comp;
+
+ if (is_2g)
+ rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+ B_PATH0_BAND_SEL_MSK_V1, 1, phy_idx);
+ else
+ rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+ B_PATH0_BAND_SEL_MSK_V1, 0, phy_idx);
+ /* SCO compensate FC setting */
+ sco_comp = rtw8851b_sco_mapping(central_ch);
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_INV, sco_comp, phy_idx);
+
+ if (chan->band_type == RTW89_BAND_6G)
+ return;
+
+ /* CCK parameters */
+ if (central_ch == 14) {
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3b13ff);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x1c42de);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfdb0ad);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xf60f6e);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xfd8f92);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0x2d011);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0x1c02c);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xfff00a);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3d23ff);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x29b354);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfc1c8);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xfdb053);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xf86f9a);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0xfaef92);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0xfe5fcc);
+ rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xffdff5);
+ }
+
+ rtw8851b_set_gain_error(rtwdev, subband, RF_PATH_A);
+ rtw8851b_set_gain_offset(rtwdev, subband, phy_idx);
+ rtw8851b_set_rxsc_rpl_comp(rtwdev, subband);
+}
+
+static void rtw8851b_bw_setting(struct rtw89_dev *rtwdev, u8 bw)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_MUL, 0xf);
+ rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_LP, 0xa);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92);
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x1);
+ break;
+ case RTW89_CHANNEL_WIDTH_10:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0);
+ break;
+ default:
+ rtw89_warn(rtwdev, "Fail to set ADC\n");
+ }
+}
+
+static void rtw8851b_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
+ enum rtw89_phy_idx phy_idx)
+{
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_10:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_20:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+ pri_ch, phy_idx);
+ /* CCK primary channel */
+ if (pri_ch == RTW89_SC_20_UPPER)
+ rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 1);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 0);
+
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x2, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+ pri_ch, phy_idx);
+ break;
+ default:
+ rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw,
+ pri_ch);
+ }
+
+ rtw8851b_bw_setting(rtwdev, bw);
+}
+
+static void rtw8851b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en)
+{
+ if (cck_en) {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF,
+ B_PD_ARBITER_OFF, 0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1);
+ rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF,
+ B_PD_ARBITER_OFF, 1);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 0);
+ }
+}
+
+static u32 rtw8851b_spur_freq(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ u8 center_chan = chan->channel;
+
+ switch (chan->band_type) {
+ case RTW89_BAND_5G:
+ if (center_chan == 151 || center_chan == 153 ||
+ center_chan == 155 || center_chan == 163)
+ return 5760;
+ else if (center_chan == 54 || center_chan == 58)
+ return 5280;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#define CARRIER_SPACING_312_5 312500 /* 312.5 kHz */
+#define CARRIER_SPACING_78_125 78125 /* 78.125 kHz */
+#define MAX_TONE_NUM 2048
+
+static void rtw8851b_set_csi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 spur_freq;
+ s32 freq_diff, csi_idx, csi_tone_idx;
+
+ spur_freq = rtw8851b_spur_freq(rtwdev, chan);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN,
+ 0, phy_idx);
+ return;
+ }
+
+ freq_diff = (spur_freq - chan->freq) * 1000000;
+ csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125);
+ s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx);
+
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_V1, B_SEG0CSI_IDX,
+ csi_tone_idx, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, 1, phy_idx);
+}
+
+static const struct rtw89_nbi_reg_def rtw8851b_nbi_reg_def = {
+ .notch1_idx = {0x46E4, 0xFF},
+ .notch1_frac_idx = {0x46E4, 0xC00},
+ .notch1_en = {0x46E4, 0x1000},
+ .notch2_idx = {0x47A4, 0xFF},
+ .notch2_frac_idx = {0x47A4, 0xC00},
+ .notch2_en = {0x47A4, 0x1000},
+};
+
+static void rtw8851b_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ const struct rtw89_nbi_reg_def *nbi = &rtw8851b_nbi_reg_def;
+ s32 nbi_frac_idx, nbi_frac_tone_idx;
+ s32 nbi_idx, nbi_tone_idx;
+ bool notch2_chk = false;
+ u32 spur_freq, fc;
+ s32 freq_diff;
+
+ spur_freq = rtw8851b_spur_freq(rtwdev, chan);
+ if (spur_freq == 0) {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ return;
+ }
+
+ fc = chan->freq;
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160) {
+ fc = (spur_freq > fc) ? fc + 40 : fc - 40;
+ if ((fc > spur_freq &&
+ chan->channel < chan->primary_channel) ||
+ (fc < spur_freq &&
+ chan->channel > chan->primary_channel))
+ notch2_chk = true;
+ }
+
+ freq_diff = (spur_freq - fc) * 1000000;
+ nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5,
+ &nbi_frac_idx);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_20) {
+ s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx);
+ } else {
+ u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ?
+ 128 : 256;
+
+ s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx);
+ }
+ nbi_frac_tone_idx = s32_div_u32_round_closest(nbi_frac_idx,
+ CARRIER_SPACING_78_125);
+
+ if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_idx.addr,
+ nbi->notch2_idx.mask, nbi_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_frac_idx.addr,
+ nbi->notch2_frac_idx.mask, nbi_frac_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 1);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_idx.addr,
+ nbi->notch1_idx.mask, nbi_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_frac_idx.addr,
+ nbi->notch1_frac_idx.mask, nbi_frac_tone_idx);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 0);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr,
+ nbi->notch1_en.mask, 1);
+ rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr,
+ nbi->notch2_en.mask, 0);
+ }
+}
+
+static void rtw8851b_set_cfr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan)
+{
+ if (chan->band_type == RTW89_BAND_2G &&
+ chan->band_width == RTW89_CHANNEL_WIDTH_20 &&
+ (chan->channel == 1 || chan->channel == 13)) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC0, 0xf8);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC1, 0x120);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x3);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC0, 0x120);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR,
+ B_PATH0_TX_CFR_LGC1, 0x3ff);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING,
+ B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x7);
+ }
+}
+
+static void rtw8851b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 pri_ch = chan->pri_ch_idx;
+ bool mask_5m_low;
+ bool mask_5m_en;
+
+ switch (chan->band_width) {
+ case RTW89_CHANNEL_WIDTH_40:
+ /* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */
+ mask_5m_en = true;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWER;
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ /* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */
+ mask_5m_en = pri_ch == RTW89_SC_20_UPMOST ||
+ pri_ch == RTW89_SC_20_LOWEST;
+ mask_5m_low = pri_ch == RTW89_SC_20_LOWEST;
+ break;
+ default:
+ mask_5m_en = false;
+ break;
+ }
+
+ if (!mask_5m_en) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x0);
+ rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+ B_ASSIGN_SBD_OPT_EN_V1, 0x0, phy_idx);
+ return;
+ }
+
+ if (mask_5m_low) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x0);
+ }
+ rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+ B_ASSIGN_SBD_OPT_EN_V1, 0x1, phy_idx);
+}
+
+static void rtw8851b_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+ fsleep(1);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+}
+
+static void rtw8851b_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band,
+ enum rtw89_phy_idx phy_idx, bool en)
+{
+ if (en) {
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
+ B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+ if (band == RTW89_BAND_2G)
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x1);
+ rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
+ B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+ fsleep(1);
+ rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
+ }
+}
+
+static void rtw8851b_bb_reset(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
+ B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x1);
+ rtw89_phy_write32_set(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN);
+ rtw8851b_bb_reset_all(rtwdev, phy_idx);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
+ B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x3);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN);
+}
+
+static
+void rtw8851b_bb_gpio_trsw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ u8 tx_path_en, u8 trsw_tx,
+ u8 trsw_rx, u8 trsw_a, u8 trsw_b)
+{
+ u32 mask_ofst = 16;
+ u32 val;
+
+ if (path != RF_PATH_A)
+ return;
+
+ mask_ofst += (tx_path_en * 4 + trsw_tx * 2 + trsw_rx) * 2;
+ val = u32_encode_bits(trsw_a, B_P0_TRSW_A) |
+ u32_encode_bits(trsw_b, B_P0_TRSW_B);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TRSW,
+ (B_P0_TRSW_A | B_P0_TRSW_B) << mask_ofst, val);
+}
+
+static void rtw8851b_bb_gpio_init(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_write32_set(rtwdev, R_P0_TRSW, B_P0_TRSW_A);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_X);
+ rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_SO_A2);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL0_BASE, 0x77777777);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL32_BASE, 0x77777777);
+
+ rtw89_phy_write32(rtwdev, R_RFE_E_A2, 0xffffffff);
+ rtw89_phy_write32(rtwdev, R_RFE_O_SEL_A2, 0);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL0_A2, 0);
+ rtw89_phy_write32(rtwdev, R_RFE_SEL32_A2, 0);
+
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 0, 0, 1);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 0, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 0, 0, 1);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 1, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 0, 1, 0);
+ rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 1, 1, 0);
+}
+
+static void rtw8851b_bb_macid_ctrl_init(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ u32 addr;
+
+ for (addr = R_AX_PWR_MACID_LMT_TABLE0;
+ addr <= R_AX_PWR_MACID_LMT_TABLE127; addr += 4)
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, 0);
+}
+
+static void rtw8851b_bb_sethw(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+
+ rtw89_phy_write32_clr(rtwdev, R_P0_EN_SOUND_WO_NDP, B_P0_EN_SOUND_WO_NDP);
+
+ rtw8851b_bb_macid_ctrl_init(rtwdev, RTW89_PHY_0);
+ rtw8851b_bb_gpio_init(rtwdev);
+
+ rtw89_write32_clr(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_VALUE);
+ rtw89_write32_set(rtwdev, R_AX_PWR_NORM_FORCE1, B_AX_FORCE_NTX_EN);
+
+ /* read these registers after loading BB parameters */
+ gain->offset_base[RTW89_PHY_0] =
+ rtw89_phy_read32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK);
+ gain->rssi_base[RTW89_PHY_0] =
+ rtw89_phy_read32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK);
+}
+
+static void rtw8851b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 band = chan->band_type, chan_idx;
+ bool cck_en = chan->channel <= 14;
+ u8 pri_ch_idx = chan->pri_ch_idx;
+
+ if (cck_en)
+ rtw8851b_ctrl_sco_cck(rtwdev, chan->primary_channel);
+
+ rtw8851b_ctrl_ch(rtwdev, chan, phy_idx);
+ rtw8851b_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
+ rtw8851b_ctrl_cck_en(rtwdev, cck_en);
+ rtw8851b_set_nbi_tone_idx(rtwdev, chan);
+ rtw8851b_set_csi_tone_idx(rtwdev, chan, phy_idx);
+
+ if (chan->band_type == RTW89_BAND_5G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
+ }
+
+ chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band);
+ rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx);
+ rtw8851b_5m_mask(rtwdev, chan, phy_idx);
+ rtw8851b_set_cfr(rtwdev, chan);
+ rtw8851b_bb_reset_all(rtwdev, phy_idx);
+}
+
+static void rtw8851b_set_channel(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_mac_idx mac_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_set_channel_mac(rtwdev, chan, mac_idx);
+ rtw8851b_set_channel_bb(rtwdev, chan, phy_idx);
+ rtw8851b_set_channel_rf(rtwdev, chan, phy_idx);
+}
+
+static void rtw8851b_tssi_cont_en(struct rtw89_dev *rtwdev, bool en,
+ enum rtw89_rf_path path)
+{
+ if (en) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x1);
+ }
+}
+
+static void rtw8851b_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en,
+ u8 phy_idx)
+{
+ rtw8851b_tssi_cont_en(rtwdev, en, RF_PATH_A);
+}
+
+static void rtw8851b_adc_en(struct rtw89_dev *rtwdev, bool en)
+{
+ if (en)
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0xf);
+}
+
+static void rtw8851b_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
+ struct rtw89_channel_help_params *p,
+ const struct rtw89_chan *chan,
+ enum rtw89_mac_idx mac_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (enter) {
+ rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL);
+ rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
+ rtw8851b_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
+ rtw8851b_adc_en(rtwdev, false);
+ fsleep(40);
+ rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, false);
+ } else {
+ rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
+ rtw8851b_adc_en(rtwdev, true);
+ rtw8851b_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
+ rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, true);
+ rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
+ }
+}
+
+static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev)
+{
+ rtwdev->is_tssi_mode[RF_PATH_A] = false;
+ rtwdev->is_tssi_mode[RF_PATH_B] = false;
+ rtw8851b_lck_init(rtwdev);
+
+ rtw8851b_dpk_init(rtwdev);
+ rtw8851b_aack(rtwdev);
+ rtw8851b_rck(rtwdev);
+ rtw8851b_dack(rtwdev);
+ rtw8851b_rx_dck(rtwdev, RTW89_PHY_0);
+}
+
+static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev)
+{
+ enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
+
+ rtw8851b_rx_dck(rtwdev, phy_idx);
+ rtw8851b_iqk(rtwdev, phy_idx);
+ rtw8851b_tssi(rtwdev, phy_idx, true);
+ rtw8851b_dpk(rtwdev, phy_idx);
+}
+
+static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_tssi_scan(rtwdev, phy_idx);
+}
+
+static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, bool start)
+{
+ rtw8851b_wifi_scan_notify(rtwdev, start, RTW89_PHY_0);
+}
+
+static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_dpk_track(rtwdev);
+ rtw8851b_lck_track(rtwdev);
+}
+
+static u32 rtw8851b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, s16 ref)
+{
+ const u16 tssi_16dbm_cw = 0x12c;
+ const u8 base_cw_0db = 0x27;
+ const s8 ofst_int = 0;
+ s16 pwr_s10_3;
+ s16 rf_pwr_cw;
+ u16 bb_pwr_cw;
+ u32 pwr_cw;
+ u32 tssi_ofst_cw;
+
+ pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3);
+ bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0));
+ rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3));
+ rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63);
+ pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw;
+
+ tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3));
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n",
+ tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw);
+
+ return u32_encode_bits(tssi_ofst_cw, B_DPD_TSSI_CW) |
+ u32_encode_bits(pwr_cw, B_DPD_PWR_CW) |
+ u32_encode_bits(ref, B_DPD_REF);
+}
+
+static void rtw8851b_set_txpwr_ref(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ static const u32 addr[RF_PATH_NUM_8851B] = {0x5800};
+ const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF;
+ const u8 ofst_ofdm = 0x4;
+ const u8 ofst_cck = 0x8;
+ const s16 ref_ofdm = 0;
+ const s16 ref_cck = 0;
+ u32 val;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n");
+
+ rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL,
+ B_AX_PWR_REF, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
+ val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm);
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val,
+ phy_idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n");
+ val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck);
+
+ for (i = 0; i < RF_PATH_NUM_8851B; i++)
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val,
+ phy_idx);
+}
+
+static void rtw8851b_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ u8 tx_shape_idx,
+ enum rtw89_phy_idx phy_idx)
+{
+#define __DFIR_CFG_ADDR(i) (R_TXFIR0 + ((i) << 2))
+#define __DFIR_CFG_MASK 0xffffffff
+#define __DFIR_CFG_NR 8
+#define __DECL_DFIR_PARAM(_name, _val...) \
+ static const u32 param_ ## _name[] = {_val}; \
+ static_assert(ARRAY_SIZE(param_ ## _name) == __DFIR_CFG_NR)
+
+ __DECL_DFIR_PARAM(flat,
+ 0x023D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053,
+ 0x00F86F9A, 0x06FAEF92, 0x00FE5FCC, 0x00FFDFF5);
+ __DECL_DFIR_PARAM(sharp,
+ 0x023D83FF, 0x002C636A, 0x0013F204, 0x00008090,
+ 0x00F87FB0, 0x06F99F83, 0x00FDBFBA, 0x00003FF5);
+ __DECL_DFIR_PARAM(sharp_14,
+ 0x023B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E,
+ 0x00FD8F92, 0x0602D011, 0x0001C02C, 0x00FFF00A);
+ u8 ch = chan->channel;
+ const u32 *param;
+ u32 addr;
+ int i;
+
+ if (ch > 14) {
+ rtw89_warn(rtwdev,
+ "set tx shape dfir by unknown ch: %d on 2G\n", ch);
+ return;
+ }
+
+ if (ch == 14)
+ param = param_sharp_14;
+ else
+ param = tx_shape_idx == 0 ? param_flat : param_sharp;
+
+ for (i = 0; i < __DFIR_CFG_NR; i++) {
+ addr = __DFIR_CFG_ADDR(i);
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "set tx shape dfir: 0x%x: 0x%x\n", addr, param[i]);
+ rtw89_phy_write32_idx(rtwdev, addr, __DFIR_CFG_MASK, param[i],
+ phy_idx);
+ }
+
+#undef __DECL_DFIR_PARAM
+#undef __DFIR_CFG_NR
+#undef __DFIR_CFG_MASK
+#undef __DECL_CFG_ADDR
+}
+
+static void rtw8851b_set_tx_shape(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ u8 band = chan->band_type;
+ u8 regd = rtw89_regd_get(rtwdev, band);
+ u8 tx_shape_cck = rtw89_8851b_tx_shape[band][RTW89_RS_CCK][regd];
+ u8 tx_shape_ofdm = rtw89_8851b_tx_shape[band][RTW89_RS_OFDM][regd];
+
+ if (band == RTW89_BAND_2G)
+ rtw8851b_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx);
+
+ rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG,
+ tx_shape_ofdm);
+}
+
+static void rtw8851b_set_txpwr(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx);
+ rtw8851b_set_tx_shape(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
+ rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+}
+
+static void rtw8851b_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_set_txpwr_ref(rtwdev, phy_idx);
+}
+
+static
+void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
+ s8 pw_ofst, enum rtw89_mac_idx mac_idx)
+{
+ u32 reg;
+
+ if (pw_ofst < -16 || pw_ofst > 15) {
+ rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst);
+ return;
+ }
+
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx);
+ rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN);
+
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst);
+
+ pw_ofst = max_t(s8, pw_ofst - 3, -16);
+ reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst);
+}
+
+static int
+rtw8851b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ int ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff);
+ if (ret)
+ return ret;
+
+ rtw8851b_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ?
+ RTW89_MAC_1 : RTW89_MAC_0);
+
+ return 0;
+}
+
+static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8851b_btc_preagc_en_defs_tbl :
+ &rtw8851b_btc_preagc_dis_defs_tbl);
+
+ if (!bt_en) {
+ if (chan->band_type == RTW89_BAND_2G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x20);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ }
+ }
+}
+
+static void rtw8851b_ctrl_btg(struct rtw89_dev *rtwdev, bool btg)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ if (btg) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x20);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30);
+ rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x1);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+ B_PATH0_BT_SHARE_V1, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+ B_PATH0_BTG_PATH_V1, 0x0);
+ if (chan->band_type == RTW89_BAND_2G) {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x80);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1,
+ B_PATH0_G_LNA6_OP1DB_V1, 0x1a);
+ rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1,
+ B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a);
+ }
+ rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0xc);
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+ B_BT_DYN_DC_EST_EN_MSK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
+ }
+}
+
+static void rtw8851b_bb_ctrl_rx_path(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path_bit rx_path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 rst_mask0;
+
+ if (rx_path == RF_A) {
+ rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG1, 1);
+ rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_USER_MAX, 4);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0);
+ }
+
+ rtw8851b_set_gain_offset(rtwdev, chan->subband_type, RTW89_PHY_0);
+
+ rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI;
+ if (rx_path == RF_A) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 3);
+ }
+}
+
+static void rtw8851b_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_bb_ctrl_rx_path(rtwdev, RF_A);
+
+ if (rtwdev->hal.rx_nss == 1) {
+ rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0);
+ rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0);
+ }
+
+ rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL_MOD, 0x0, RTW89_PHY_0);
+}
+
+static u8 rtw8851b_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
+{
+ if (rtwdev->is_tssi_mode[rf_path]) {
+ u32 addr = R_TSSI_THER + (rf_path << 13);
+
+ return rtw89_phy_read32_mask(rtwdev, addr, B_TSSI_THER);
+ }
+
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0);
+ rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1);
+
+ fsleep(200);
+
+ return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL);
+}
+
+static void rtw8851b_btc_set_rfe(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_module *module = &btc->mdinfo;
+
+ module->rfe_type = rtwdev->efuse.rfe_type;
+ module->cv = rtwdev->hal.cv;
+ module->bt_solo = 0;
+ module->switch_type = BTC_SWITCH_INTERNAL;
+ module->ant.isolation = 10;
+ module->kt_ver_adie = rtwdev->hal.acv;
+
+ if (module->rfe_type == 0)
+ return;
+
+ /* rfe_type 3*n+1: 1-Ant(shared),
+ * 3*n+2: 2-Ant+Div(non-shared),
+ * 3*n+3: 2-Ant+no-Div(non-shared)
+ */
+ module->ant.num = (module->rfe_type % 3 == 1) ? 1 : 2;
+ /* WL-1ss at S0, btg at s0 (On 1 WL RF) */
+ module->ant.single_pos = RF_PATH_A;
+ module->ant.btg_pos = RF_PATH_A;
+ module->ant.stream_cnt = 1;
+
+ if (module->ant.num == 1) {
+ module->ant.type = BTC_ANT_SHARED;
+ module->bt_pos = BTC_BT_BTG;
+ module->wa_type = 1;
+ module->ant.diversity = 0;
+ } else { /* ant.num == 2 */
+ module->ant.type = BTC_ANT_DEDICATED;
+ module->bt_pos = BTC_BT_ALONE;
+ module->switch_type = BTC_SWITCH_EXTERNAL;
+ module->wa_type = 0;
+ if (module->rfe_type % 3 == 2)
+ module->ant.diversity = 1;
+ }
+}
+
+static
+void rtw8851b_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val)
+{
+ if (group > BTC_BT_SS_GROUP)
+ group--; /* Tx-group=1, Rx-group=2 */
+
+ if (rtwdev->btc.mdinfo.ant.type == BTC_ANT_SHARED) /* 1-Ant */
+ group += 3;
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, group);
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val);
+}
+
+static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev)
+{
+ static const struct rtw89_mac_ax_coex coex_params = {
+ .pta_mode = RTW89_MAC_AX_COEX_RTK_MODE,
+ .direction = RTW89_MAC_AX_COEX_INNER,
+ };
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_module *module = &btc->mdinfo;
+ struct rtw89_btc_ant_info *ant = &module->ant;
+ u8 path, path_min, path_max;
+
+ /* PTA init */
+ rtw89_mac_coex_init(rtwdev, &coex_params);
+
+ /* set WL Tx response = Hi-Pri */
+ chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true);
+ chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true);
+
+ /* for 1-Ant && 1-ss case: only 1-path */
+ if (ant->stream_cnt == 1) {
+ path_min = ant->single_pos;
+ path_max = path_min;
+ } else {
+ path_min = RF_PATH_A;
+ path_max = RF_PATH_B;
+ }
+
+ for (path = path_min; path <= path_max; path++) {
+ /* set rf gnt-debug off */
+ rtw89_write_rf(rtwdev, path, RR_WLSEL, RFREG_MASK, 0x0);
+
+ /* set DEBUG_LUT_RFMODE_MASK = 1 to start trx-mask-setup */
+ rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, BIT(17));
+
+ /* if GNT_WL=0 && BT=SS_group --> WL Tx/Rx = THRU */
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_SS_GROUP, 0x5ff);
+
+ /* if GNT_WL=0 && BT=Rx_group --> WL-Rx = THRU + WL-Tx = MASK */
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_RX_GROUP, 0x5df);
+
+ /* if GNT_WL = 0 && BT = Tx_group -->
+ * Shared-Ant && BTG-path:WL mask(0x55f), others:WL THRU(0x5ff)
+ */
+ if (ant->type == BTC_ANT_SHARED && ant->btg_pos == path)
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x55f);
+ else
+ rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x5ff);
+
+ /* set DEBUG_LUT_RFMODE_MASK = 0 to stop trx-mask-setup */
+ rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0);
+ }
+
+ /* set PTA break table */
+ rtw89_write32(rtwdev, R_BTC_BREAK_TABLE, BTC_BREAK_PARAM);
+
+ /* enable BT counter 0xda40[16,2] = 2b'11 */
+ rtw89_write32_set(rtwdev, R_AX_CSR_MODE, B_AX_BT_CNT_RST | B_AX_STATIS_BT_EN);
+
+ btc->cx.wl.status.map.init_ok = true;
+}
+
+static
+void rtw8851b_btc_set_wl_pri(struct rtw89_dev *rtwdev, u8 map, bool state)
+{
+ u32 bitmap;
+ u32 reg;
+
+ switch (map) {
+ case BTC_PRI_MASK_TX_RESP:
+ reg = R_BTC_BT_COEX_MSK_TABLE;
+ bitmap = B_BTC_PRI_MASK_TX_RESP_V1;
+ break;
+ case BTC_PRI_MASK_BEACON:
+ reg = R_AX_WL_PRI_MSK;
+ bitmap = B_AX_PTA_WL_PRI_MASK_BCNQ;
+ break;
+ case BTC_PRI_MASK_RX_CCK:
+ reg = R_BTC_BT_COEX_MSK_TABLE;
+ bitmap = B_BTC_PRI_MASK_RXCCK_V1;
+ break;
+ default:
+ return;
+ }
+
+ if (state)
+ rtw89_write32_set(rtwdev, reg, bitmap);
+ else
+ rtw89_write32_clr(rtwdev, reg, bitmap);
+}
+
+union rtw8851b_btc_wl_txpwr_ctrl {
+ u32 txpwr_val;
+ struct {
+ union {
+ u16 ctrl_all_time;
+ struct {
+ s16 data:9;
+ u16 rsvd:6;
+ u16 flag:1;
+ } all_time;
+ };
+ union {
+ u16 ctrl_gnt_bt;
+ struct {
+ s16 data:9;
+ u16 rsvd:7;
+ } gnt_bt;
+ };
+ };
+} __packed;
+
+static void
+rtw8851b_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val)
+{
+ union rtw8851b_btc_wl_txpwr_ctrl arg = { .txpwr_val = txpwr_val };
+ s32 val;
+
+#define __write_ctrl(_reg, _msk, _val, _en, _cond) \
+do { \
+ u32 _wrt = FIELD_PREP(_msk, _val); \
+ BUILD_BUG_ON(!!(_msk & _en)); \
+ if (_cond) \
+ _wrt |= _en; \
+ else \
+ _wrt &= ~_en; \
+ rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \
+ _msk | _en, _wrt); \
+} while (0)
+
+ switch (arg.ctrl_all_time) {
+ case 0xffff:
+ val = 0;
+ break;
+ default:
+ val = arg.all_time.data;
+ break;
+ }
+
+ __write_ctrl(R_AX_PWR_RATE_CTRL, B_AX_FORCE_PWR_BY_RATE_VALUE_MASK,
+ val, B_AX_FORCE_PWR_BY_RATE_EN,
+ arg.ctrl_all_time != 0xffff);
+
+ switch (arg.ctrl_gnt_bt) {
+ case 0xffff:
+ val = 0;
+ break;
+ default:
+ val = arg.gnt_bt.data;
+ break;
+ }
+
+ __write_ctrl(R_AX_PWR_COEXT_CTRL, B_AX_TXAGC_BT_MASK, val,
+ B_AX_TXAGC_BT_EN, arg.ctrl_gnt_bt != 0xffff);
+
+#undef __write_ctrl
+}
+
+static
+s8 rtw8851b_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val)
+{
+ val = clamp_t(s8, val, -100, 0) + 100;
+ val = min(val + 6, 100); /* compensate offset */
+
+ return val;
+}
+
+static
+void rtw8851b_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
+{
+ /* Feature move to firmware */
+}
+
+static void rtw8851b_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000);
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110);
+
+ /* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */
+ if (state)
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c);
+ else
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208);
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x0);
+}
+
+#define LNA2_51B_MA 0x700
+
+static const struct rtw89_reg2_def btc_8851b_rf_0[] = {{0x2, 0x0}};
+static const struct rtw89_reg2_def btc_8851b_rf_1[] = {{0x2, 0x1}};
+
+static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
+{
+ /* To improve BT ACI in co-rx
+ * level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB
+ * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
+ */
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant;
+ const struct rtw89_reg2_def *rf;
+ u32 n, i, val;
+
+ switch (level) {
+ case 0: /* original */
+ default:
+ btc->dm.wl_lna2 = 0;
+ break;
+ case 1: /* for FDD free-run */
+ btc->dm.wl_lna2 = 0;
+ break;
+ case 2: /* for BTG Co-Rx*/
+ btc->dm.wl_lna2 = 1;
+ break;
+ }
+
+ if (btc->dm.wl_lna2 == 0) {
+ rf = btc_8851b_rf_0;
+ n = ARRAY_SIZE(btc_8851b_rf_0);
+ } else {
+ rf = btc_8851b_rf_1;
+ n = ARRAY_SIZE(btc_8851b_rf_1);
+ }
+
+ for (i = 0; i < n; i++, rf++) {
+ val = rf->data;
+ /* bit[10] = 1 if non-shared-ant for 8851b */
+ if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED)
+ val |= 0x4;
+
+ rtw89_write_rf(rtwdev, ant->btg_pos, rf->addr, LNA2_51B_MA, val);
+ }
+}
+
+static void rtw8851b_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct ieee80211_rx_status *status)
+{
+ u16 chan = phy_ppdu->chan_idx;
+ enum nl80211_band band;
+ u8 ch;
+
+ if (chan == 0)
+ return;
+
+ rtw89_decode_chan_idx(rtwdev, chan, &ch, &band);
+ status->freq = ieee80211_channel_to_frequency(ch, band);
+ status->band = band;
+}
+
+static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_phy_ppdu *phy_ppdu,
+ struct ieee80211_rx_status *status)
+{
+ u8 path;
+ u8 *rx_power = phy_ppdu->rssi;
+
+ status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]);
+
+ for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
+ status->chains |= BIT(path);
+ status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
+ }
+ if (phy_ppdu->valid)
+ rtw8851b_fill_freq_with_ppdu(rtwdev, phy_ppdu, status);
+}
+
+static int rtw8851b_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
+{
+ int ret;
+
+ rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN,
+ B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
+ rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+ rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG);
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xC7,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xC7,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ rtw89_write8(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_XYN_CYCLE);
+
+ return 0;
+}
+
+static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
+{
+ u8 wl_rfc_s0;
+ u8 wl_rfc_s1;
+ int ret;
+
+ rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN,
+ B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
+
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, &wl_rfc_s0);
+ if (ret)
+ return ret;
+ wl_rfc_s0 &= ~XTAL_SI_RF00S_EN;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, wl_rfc_s0,
+ FULL_BIT_MASK);
+ if (ret)
+ return ret;
+
+ ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, &wl_rfc_s1);
+ if (ret)
+ return ret;
+ wl_rfc_s1 &= ~XTAL_SI_RF10S_EN;
+ ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, wl_rfc_s1,
+ FULL_BIT_MASK);
+ return ret;
+}
+
+static const struct rtw89_chip_ops rtw8851b_chip_ops = {
+ .enable_bb_rf = rtw8851b_mac_enable_bb_rf,
+ .disable_bb_rf = rtw8851b_mac_disable_bb_rf,
+ .bb_reset = rtw8851b_bb_reset,
+ .bb_sethw = rtw8851b_bb_sethw,
+ .read_rf = rtw89_phy_read_rf_v1,
+ .write_rf = rtw89_phy_write_rf_v1,
+ .set_channel = rtw8851b_set_channel,
+ .set_channel_help = rtw8851b_set_channel_help,
+ .read_efuse = rtw8851b_read_efuse,
+ .read_phycap = rtw8851b_read_phycap,
+ .fem_setup = NULL,
+ .rfe_gpio = rtw8851b_rfe_gpio,
+ .rfk_init = rtw8851b_rfk_init,
+ .rfk_channel = rtw8851b_rfk_channel,
+ .rfk_band_changed = rtw8851b_rfk_band_changed,
+ .rfk_scan = rtw8851b_rfk_scan,
+ .rfk_track = rtw8851b_rfk_track,
+ .power_trim = rtw8851b_power_trim,
+ .set_txpwr = rtw8851b_set_txpwr,
+ .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl,
+ .init_txpwr_unit = rtw8851b_init_txpwr_unit,
+ .get_thermal = rtw8851b_get_thermal,
+ .ctrl_btg = rtw8851b_ctrl_btg,
+ .query_ppdu = rtw8851b_query_ppdu,
+ .bb_ctrl_btc_preagc = rtw8851b_bb_ctrl_btc_preagc,
+ .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path,
+ .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset,
+ .pwr_on_func = rtw8851b_pwr_on_func,
+ .pwr_off_func = rtw8851b_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
+ .fill_txdesc = rtw89_core_fill_txdesc,
+ .fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
+ .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
+ .mac_cfg_gnt = rtw89_mac_cfg_gnt,
+ .stop_sch_tx = rtw89_mac_stop_sch_tx,
+ .resume_sch_tx = rtw89_mac_resume_sch_tx,
+ .h2c_dctl_sec_cam = NULL,
+
+ .btc_set_rfe = rtw8851b_btc_set_rfe,
+ .btc_init_cfg = rtw8851b_btc_init_cfg,
+ .btc_set_wl_pri = rtw8851b_btc_set_wl_pri,
+ .btc_set_wl_txpwr_ctrl = rtw8851b_btc_set_wl_txpwr_ctrl,
+ .btc_get_bt_rssi = rtw8851b_btc_get_bt_rssi,
+ .btc_update_bt_cnt = rtw8851b_btc_update_bt_cnt,
+ .btc_wl_s1_standby = rtw8851b_btc_wl_s1_standby,
+ .btc_set_wl_rx_gain = rtw8851b_btc_set_wl_rx_gain,
+ .btc_set_policy = rtw89_btc_set_policy_v1,
+};
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support rtw_wowlan_stub_8851b = {
+ .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+ .n_patterns = RTW89_MAX_PATTERN_NUM,
+ .pattern_max_len = RTW89_MAX_PATTERN_SIZE,
+ .pattern_min_len = 1,
+};
+#endif
+
+const struct rtw89_chip_info rtw8851b_chip_info = {
+ .chip_id = RTL8851B,
+ .ops = &rtw8851b_chip_ops,
+ .fw_basename = RTW8851B_FW_BASENAME,
+ .fw_format_max = RTW8851B_FW_FORMAT_MAX,
+ .try_ce_fw = true,
+ .fifo_size = 196608,
+ .small_fifo_size = true,
+ .dle_scc_rsvd_size = 98304,
+ .max_amsdu_limit = 3500,
+ .dis_2g_40m_ul_ofdma = true,
+ .rsvd_ple_ofst = 0x2f800,
+ .hfc_param_ini = rtw8851b_hfc_param_ini_pcie,
+ .dle_mem = rtw8851b_dle_mem_pcie,
+ .wde_qempty_acq_num = 4,
+ .wde_qempty_mgq_sel = 4,
+ .rf_base_addr = {0xe000},
+ .pwr_on_seq = NULL,
+ .pwr_off_seq = NULL,
+ .bb_table = &rtw89_8851b_phy_bb_table,
+ .bb_gain_table = &rtw89_8851b_phy_bb_gain_table,
+ .rf_table = {&rtw89_8851b_phy_radioa_table,},
+ .nctl_table = &rtw89_8851b_phy_nctl_table,
+ .nctl_post_table = &rtw8851b_nctl_post_defs_tbl,
+ .byr_table = &rtw89_8851b_byr_table,
+ .dflt_parms = &rtw89_8851b_dflt_parms,
+ .rfe_parms_conf = rtw89_8851b_rfe_parms_conf,
+ .txpwr_factor_rf = 2,
+ .txpwr_factor_mac = 1,
+ .dig_table = NULL,
+ .dig_regs = &rtw8851b_dig_regs,
+ .tssi_dbw_table = NULL,
+ .support_chanctx_num = 0,
+ .support_bands = BIT(NL80211_BAND_2GHZ) |
+ BIT(NL80211_BAND_5GHZ),
+ .support_bw160 = false,
+ .support_unii4 = true,
+ .support_ul_tb_ctrl = true,
+ .hw_sec_hdr = false,
+ .rf_path_num = 1,
+ .tx_nss = 1,
+ .rx_nss = 1,
+ .acam_num = 32,
+ .bcam_num = 20,
+ .scam_num = 128,
+ .bacam_num = 2,
+ .bacam_dynamic_num = 4,
+ .bacam_ver = RTW89_BACAM_V0,
+ .sec_ctrl_efuse_size = 4,
+ .physical_efuse_size = 1216,
+ .logical_efuse_size = 2048,
+ .limit_efuse_size = 1280,
+ .dav_phy_efuse_size = 0,
+ .dav_log_efuse_size = 0,
+ .phycap_addr = 0x580,
+ .phycap_size = 128,
+ .para_ver = 0,
+ .wlcx_desired = 0x06000000,
+ .btcx_desired = 0x7,
+ .scbd = 0x1,
+ .mailbox = 0x1,
+
+ .afh_guard_ch = 6,
+ .wl_rssi_thres = rtw89_btc_8851b_wl_rssi_thres,
+ .bt_rssi_thres = rtw89_btc_8851b_bt_rssi_thres,
+ .rssi_tol = 2,
+ .mon_reg_num = ARRAY_SIZE(rtw89_btc_8851b_mon_reg),
+ .mon_reg = rtw89_btc_8851b_mon_reg,
+ .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_ul),
+ .rf_para_ulink = rtw89_btc_8851b_rf_ul,
+ .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_dl),
+ .rf_para_dlink = rtw89_btc_8851b_rf_dl,
+ .ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) |
+ BIT(RTW89_PS_MODE_CLK_GATED),
+ .low_power_hci_modes = 0,
+ .h2c_cctl_func_id = H2C_FUNC_MAC_CCTLINFO_UD,
+ .hci_func_en_addr = R_AX_HCI_FUNC_EN,
+ .h2c_desc_size = sizeof(struct rtw89_txwd_body),
+ .txwd_body_size = sizeof(struct rtw89_txwd_body),
+ .h2c_ctrl_reg = R_AX_H2CREG_CTRL,
+ .h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8},
+ .h2c_regs = rtw8851b_h2c_regs,
+ .c2h_ctrl_reg = R_AX_C2HREG_CTRL,
+ .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8},
+ .c2h_regs = rtw8851b_c2h_regs,
+ .page_regs = &rtw8851b_page_regs,
+ .cfo_src_fd = true,
+ .cfo_hw_comp = true,
+ .dcfo_comp = &rtw8851b_dcfo_comp,
+ .dcfo_comp_sft = 12,
+ .imr_info = &rtw8851b_imr_info,
+ .rrsr_cfgs = &rtw8851b_rrsr_cfgs,
+ .bss_clr_map_reg = R_BSS_CLR_MAP_V1,
+ .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
+ BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
+ BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
+ .edcca_lvl_reg = R_SEG0R_EDCCA_LVL_V1,
+#ifdef CONFIG_PM
+ .wowlan_stub = &rtw_wowlan_stub_8851b,
+#endif
+ .xtal_info = &rtw8851b_xtal_info,
+};
+EXPORT_SYMBOL(rtw8851b_chip_info);
+
+MODULE_FIRMWARE(RTW8851B_MODULE_FIRMWARE);
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851B driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.h b/drivers/net/wireless/realtek/rtw89/rtw8851b.h
new file mode 100644
index 000000000000..1a5c52654d8a
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_H__
+#define __RTW89_8851B_H__
+
+#include "core.h"
+
+#define RF_PATH_NUM_8851B 1
+#define BB_PATH_NUM_8851B 1
+
+struct rtw8851bu_efuse {
+ u8 rsvd[0x88];
+ u8 mac_addr[ETH_ALEN];
+};
+
+struct rtw8851be_efuse {
+ u8 mac_addr[ETH_ALEN];
+};
+
+struct rtw8851b_tssi_offset {
+ u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
+ u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
+ u8 rsvd[7];
+ u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
+} __packed;
+
+struct rtw8851b_efuse {
+ u8 rsvd[0x210];
+ struct rtw8851b_tssi_offset path_a_tssi;
+ u8 rsvd1[136];
+ u8 channel_plan;
+ u8 xtal_k;
+ u8 rsvd2;
+ u8 iqk_lck;
+ u8 rsvd3[8];
+ u8 eeprom_version;
+ u8 customer_id;
+ u8 tx_bb_swing_2g;
+ u8 tx_bb_swing_5g;
+ u8 tx_cali_pwr_trk_mode;
+ u8 trx_path_selection;
+ u8 rfe_type;
+ u8 country_code[2];
+ u8 rsvd4[3];
+ u8 path_a_therm;
+ u8 rsvd5[3];
+ u8 rx_gain_2g_ofdm;
+ u8 rsvd6;
+ u8 rx_gain_2g_cck;
+ u8 rsvd7;
+ u8 rx_gain_5g_low;
+ u8 rsvd8;
+ u8 rx_gain_5g_mid;
+ u8 rsvd9;
+ u8 rx_gain_5g_high;
+ u8 rsvd10[35];
+ u8 path_a_cck_pwr_idx[6];
+ u8 path_a_bw40_1tx_pwr_idx[5];
+ u8 path_a_ofdm_1tx_pwr_idx_diff:4;
+ u8 path_a_bw20_1tx_pwr_idx_diff:4;
+ u8 path_a_bw20_2tx_pwr_idx_diff:4;
+ u8 path_a_bw40_2tx_pwr_idx_diff:4;
+ u8 path_a_cck_2tx_pwr_idx_diff:4;
+ u8 path_a_ofdm_2tx_pwr_idx_diff:4;
+ u8 rsvd11[0xf2];
+ union {
+ struct rtw8851bu_efuse u;
+ struct rtw8851be_efuse e;
+ };
+} __packed;
+
+extern const struct rtw89_chip_info rtw8851b_chip_info;
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
new file mode 100644
index 000000000000..a221f94627f5
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
@@ -0,0 +1,3621 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include "coex.h"
+#include "debug.h"
+#include "mac.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw8851b.h"
+#include "rtw8851b_rfk.h"
+#include "rtw8851b_rfk_table.h"
+#include "rtw8851b_table.h"
+
+#define DPK_VER_8851B 0x5
+#define DPK_KIP_REG_NUM_8851B 7
+#define DPK_RF_REG_NUM_8851B 4
+#define DPK_KSET_NUM 4
+#define RTW8851B_RXK_GROUP_NR 4
+#define RTW8851B_RXK_GROUP_IDX_NR 2
+#define RTW8851B_TXK_GROUP_NR 1
+#define RTW8851B_IQK_VER 0x2a
+#define RTW8851B_IQK_SS 1
+#define RTW8851B_LOK_GRAM 10
+#define RTW8851B_TSSI_PATH_NR 1
+
+#define _TSSI_DE_MASK GENMASK(21, 12)
+
+enum dpk_id {
+ LBK_RXIQK = 0x06,
+ SYNC = 0x10,
+ MDPK_IDL = 0x11,
+ MDPK_MPA = 0x12,
+ GAIN_LOSS = 0x13,
+ GAIN_CAL = 0x14,
+ DPK_RXAGC = 0x15,
+ KIP_PRESET = 0x16,
+ KIP_RESTORE = 0x17,
+ DPK_TXAGC = 0x19,
+ D_KIP_PRESET = 0x28,
+ D_TXAGC = 0x29,
+ D_RXAGC = 0x2a,
+ D_SYNC = 0x2b,
+ D_GAIN_LOSS = 0x2c,
+ D_MDPK_IDL = 0x2d,
+ D_MDPK_LDL = 0x2e,
+ D_GAIN_NORM = 0x2f,
+ D_KIP_THERMAL = 0x30,
+ D_KIP_RESTORE = 0x31
+};
+
+enum dpk_agc_step {
+ DPK_AGC_STEP_SYNC_DGAIN,
+ DPK_AGC_STEP_GAIN_LOSS_IDX,
+ DPK_AGC_STEP_GL_GT_CRITERION,
+ DPK_AGC_STEP_GL_LT_CRITERION,
+ DPK_AGC_STEP_SET_TX_GAIN,
+};
+
+enum rtw8851b_iqk_type {
+ ID_TXAGC = 0x0,
+ ID_FLOK_COARSE = 0x1,
+ ID_FLOK_FINE = 0x2,
+ ID_TXK = 0x3,
+ ID_RXAGC = 0x4,
+ ID_RXK = 0x5,
+ ID_NBTXK = 0x6,
+ ID_NBRXK = 0x7,
+ ID_FLOK_VBUFFER = 0x8,
+ ID_A_FLOK_COARSE = 0x9,
+ ID_G_FLOK_COARSE = 0xa,
+ ID_A_FLOK_FINE = 0xb,
+ ID_G_FLOK_FINE = 0xc,
+ ID_IQK_RESTORE = 0x10,
+};
+
+enum rf_mode {
+ RF_SHUT_DOWN = 0x0,
+ RF_STANDBY = 0x1,
+ RF_TX = 0x2,
+ RF_RX = 0x3,
+ RF_TXIQK = 0x4,
+ RF_DPK = 0x5,
+ RF_RXK1 = 0x6,
+ RF_RXK2 = 0x7,
+};
+
+static const u32 _tssi_de_cck_long[RF_PATH_NUM_8851B] = {0x5858};
+static const u32 _tssi_de_cck_short[RF_PATH_NUM_8851B] = {0x5860};
+static const u32 _tssi_de_mcs_20m[RF_PATH_NUM_8851B] = {0x5838};
+static const u32 _tssi_de_mcs_40m[RF_PATH_NUM_8851B] = {0x5840};
+static const u32 _tssi_de_mcs_80m[RF_PATH_NUM_8851B] = {0x5848};
+static const u32 _tssi_de_mcs_80m_80m[RF_PATH_NUM_8851B] = {0x5850};
+static const u32 _tssi_de_mcs_5m[RF_PATH_NUM_8851B] = {0x5828};
+static const u32 _tssi_de_mcs_10m[RF_PATH_NUM_8851B] = {0x5830};
+static const u32 g_idxrxgain[RTW8851B_RXK_GROUP_NR] = {0x10e, 0x116, 0x28e, 0x296};
+static const u32 g_idxattc2[RTW8851B_RXK_GROUP_NR] = {0x0, 0xf, 0x0, 0xf};
+static const u32 g_idxrxagc[RTW8851B_RXK_GROUP_NR] = {0x0, 0x1, 0x2, 0x3};
+static const u32 a_idxrxgain[RTW8851B_RXK_GROUP_IDX_NR] = {0x10C, 0x28c};
+static const u32 a_idxattc2[RTW8851B_RXK_GROUP_IDX_NR] = {0xf, 0xf};
+static const u32 a_idxrxagc[RTW8851B_RXK_GROUP_IDX_NR] = {0x4, 0x6};
+static const u32 a_power_range[RTW8851B_TXK_GROUP_NR] = {0x0};
+static const u32 a_track_range[RTW8851B_TXK_GROUP_NR] = {0x6};
+static const u32 a_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x0a};
+static const u32 a_itqt[RTW8851B_TXK_GROUP_NR] = {0x12};
+static const u32 g_power_range[RTW8851B_TXK_GROUP_NR] = {0x0};
+static const u32 g_track_range[RTW8851B_TXK_GROUP_NR] = {0x6};
+static const u32 g_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x10};
+static const u32 g_itqt[RTW8851B_TXK_GROUP_NR] = {0x12};
+
+static const u32 rtw8851b_backup_bb_regs[] = {0xc0d4, 0xc0d8, 0xc0c4, 0xc0ec, 0xc0e8};
+static const u32 rtw8851b_backup_rf_regs[] = {
+ 0xef, 0xde, 0x0, 0x1e, 0x2, 0x85, 0x90, 0x5};
+
+#define BACKUP_BB_REGS_NR ARRAY_SIZE(rtw8851b_backup_bb_regs)
+#define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8851b_backup_rf_regs)
+
+static const u32 dpk_kip_reg[DPK_KIP_REG_NUM_8851B] = {
+ 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8};
+static const u32 dpk_rf_reg[DPK_RF_REG_NUM_8851B] = {0xde, 0x8f, 0x5, 0x10005};
+
+static void _set_ch(struct rtw89_dev *rtwdev, u32 val);
+
+static u8 _rxk_5ghz_group_from_idx(u8 idx)
+{
+ /* There are four RXK groups (RTW8851B_RXK_GROUP_NR), but only group 0
+ * and 2 are used in 5 GHz band, so reduce elements to 2.
+ */
+ if (idx < RTW8851B_RXK_GROUP_IDX_NR)
+ return idx * 2;
+
+ return 0;
+}
+
+static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ return RF_A;
+}
+
+static void _adc_fifo_rst(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0101);
+ fsleep(10);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x1111);
+}
+
+static void _rfk_rf_direct_cntrl(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool is_bybb)
+{
+ if (is_bybb)
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1);
+ else
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+}
+
+static void _rfk_drf_direct_cntrl(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool is_bybb)
+{
+ if (is_bybb)
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x1);
+ else
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x0);
+}
+
+static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath)
+{
+ u32 rf_mode;
+ u8 path;
+ int ret;
+
+ for (path = 0; path < RF_PATH_MAX; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, rf_mode,
+ rf_mode != 2, 2, 5000, false,
+ rtwdev, path, 0x00, RR_MOD_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK] Wait S%d to Rx mode!! (ret = %d)\n",
+ path, ret);
+ }
+}
+
+static void _dack_reset(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_RST, 0x1);
+}
+
+static void _drck(struct rtw89_dev *rtwdev)
+{
+ u32 rck_d;
+ u32 val;
+ int ret;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]Ddie RCK start!!!\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_DRCK_RES, B_DRCK_POL);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DRCK timeout\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x1);
+ udelay(1);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK_FH, B_DRCK_LAT, 0x0);
+
+ rck_d = rtw89_phy_read32_mask(rtwdev, R_DRCK_RES, 0x7c00);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_IDLE, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_VAL, rck_d);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0xc0c4 = 0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_DRCK, MASKDWORD));
+}
+
+static void _addck_backup(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x0);
+
+ dack->addck_d[0][0] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A0);
+ dack->addck_d[0][1] = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_A1);
+}
+
+static void _addck_reload(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL1, dack->addck_d[0][0]);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RL0, dack->addck_d[0][1]);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0_RL, B_ADDCK0_RLS, 0x3);
+}
+
+static void _dack_backup_s0(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u8 i;
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x1);
+
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_DCOF0, B_DCOF0_V, i);
+ dack->msbk_d[0][0][i] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0M0);
+
+ rtw89_phy_write32_mask(rtwdev, R_DCOF8, B_DCOF8_V, i);
+ dack->msbk_d[0][1][i] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0M1);
+ }
+
+ dack->biask_d[0][0] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS00, B_DACK_BIAS00);
+ dack->biask_d[0][1] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_BIAS01, B_DACK_BIAS01);
+ dack->dadck_d[0][0] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK00, B_DACK_DADCK00) + 24;
+ dack->dadck_d[0][1] =
+ rtw89_phy_read32_mask(rtwdev, R_DACK_DADCK01, B_DACK_DADCK01) + 24;
+}
+
+static void _dack_reload_by_path(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, u8 index)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 idx_offset, path_offset;
+ u32 offset, reg;
+ u32 tmp;
+ u8 i;
+
+ if (index == 0)
+ idx_offset = 0;
+ else
+ idx_offset = 0x14;
+
+ if (path == RF_PATH_A)
+ path_offset = 0;
+ else
+ path_offset = 0x28;
+
+ offset = idx_offset + path_offset;
+
+ rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF9, B_DCOF9_RST, 0x1);
+
+ /* msbk_d: 15/14/13/12 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 12] << (i * 8);
+ reg = 0xc200 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 11/10/9/8 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 8] << (i * 8);
+ reg = 0xc204 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 7/6/5/4 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i + 4] << (i * 8);
+ reg = 0xc208 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* msbk_d: 3/2/1/0 */
+ tmp = 0x0;
+ for (i = 0; i < 4; i++)
+ tmp |= dack->msbk_d[path][index][i] << (i * 8);
+ reg = 0xc20c + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ /* dadak_d/biask_d */
+ tmp = 0x0;
+ tmp = (dack->biask_d[path][index] << 22) |
+ (dack->dadck_d[path][index] << 14);
+ reg = 0xc210 + offset;
+ rtw89_phy_write32(rtwdev, reg, tmp);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", reg,
+ rtw89_phy_read32_mask(rtwdev, reg, MASKDWORD));
+
+ rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL + offset, B_DACKN0_EN, 0x1);
+}
+
+static void _dack_reload(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ u8 index;
+
+ for (index = 0; index < 2; index++)
+ _dack_reload_by_path(rtwdev, path, index);
+}
+
+static void _addck(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 val;
+ int ret;
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_EN, 0x0);
+ udelay(1);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_ADDCKR0, BIT(0));
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADDCK timeout\n");
+ dack->addck_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ADDCK ret = %d\n", ret);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_RST, 0x0);
+}
+
+static void _new_dadck(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 i_dc, q_dc, ic, qc;
+ u32 val;
+ int ret;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_setup_defs_tbl);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val,
+ 1, 10000, false,
+ rtwdev, R_ADDCKR0, BIT(0));
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DADCK timeout\n");
+ dack->addck_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DADCK ret = %d\n", ret);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x0);
+ i_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC);
+ rtw89_phy_write32_mask(rtwdev, R_ADDCK0, B_ADDCK0_IQ, 0x1);
+ q_dc = rtw89_phy_read32_mask(rtwdev, R_ADDCKR0, B_ADDCKR0_DC);
+
+ ic = 0x80 - sign_extend32(i_dc, 11) * 6;
+ qc = 0x80 - sign_extend32(q_dc, 11) * 6;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]before DADCK, i_dc=0x%x, q_dc=0x%x\n", i_dc, q_dc);
+
+ dack->dadck_d[0][0] = ic;
+ dack->dadck_d[0][1] = qc;
+
+ rtw89_phy_write32_mask(rtwdev, R_DACKN0_CTL, B_DACKN0_V, dack->dadck_d[0][0]);
+ rtw89_phy_write32_mask(rtwdev, R_DACKN1_CTL, B_DACKN1_V, dack->dadck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DACK]after DADCK, 0xc210=0x%x, 0xc224=0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_DACKN0_CTL, MASKDWORD),
+ rtw89_phy_read32_mask(rtwdev, R_DACKN1_CTL, MASKDWORD));
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dadck_post_defs_tbl);
+}
+
+static bool _dack_s0_poll(struct rtw89_dev *rtwdev)
+{
+ if (rtw89_phy_read32_mask(rtwdev, R_DACK_S0P0, B_DACK_S0P0_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P1, B_DACK_S0P1_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P2, B_DACK_S0P2_OK) == 0 ||
+ rtw89_phy_read32_mask(rtwdev, R_DACK_S0P3, B_DACK_S0P3_OK) == 0)
+ return false;
+
+ return true;
+}
+
+static void _dack_s0(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ bool done;
+ int ret;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_1_defs_tbl);
+ _dack_reset(rtwdev, RF_PATH_A);
+ rtw89_phy_write32_mask(rtwdev, R_DCOF1, B_DCOF1_S, 0x1);
+
+ ret = read_poll_timeout_atomic(_dack_s0_poll, done, done,
+ 1, 10000, false, rtwdev);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DACK timeout\n");
+ dack->msbk_timeout[0] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_s0_2_defs_tbl);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S0 DADCK\n");
+
+ _dack_backup_s0(rtwdev);
+ _dack_reload(rtwdev, RF_PATH_A);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x0);
+}
+
+static void _dack(struct rtw89_dev *rtwdev)
+{
+ _dack_s0(rtwdev);
+}
+
+static void _dack_dump(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u8 i;
+ u8 t;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = 0x%x, qc = 0x%x\n",
+ dack->addck_d[0][0], dack->addck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n",
+ dack->dadck_d[0][0], dack->dadck_d[0][1]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask ic = 0x%x, qc = 0x%x\n",
+ dack->biask_d[0][0], dack->biask_d[0][1]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n");
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ t = dack->msbk_d[0][0][i];
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n");
+ for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
+ t = dack->msbk_d[0][1][i];
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
+ }
+}
+
+static void _dack_manual_off(struct rtw89_dev *rtwdev)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_dack_manual_off_defs_tbl);
+}
+
+static void _dac_cal(struct rtw89_dev *rtwdev, bool force)
+{
+ struct rtw89_dack_info *dack = &rtwdev->dack;
+ u32 rf0_0;
+
+ dack->dack_done = false;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK 0x2\n");
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK start!!!\n");
+ rf0_0 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]RF0=0x%x\n", rf0_0);
+
+ _drck(rtwdev);
+ _dack_manual_off(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x337e1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x0);
+
+ _addck(rtwdev);
+ _addck_backup(rtwdev);
+ _addck_reload(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x40001);
+
+ _dack(rtwdev);
+ _new_dadck(rtwdev);
+ _dack_dump(rtwdev);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x1);
+
+ dack->dack_done = true;
+ dack->dack_cnt++;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK finish!!!\n");
+}
+
+static void _rx_dck_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, bool is_afe)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] ==== S%d RX DCK (%s / CH%d / %s / by %s)====\n", path,
+ chan->band_type == RTW89_BAND_2G ? "2G" :
+ chan->band_type == RTW89_BAND_5G ? "5G" : "6G",
+ chan->channel,
+ chan->band_width == RTW89_CHANNEL_WIDTH_20 ? "20M" :
+ chan->band_width == RTW89_CHANNEL_WIDTH_40 ? "40M" : "80M",
+ is_afe ? "AFE" : "RFC");
+}
+
+static void _rxbb_ofst_swap(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode)
+{
+ u32 val, val_i, val_q;
+
+ val_i = rtw89_read_rf(rtwdev, path, RR_DCK, RR_DCK_S1);
+ val_q = rtw89_read_rf(rtwdev, path, RR_DCK1, RR_DCK1_S1);
+
+ val = val_q << 4 | val_i;
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, rf_mode);
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val);
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] val_i = 0x%x, val_q = 0x%x, 0x3F = 0x%x\n",
+ val_i, val_q, val);
+}
+
+static void _set_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode)
+{
+ u32 val;
+ int ret;
+
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x1);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, val, val,
+ 2, 2000, false,
+ rtwdev, path, RR_DCK, BIT(8));
+
+ rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RX_DCK] S%d RXDCK finish (ret = %d)\n",
+ path, ret);
+
+ _rxbb_ofst_swap(rtwdev, path, rf_mode);
+}
+
+static void _rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe)
+{
+ u32 rf_reg5;
+ u8 path;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RX_DCK] ****** RXDCK Start (Ver: 0x%x, Cv: %d) ******\n",
+ 0x2, rtwdev->hal.cv);
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ _rx_dck_info(rtwdev, phy, path, is_afe);
+
+ rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);
+
+ if (rtwdev->is_tssi_mode[path])
+ rtw89_phy_write32_mask(rtwdev,
+ R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, 0x1);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX);
+ _set_rx_dck(rtwdev, path, RF_RX);
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
+
+ if (rtwdev->is_tssi_mode[path])
+ rtw89_phy_write32_mask(rtwdev,
+ R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, 0x0);
+ }
+}
+
+static void _iqk_sram(struct rtw89_dev *rtwdev, u8 path)
+{
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00020000);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, MASKDWORD, 0x80000000);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009);
+
+ for (i = 0; i <= 0x9f; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD,
+ 0x00010000 + i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI));
+ }
+
+ for (i = 0; i <= 0x9f; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD,
+ 0x00010000 + i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n",
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ));
+ }
+
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00000000);
+}
+
+static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, 0xc);
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x1);
+}
+
+static bool _iqk_check_cal(struct rtw89_dev *rtwdev, u8 path)
+{
+ bool fail1 = false, fail2 = false;
+ u32 val;
+ int ret;
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55,
+ 10, 8200, false,
+ rtwdev, 0xbff8, MASKBYTE0);
+ if (ret) {
+ fail1 = true;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]NCTL1 IQK timeout!!!\n");
+ }
+
+ fsleep(10);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000,
+ 10, 200, false,
+ rtwdev, R_RPT_COM, B_RPT_COM_RDY);
+ if (ret) {
+ fail2 = true;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]NCTL2 IQK timeout!!!\n");
+ }
+
+ fsleep(10);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, ret = %d, notready = %x fail=%d,%d\n",
+ path, ret, fail1 || fail2, fail1, fail2);
+
+ return fail1 || fail2;
+}
+
+static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path, u8 ktype)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool notready;
+ u32 iqk_cmd;
+
+ switch (ktype) {
+ case ID_A_FLOK_COARSE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_A_FLOK_COARSE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x108 | (1 << (4 + path));
+ break;
+ case ID_G_FLOK_COARSE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_G_FLOK_COARSE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x108 | (1 << (4 + path));
+ break;
+ case ID_A_FLOK_FINE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_A_FLOK_FINE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x308 | (1 << (4 + path));
+ break;
+ case ID_G_FLOK_FINE:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_G_FLOK_FINE ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x308 | (1 << (4 + path));
+ break;
+ case ID_TXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_TXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ iqk_cmd = 0x008 | (1 << (path + 4)) |
+ (((0x8 + iqk_info->iqk_bw[path]) & 0xf) << 8);
+ break;
+ case ID_RXAGC:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_RXAGC ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x708 | (1 << (4 + path)) | (path << 1);
+ break;
+ case ID_RXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_RXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ iqk_cmd = 0x008 | (1 << (path + 4)) |
+ (((0xc + iqk_info->iqk_bw[path]) & 0xf) << 8);
+ break;
+ case ID_NBTXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_NBTXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT,
+ 0x00b);
+ iqk_cmd = 0x408 | (1 << (4 + path));
+ break;
+ case ID_NBRXK:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]============ S%d ID_NBRXK ============\n", path);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT,
+ 0x011);
+ iqk_cmd = 0x608 | (1 << (4 + path));
+ break;
+ default:
+ return false;
+ }
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, iqk_cmd + 1);
+ notready = _iqk_check_cal(rtwdev, path);
+ if (iqk_info->iqk_sram_en &&
+ (ktype == ID_NBRXK || ktype == ID_RXK))
+ _iqk_sram(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, ktype= %x, id = %x, notready = %x\n",
+ path, ktype, iqk_cmd + 1, notready);
+
+ return notready;
+}
+
+static bool _rxk_2g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u32 rf_0;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0; gp < RTW8851B_RXK_GROUP_NR; gp++) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(10);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail)
+ _iqk_sram(rtwdev, path);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_rxcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u32 rf_0;
+ u8 idx;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (idx = 0; idx < RTW8851B_RXK_GROUP_IDX_NR; idx++) {
+ gp = _rxk_5ghz_group_from_idx(idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(100);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, WBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail)
+ _iqk_sram(rtwdev, path);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD,
+ iqk_info->nb_rxcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD,
+ 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 idx = 0x1;
+ u32 rf_0;
+ u8 gp;
+
+ gp = _rxk_5ghz_group_from_idx(idx);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(100);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+
+ return kfail;
+}
+
+static bool _iqk_2g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp = 0x3;
+ u32 rf_0;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RGM, g_idxrxgain[gp]);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2, g_idxattc2[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP_V1, gp);
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RFREG_MASK, 0x80013);
+ fsleep(10);
+ rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, g_idxrxagc[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, RXAGC 0x8008 = 0x%x, rxbb = %x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD),
+ rtw89_read_rf(rtwdev, path, RR_MOD, 0x003e0));
+
+ rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK);
+ iqk_info->nb_rxcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC, MASKDWORD) | 0x2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, NBRXK 0x8008 = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, WBRXK 0x8008 = 0x%x\n",
+ path, rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD));
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_rxcfir[path]);
+ return kfail;
+}
+
+static void _iqk_rxclk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+
+ rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_CKT, 0x1);
+
+ if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80)
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_80_defs_tbl);
+ else
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_others_defs_tbl);
+}
+
+static bool _txk_5g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ MASKDWORD, a_itqt[gp]);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK);
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_txcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _txk_2g_group_sel(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ MASKDWORD, g_itqt[gp]);
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK);
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, iqk_info->nb_txcfir[path] | 0x2);
+ iqk_info->is_wb_txiqk[path] = false;
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000000);
+ iqk_info->is_wb_txiqk[path] = true;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_5g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2;
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_2g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool kfail = false;
+ bool notready;
+ u8 gp;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) {
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, g_itqt[gp]);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+
+ notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK);
+ iqk_info->nb_txcfir[path] =
+ rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD) | 0x2;
+ }
+
+ if (!notready)
+ kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG);
+
+ if (kfail) {
+ rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8),
+ MASKDWORD, 0x40000002);
+ iqk_info->is_wb_rxiqk[path] = false;
+ } else {
+ iqk_info->is_wb_rxiqk[path] = false;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S%x, kfail = 0x%x, 0x8%x38 = 0x%x\n", path, kfail,
+ 1 << path, iqk_info->nb_txcfir[path]);
+ return kfail;
+}
+
+static bool _iqk_2g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ static const u32 g_txbb[RTW8851B_LOK_GRAM] = {
+ 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ static const u32 g_itqt[RTW8851B_LOK_GRAM] = {
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b};
+ static const u32 g_wa[RTW8851B_LOK_GRAM] = {
+ 0x00, 0x04, 0x08, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ bool fail = false;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x6);
+
+ for (i = 0; i < RTW8851B_LOK_GRAM; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, g_txbb[i]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, g_wa[i]);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000109 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, g_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000309 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x58 = %x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK));
+ }
+
+ return fail;
+}
+
+static bool _iqk_5g_lok(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ static const u32 a_txbb[RTW8851B_LOK_GRAM] = {
+ 0x02, 0x06, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17};
+ static const u32 a_itqt[RTW8851B_LOK_GRAM] = {
+ 0x09, 0x09, 0x09, 0x12, 0x12, 0x12, 0x1b, 0x1b, 0x1b, 0x1b};
+ static const u32 a_wa[RTW8851B_LOK_GRAM] = {
+ 0x80, 0x84, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97};
+ bool fail = false;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_GR1, 0x7);
+
+ for (i = 0; i < RTW8851B_LOK_GRAM; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXIG, RR_TXIG_TG, a_txbb[i]);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RR_LUTWA_M1, a_wa[i]);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000109 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, B_KIP_IQP_IQSW, a_itqt[i]);
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x021);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD,
+ 0x00000309 | (1 << (4 + path)));
+ fail |= _iqk_check_cal(rtwdev, path);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x8[19:15] = 0x%x,0x8[09:05] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0xf8000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_DTXLOK, 0x003e0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x9[19:16] = 0x%x,0x9[09:06] = 0x%x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0xf0000),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV2, 0x003c0));
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]S0, i = %x, 0x58 = %x\n", i,
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_TXMO, RFREG_MASK));
+ }
+
+ return fail;
+}
+
+static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+
+ switch (iqk_info->iqk_band[path]) {
+ case RTW89_BAND_2G:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_2G\n");
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_2ghz_defs_tbl);
+ break;
+ case RTW89_BAND_5G:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]RTW89_BAND_5G\n");
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_txk_5ghz_defs_tbl);
+ break;
+ default:
+ break;
+ }
+}
+
+#define IQK_LOK_RETRY 1
+
+static void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ bool lok_is_fail;
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ for (i = 0; i < IQK_LOK_RETRY; i++) {
+ _iqk_txk_setting(rtwdev, path);
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ lok_is_fail = _iqk_2g_lok(rtwdev, phy_idx, path);
+ else
+ lok_is_fail = _iqk_5g_lok(rtwdev, phy_idx, path);
+
+ if (!lok_is_fail)
+ break;
+ }
+
+ if (iqk_info->is_nbiqk) {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_tx_fail[0][path] =
+ _iqk_2g_nbtxk(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_tx_fail[0][path] =
+ _iqk_5g_nbtxk(rtwdev, phy_idx, path);
+ } else {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_tx_fail[0][path] =
+ _txk_2g_group_sel(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_tx_fail[0][path] =
+ _txk_5g_group_sel(rtwdev, phy_idx, path);
+ }
+
+ _iqk_rxclk_setting(rtwdev, path);
+ _iqk_rxk_setting(rtwdev, path);
+ _adc_fifo_rst(rtwdev, phy_idx, path);
+
+ if (iqk_info->is_nbiqk) {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_rx_fail[0][path] =
+ _iqk_2g_nbrxk(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_rx_fail[0][path] =
+ _iqk_5g_nbrxk(rtwdev, phy_idx, path);
+ } else {
+ if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
+ iqk_info->iqk_rx_fail[0][path] =
+ _rxk_2g_group_sel(rtwdev, phy_idx, path);
+ else
+ iqk_info->iqk_rx_fail[0][path] =
+ _rxk_5g_group_sel(rtwdev, phy_idx, path);
+ }
+}
+
+static void _rfk_backup_bb_reg(struct rtw89_dev *rtwdev,
+ u32 backup_bb_reg_val[])
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
+ backup_bb_reg_val[i] =
+ rtw89_phy_read32_mask(rtwdev, rtw8851b_backup_bb_regs[i],
+ MASKDWORD);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]backup bb reg : %x, value =%x\n",
+ rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]);
+ }
+}
+
+static void _rfk_backup_rf_reg(struct rtw89_dev *rtwdev,
+ u32 backup_rf_reg_val[], u8 rf_path)
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
+ backup_rf_reg_val[i] =
+ rtw89_read_rf(rtwdev, rf_path,
+ rtw8851b_backup_rf_regs[i], RFREG_MASK);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]backup rf S%d reg : %x, value =%x\n", rf_path,
+ rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]);
+ }
+}
+
+static void _rfk_restore_bb_reg(struct rtw89_dev *rtwdev,
+ const u32 backup_bb_reg_val[])
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
+ rtw89_phy_write32_mask(rtwdev, rtw8851b_backup_bb_regs[i],
+ MASKDWORD, backup_bb_reg_val[i]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]restore bb reg : %x, value =%x\n",
+ rtw8851b_backup_bb_regs[i], backup_bb_reg_val[i]);
+ }
+}
+
+static void _rfk_restore_rf_reg(struct rtw89_dev *rtwdev,
+ const u32 backup_rf_reg_val[], u8 rf_path)
+{
+ u32 i;
+
+ for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
+ rtw89_write_rf(rtwdev, rf_path, rtw8851b_backup_rf_regs[i],
+ RFREG_MASK, backup_rf_reg_val[i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]restore rf S%d reg: %x, value =%x\n", rf_path,
+ rtw8851b_backup_rf_regs[i], backup_rf_reg_val[i]);
+ }
+}
+
+static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ u8 path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 idx = 0;
+
+ iqk_info->iqk_band[path] = chan->band_type;
+ iqk_info->iqk_bw[path] = chan->band_width;
+ iqk_info->iqk_ch[path] = chan->channel;
+ iqk_info->iqk_table_idx[path] = idx;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n",
+ path, phy, rtwdev->dbcc_en ? "on" : "off",
+ iqk_info->iqk_band[path] == 0 ? "2G" :
+ iqk_info->iqk_band[path] == 1 ? "5G" : "6G",
+ iqk_info->iqk_ch[path],
+ iqk_info->iqk_bw[path] == 0 ? "20M" :
+ iqk_info->iqk_bw[path] == 1 ? "40M" : "80M");
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]times = 0x%x, ch =%x\n",
+ iqk_info->iqk_times, idx);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, iqk_info->syn1to2= 0x%x\n",
+ path, iqk_info->syn1to2);
+}
+
+static void _iqk_start_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
+ u8 path)
+{
+ _iqk_by_path(rtwdev, phy_idx, path);
+}
+
+static void _iqk_restore(struct rtw89_dev *rtwdev, u8 path)
+{
+ bool fail;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, 0x00001219);
+ fsleep(10);
+ fail = _iqk_check_cal(rtwdev, path);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] restore fail=%d\n", fail);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RR_LUTWE_LOK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTDBG, RR_LUTDBG_TIA, 0x0);
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000);
+}
+
+static void _iqk_afebb_restore(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_afebb_restore_defs_tbl);
+}
+
+static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x81ff010a);
+}
+
+static void _iqk_macbb_setting(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_macbb_defs_tbl);
+}
+
+static void _iqk_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 idx, path;
+
+ rtw89_phy_write32_mask(rtwdev, R_IQKINF, MASKDWORD, 0x0);
+
+ if (iqk_info->is_iqk_init)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
+
+ iqk_info->is_iqk_init = true;
+ iqk_info->is_nbiqk = false;
+ iqk_info->iqk_fft_en = false;
+ iqk_info->iqk_sram_en = false;
+ iqk_info->iqk_cfir_en = false;
+ iqk_info->iqk_xym_en = false;
+ iqk_info->iqk_times = 0x0;
+
+ for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
+ iqk_info->iqk_channel[idx] = 0x0;
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ iqk_info->lok_cor_fail[idx][path] = false;
+ iqk_info->lok_fin_fail[idx][path] = false;
+ iqk_info->iqk_tx_fail[idx][path] = false;
+ iqk_info->iqk_rx_fail[idx][path] = false;
+ iqk_info->iqk_table_idx[path] = 0x0;
+ }
+ }
+}
+
+static void _doiqk(struct rtw89_dev *rtwdev, bool force,
+ enum rtw89_phy_idx phy_idx, u8 path)
+{
+ struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB);
+ u32 backup_rf_val[RTW8851B_IQK_SS][BACKUP_RF_REGS_NR];
+ u32 backup_bb_val[BACKUP_BB_REGS_NR];
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK,
+ BTC_WRFK_ONESHOT_START);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[IQK]==========IQK start!!!!!==========\n");
+ iqk_info->iqk_times++;
+ iqk_info->version = RTW8851B_IQK_VER;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
+ _iqk_get_ch_info(rtwdev, phy_idx, path);
+
+ _rfk_backup_bb_reg(rtwdev, &backup_bb_val[0]);
+ _rfk_backup_rf_reg(rtwdev, &backup_rf_val[path][0], path);
+ _iqk_macbb_setting(rtwdev, phy_idx, path);
+ _iqk_preset(rtwdev, path);
+ _iqk_start_iqk(rtwdev, phy_idx, path);
+ _iqk_restore(rtwdev, path);
+ _iqk_afebb_restore(rtwdev, phy_idx, path);
+ _rfk_restore_bb_reg(rtwdev, &backup_bb_val[0]);
+ _rfk_restore_rf_reg(rtwdev, &backup_rf_val[path][0], path);
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK,
+ BTC_WRFK_ONESHOT_STOP);
+}
+
+static void _iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool force)
+{
+ _doiqk(rtwdev, force, phy_idx, RF_PATH_A);
+}
+
+static void _dpk_bkup_kip(struct rtw89_dev *rtwdev, const u32 *reg,
+ u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) {
+ reg_bkup[path][i] =
+ rtw89_phy_read32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup 0x%x = %x\n",
+ reg[i] + (path << 8), reg_bkup[path][i]);
+ }
+}
+
+static void _dpk_bkup_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg,
+ u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) {
+ rf_bkup[path][i] = rtw89_read_rf(rtwdev, path, rf_reg[i], RFREG_MASK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup RF S%d 0x%x = %x\n",
+ path, rf_reg[i], rf_bkup[path][i]);
+ }
+}
+
+static void _dpk_reload_kip(struct rtw89_dev *rtwdev, const u32 *reg,
+ u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) {
+ rtw89_phy_write32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD,
+ reg_bkup[path][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Reload 0x%x = %x\n",
+ reg[i] + (path << 8), reg_bkup[path][i]);
+ }
+}
+
+static void _dpk_reload_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg,
+ u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path)
+{
+ u8 i;
+
+ for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) {
+ rtw89_write_rf(rtwdev, path, rf_reg[i], RFREG_MASK, rf_bkup[path][i]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Reload RF S%d 0x%x = %x\n", path,
+ rf_reg[i], rf_bkup[path][i]);
+ }
+}
+
+static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, enum dpk_id id)
+{
+ u16 dpk_cmd;
+ u32 val;
+ int ret;
+
+ dpk_cmd = ((id << 8) | (0x19 + path * 0x12));
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, dpk_cmd);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55,
+ 10, 20000, false,
+ rtwdev, 0xbff8, MASKBYTE0);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 1 timeout\n");
+
+ udelay(1);
+
+ ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000,
+ 1, 2000, false,
+ rtwdev, R_RPT_COM, MASKLWORD);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 2 timeout\n");
+
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] one-shot for %s = 0x%04x\n",
+ id == 0x28 ? "KIP_PRESET" :
+ id == 0x29 ? "DPK_TXAGC" :
+ id == 0x2a ? "DPK_RXAGC" :
+ id == 0x2b ? "SYNC" :
+ id == 0x2c ? "GAIN_LOSS" :
+ id == 0x2d ? "MDPK_IDL" :
+ id == 0x2f ? "DPK_GAIN_NORM" :
+ id == 0x31 ? "KIP_RESTORE" :
+ id == 0x6 ? "LBK_RXIQK" : "Unknown id",
+ dpk_cmd);
+}
+
+static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool off)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 kidx = dpk->cur_idx[path];
+ u8 off_reverse = off ? 0 : 1;
+ u8 val;
+
+ val = dpk->is_dpk_enable * off_reverse * dpk->bp[path][kidx].path_ok;
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ 0xf0000000, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path,
+ kidx, val == 0 ? "disable" : "enable");
+}
+
+static void _dpk_init(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ u8 kidx = dpk->cur_idx[path];
+
+ dpk->bp[path][kidx].path_ok = 0;
+}
+
+static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ u8 kidx = dpk->cur_idx[path];
+
+ dpk->bp[path][kidx].band = chan->band_type;
+ dpk->bp[path][kidx].ch = chan->band_width;
+ dpk->bp[path][kidx].bw = chan->channel;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
+ path, dpk->cur_idx[path], phy,
+ rtwdev->is_tssi_mode[path] ? "on" : "off",
+ rtwdev->dbcc_en ? "on" : "off",
+ dpk->bp[path][kidx].band == 0 ? "2G" :
+ dpk->bp[path][kidx].band == 1 ? "5G" : "6G",
+ dpk->bp[path][kidx].ch,
+ dpk->bp[path][kidx].bw == 0 ? "20M" :
+ dpk->bp[path][kidx].bw == 1 ? "40M" :
+ dpk->bp[path][kidx].bw == 2 ? "80M" : "160M");
+}
+
+static void _dpk_rxagc_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool turn_on)
+{
+ if (path == RF_PATH_A)
+ rtw89_phy_write32_mask(rtwdev, R_P0_AGC_CTL, B_P0_AGC_EN, turn_on);
+ else
+ rtw89_phy_write32_mask(rtwdev, R_P1_AGC_CTL, B_P1_AGC_EN, turn_on);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d RXAGC is %s\n", path,
+ turn_on ? "turn_on" : "turn_off");
+}
+
+static void _dpk_bb_afe_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0xd801dffd);
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_bb_afe_defs_tbl);
+
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x1);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE setting\n", path);
+}
+
+static void _dpk_bb_afe_restore(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13), B_P0_TXCK_ALL, 0x00);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE restore\n", path);
+}
+
+static void _dpk_tssi_pause(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ bool is_pause)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK + (path << 13),
+ B_P0_TSSI_TRK_EN, is_pause);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d TSSI %s\n", path,
+ is_pause ? "pause" : "resume");
+}
+
+static void _dpk_tpg_sel(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80) {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xffe0fa00);
+ } else if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40) {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xff4009e0);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xf9f007d0);
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] TPG Select for %s\n",
+ dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80 ? "80M" :
+ dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40 ? "40M" : "20M");
+}
+
+static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool force)
+{
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), B_TXPWRB_ON, force);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n",
+ path, force ? "on" : "off");
+}
+
+static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on)
+{
+ if (turn_on) {
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x807f030a);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_WR, BIT(18), 0x1);
+ }
+}
+
+static void _dpk_kip_control_rfc(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, bool ctrl_by_kip)
+{
+ rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13),
+ B_IQK_RFC_ON, ctrl_by_kip);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] RFC is controlled by %s\n",
+ ctrl_by_kip ? "KIP" : "BB");
+}
+
+static void _dpk_kip_preset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD,
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_SEL, 0x01);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+ _dpk_one_shot(rtwdev, phy, path, D_KIP_PRESET);
+}
+
+static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ _dpk_one_shot(rtwdev, phy, path, D_KIP_RESTORE);
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ _dpk_txpwr_bb_force(rtwdev, path, false);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d restore KIP\n", path);
+}
+
+static void _dpk_kset_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0x10);
+
+ dpk->cur_k_set =
+ rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), B_RPT_PER_KSET) - 1;
+}
+
+static void _dpk_para_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = {
+ {0x8190, 0x8194, 0x8198, 0x81a4},
+ {0x81a8, 0x81c4, 0x81c8, 0x81e8}
+ };
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 cur_k_set = dpk->cur_k_set;
+ u32 para;
+
+ if (cur_k_set >= DPK_KSET_NUM) {
+ rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set);
+ cur_k_set = 2;
+ }
+
+ para = rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ MASKDWORD);
+
+ dpk->bp[path][kidx].txagc_dpk = (para >> 10) & 0x3f;
+ dpk->bp[path][kidx].ther_dpk = (para >> 26) & 0x3f;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] thermal/ txagc_RF (K%d) = 0x%x/ 0x%x\n",
+ dpk->cur_k_set, dpk->bp[path][kidx].ther_dpk,
+ dpk->bp[path][kidx].txagc_dpk);
+}
+
+static bool _dpk_sync_check(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 corr_val, corr_idx, rxbb;
+ u16 dc_i, dc_q;
+ u8 rxbb_ov;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0);
+
+ corr_idx = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORI);
+ corr_val = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORV);
+ dpk->corr_idx[path][kidx] = corr_idx;
+ dpk->corr_val[path][kidx] = corr_val;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x9);
+
+ dc_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI);
+ dc_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ);
+
+ dc_i = abs(sign_extend32(dc_i, 11));
+ dc_q = abs(sign_extend32(dc_q, 11));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d Corr_idx/ Corr_val /DC I/Q, = %d / %d / %d / %d\n",
+ path, corr_idx, corr_val, dc_i, dc_q);
+
+ dpk->dc_i[path][kidx] = dc_i;
+ dpk->dc_q[path][kidx] = dc_q;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x8);
+ rxbb = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXBB);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x31);
+ rxbb_ov = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXOV);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] S%d RXBB/ RXAGC_done /RXBB_ovlmt = %d / %d / %d\n",
+ path, rxbb,
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DONE),
+ rxbb_ov);
+
+ if (dc_i > 200 || dc_q > 200 || corr_val < 170)
+ return true;
+ else
+ return false;
+}
+
+static void _dpk_kip_set_txagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 dbm,
+ bool set_from_bb)
+{
+ if (set_from_bb) {
+ dbm = clamp_t(u8, dbm, 7, 24);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] set S%d txagc to %ddBm\n", path, dbm);
+ rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13),
+ B_TXPWRB_VAL, dbm << 2);
+ }
+
+ _dpk_one_shot(rtwdev, phy, path, D_TXAGC);
+ _dpk_kset_query(rtwdev, path);
+}
+
+static bool _dpk_kip_set_rxagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD,
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+ _dpk_kip_control_rfc(rtwdev, path, true);
+
+ _dpk_one_shot(rtwdev, phy, path, D_RXAGC);
+ return _dpk_sync_check(rtwdev, path, kidx);
+}
+
+static void _dpk_lbk_rxiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ u32 rf_11, reg_81cc;
+ u8 cur_rxbb;
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x1);
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+
+ cur_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB);
+ rf_11 = rtw89_read_rf(rtwdev, path, RR_TXIG, RFREG_MASK);
+ reg_81cc = rtw89_phy_read32_mask(rtwdev, R_KIP_IQP + (path << 8),
+ B_KIP_IQP_SW);
+
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, 0x3);
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, 0xd);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, 0x1f);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_IQSW, 0x12);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, 0x3);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+
+ rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, MASKDWORD, 0x00250025);
+
+ _dpk_one_shot(rtwdev, phy, path, LBK_RXIQK);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d LBK RXIQC = 0x%x\n", path,
+ rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD));
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+
+ rtw89_write_rf(rtwdev, path, RR_TXIG, RFREG_MASK, rf_11);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, cur_rxbb);
+ rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, reg_81cc);
+
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_KPATH_CFG, B_KPATH_CFG_ED, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_DI, 0x1);
+
+ _dpk_kip_control_rfc(rtwdev, path, true);
+}
+
+static void _dpk_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ if (dpk->bp[path][kidx].band == RTW89_BAND_2G) {
+ rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, 0x50521);
+ rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTC, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTR, 0x7);
+ } else {
+ rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK,
+ 0x50521 | BIT(rtwdev->dbcc_en));
+ rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK);
+ rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RAA2_SATT, 0x3);
+ }
+
+ rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_BW, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_TXBB, dpk->bp[path][kidx].bw + 1);
+ rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_RXBB, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0);
+}
+
+static void _dpk_bypass_rxiqc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, 0x40000002);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Bypass RXIQC\n");
+}
+
+static u16 _dpk_dgain_read(struct rtw89_dev *rtwdev)
+{
+ u16 dgain;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0);
+ dgain = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] DGain = 0x%x\n", dgain);
+
+ return dgain;
+}
+
+static u8 _dpk_gainloss_read(struct rtw89_dev *rtwdev)
+{
+ u8 result;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x6);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x1);
+ result = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_GL);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] tmp GL = %d\n", result);
+
+ return result;
+}
+
+static u8 _dpk_gainloss(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ _dpk_one_shot(rtwdev, phy, path, D_GAIN_LOSS);
+ _dpk_kip_set_txagc(rtwdev, phy, path, 0xff, false);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A1, 0xf078);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A0, 0x0);
+
+ return _dpk_gainloss_read(rtwdev);
+}
+
+static u8 _dpk_pas_read(struct rtw89_dev *rtwdev, u8 is_check)
+{
+ u32 val1_i = 0, val1_q = 0, val2_i = 0, val2_q = 0;
+ u32 val1_sqrt_sum, val2_sqrt_sum;
+ u8 i;
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKBYTE2, 0x06);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE2, 0x08);
+
+ if (is_check) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x00);
+ val1_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD);
+ val1_i = abs(sign_extend32(val1_i, 11));
+ val1_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD);
+ val1_q = abs(sign_extend32(val1_q, 11));
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x1f);
+ val2_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD);
+ val2_i = abs(sign_extend32(val2_i, 11));
+ val2_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD);
+ val2_q = abs(sign_extend32(val2_q, 11));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] PAS_delta = 0x%x\n",
+ phy_div(val1_i * val1_i + val1_q * val1_q,
+ val2_i * val2_i + val2_q * val2_q));
+ } else {
+ for (i = 0; i < 32; i++) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, i);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] PAS_Read[%02d]= 0x%08x\n", i,
+ rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD));
+ }
+ }
+
+ val1_sqrt_sum = val1_i * val1_i + val1_q * val1_q;
+ val2_sqrt_sum = val2_i * val2_i + val2_q * val2_q;
+
+ if (val1_sqrt_sum < val2_sqrt_sum)
+ return 2;
+ else if (val1_sqrt_sum >= val2_sqrt_sum * 8 / 5)
+ return 1;
+ else
+ return 0;
+}
+
+static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx, u8 init_xdbm, u8 loss_only)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 tmp_dbm = init_xdbm, tmp_gl_idx = 0;
+ u8 step = DPK_AGC_STEP_SYNC_DGAIN;
+ u8 goout = 0, agc_cnt = 0;
+ bool is_fail = false;
+ int limit = 200;
+ u8 tmp_rxbb;
+ u16 dgain;
+
+ do {
+ switch (step) {
+ case DPK_AGC_STEP_SYNC_DGAIN:
+ is_fail = _dpk_kip_set_rxagc(rtwdev, phy, path, kidx);
+
+ if (is_fail) {
+ goout = 1;
+ break;
+ }
+
+ dgain = _dpk_dgain_read(rtwdev);
+
+ if (dgain > 0x5fc || dgain < 0x556) {
+ _dpk_one_shot(rtwdev, phy, path, D_SYNC);
+ dgain = _dpk_dgain_read(rtwdev);
+ }
+
+ if (agc_cnt == 0) {
+ if (dpk->bp[path][kidx].band == RTW89_BAND_2G)
+ _dpk_bypass_rxiqc(rtwdev, path);
+ else
+ _dpk_lbk_rxiqk(rtwdev, phy, path);
+ }
+ step = DPK_AGC_STEP_GAIN_LOSS_IDX;
+ break;
+
+ case DPK_AGC_STEP_GAIN_LOSS_IDX:
+ tmp_gl_idx = _dpk_gainloss(rtwdev, phy, path, kidx);
+
+ if (_dpk_pas_read(rtwdev, true) == 2 && tmp_gl_idx > 0)
+ step = DPK_AGC_STEP_GL_LT_CRITERION;
+ else if ((tmp_gl_idx == 0 && _dpk_pas_read(rtwdev, true) == 1) ||
+ tmp_gl_idx >= 7)
+ step = DPK_AGC_STEP_GL_GT_CRITERION;
+ else if (tmp_gl_idx == 0)
+ step = DPK_AGC_STEP_GL_LT_CRITERION;
+ else
+ step = DPK_AGC_STEP_SET_TX_GAIN;
+ break;
+
+ case DPK_AGC_STEP_GL_GT_CRITERION:
+ if (tmp_dbm <= 7) {
+ goout = 1;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Txagc@lower bound!!\n");
+ } else {
+ tmp_dbm = max_t(u8, tmp_dbm - 3, 7);
+ _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true);
+ }
+ step = DPK_AGC_STEP_SYNC_DGAIN;
+ agc_cnt++;
+ break;
+
+ case DPK_AGC_STEP_GL_LT_CRITERION:
+ if (tmp_dbm >= 24) {
+ goout = 1;
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Txagc@upper bound!!\n");
+ } else {
+ tmp_dbm = min_t(u8, tmp_dbm + 2, 24);
+ _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true);
+ }
+ step = DPK_AGC_STEP_SYNC_DGAIN;
+ agc_cnt++;
+ break;
+
+ case DPK_AGC_STEP_SET_TX_GAIN:
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ tmp_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB);
+ tmp_rxbb = min_t(u8, tmp_rxbb + tmp_gl_idx, 0x1f);
+
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, tmp_rxbb);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Adjust RXBB (%+d) = 0x%x\n",
+ tmp_gl_idx, tmp_rxbb);
+ _dpk_kip_control_rfc(rtwdev, path, true);
+ goout = 1;
+ break;
+ default:
+ goout = 1;
+ break;
+ }
+ } while (!goout && agc_cnt < 6 && limit-- > 0);
+
+ return is_fail;
+}
+
+static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order)
+{
+ switch (order) {
+ case 0: /* (5,3,1) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1);
+ break;
+ case 1: /* (5,3,0) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0);
+ break;
+ case 2: /* (5,0,0) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x2);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0);
+ break;
+ case 3: /* (7,3,1) */
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4);
+ rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1);
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] Wrong MDPD order!!(0x%x)\n", order);
+ break;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Set %s for IDL\n",
+ order == 0x0 ? "(5,3,1)" :
+ order == 0x1 ? "(5,3,0)" :
+ order == 0x2 ? "(5,0,0)" : "(7,3,1)");
+}
+
+static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_MA, 0x1);
+
+ if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD500) == 0x1)
+ _dpk_set_mdpd_para(rtwdev, 0x2);
+ else if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD530) == 0x1)
+ _dpk_set_mdpd_para(rtwdev, 0x1);
+ else
+ _dpk_set_mdpd_para(rtwdev, 0x0);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL, 0x0);
+ fsleep(1000);
+
+ _dpk_one_shot(rtwdev, phy, path, D_MDPK_IDL);
+}
+
+static u8 _dpk_order_convert(struct rtw89_dev *rtwdev)
+{
+ u32 order;
+ u8 val;
+
+ order = rtw89_phy_read32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP);
+
+ switch (order) {
+ case 0: /* (5,3,1) */
+ val = 0x6;
+ break;
+ case 1: /* (5,3,0) */
+ val = 0x2;
+ break;
+ case 2: /* (5,0,0) */
+ val = 0x0;
+ break;
+ default:
+ val = 0xff;
+ break;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] convert MDPD order to 0x%x\n", val);
+
+ return val;
+}
+
+static void _dpk_gain_normalize(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx, bool is_execute)
+{
+ static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = {
+ {0x8190, 0x8194, 0x8198, 0x81a4},
+ {0x81a8, 0x81c4, 0x81c8, 0x81e8}
+ };
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 cur_k_set = dpk->cur_k_set;
+
+ if (cur_k_set >= DPK_KSET_NUM) {
+ rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set);
+ cur_k_set = 2;
+ }
+
+ if (is_execute) {
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8),
+ B_DPK_GN_AG, 0x200);
+ rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8),
+ B_DPK_GN_EN, 0x3);
+
+ _dpk_one_shot(rtwdev, phy, path, D_GAIN_NORM);
+ } else {
+ rtw89_phy_write32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ 0x0000007F, 0x5b);
+ }
+
+ dpk->bp[path][kidx].gs =
+ rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8),
+ 0x0000007F);
+}
+
+static void _dpk_on(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, u8 kidx)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_ORDER, _dpk_order_convert(rtwdev));
+
+ dpk->bp[path][kidx].path_ok =
+ dpk->bp[path][kidx].path_ok | BIT(dpk->cur_k_set);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] path_ok = 0x%x\n",
+ path, kidx, dpk->bp[path][kidx].path_ok);
+
+ rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2),
+ B_DPD_MEN, dpk->bp[path][kidx].path_ok);
+
+ _dpk_gain_normalize(rtwdev, phy, path, kidx, false);
+}
+
+static bool _dpk_main(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u8 kidx = dpk->cur_idx[path];
+ u8 init_xdbm = 17;
+ bool is_fail;
+
+ if (dpk->bp[path][kidx].band != RTW89_BAND_2G)
+ init_xdbm = 15;
+
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ _rfk_rf_direct_cntrl(rtwdev, path, false);
+ rtw89_write_rf(rtwdev, path, RR_BBDC, RFREG_MASK, 0x03ffd);
+
+ _dpk_rf_setting(rtwdev, path, kidx);
+ _set_rx_dck(rtwdev, path, RF_DPK);
+
+ _dpk_kip_pwr_clk_onoff(rtwdev, true);
+ _dpk_kip_preset(rtwdev, phy, path, kidx);
+ _dpk_txpwr_bb_force(rtwdev, path, true);
+ _dpk_kip_set_txagc(rtwdev, phy, path, init_xdbm, true);
+ _dpk_tpg_sel(rtwdev, path, kidx);
+ is_fail = _dpk_agc(rtwdev, phy, path, kidx, init_xdbm, false);
+ if (is_fail)
+ goto _error;
+
+ _dpk_idl_mpa(rtwdev, phy, path, kidx);
+ _dpk_para_query(rtwdev, path, kidx);
+
+ _dpk_on(rtwdev, phy, path, kidx);
+_error:
+ _dpk_kip_control_rfc(rtwdev, path, false);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d]_K%d %s\n", path, kidx,
+ dpk->cur_k_set, is_fail ? "need Check" : "is Success");
+
+ return is_fail;
+}
+
+static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
+ enum rtw89_phy_idx phy, u8 kpath)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ u32 kip_bkup[RF_PATH_NUM_8851B][DPK_KIP_REG_NUM_8851B] = {};
+ u32 rf_bkup[RF_PATH_NUM_8851B][DPK_RF_REG_NUM_8851B] = {};
+ bool is_fail;
+ u8 path;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++)
+ dpk->cur_idx[path] = 0;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+ _dpk_bkup_kip(rtwdev, dpk_kip_reg, kip_bkup, path);
+ _dpk_bkup_rf(rtwdev, dpk_rf_reg, rf_bkup, path);
+ _dpk_information(rtwdev, phy, path);
+ _dpk_init(rtwdev, path);
+
+ if (rtwdev->is_tssi_mode[path])
+ _dpk_tssi_pause(rtwdev, path, true);
+ }
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] ========= S%d[%d] DPK Start =========\n",
+ path, dpk->cur_idx[path]);
+
+ _dpk_rxagc_onoff(rtwdev, path, false);
+ _rfk_drf_direct_cntrl(rtwdev, path, false);
+ _dpk_bb_afe_setting(rtwdev, path);
+
+ is_fail = _dpk_main(rtwdev, phy, path);
+ _dpk_onoff(rtwdev, path, is_fail);
+ }
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ _dpk_kip_restore(rtwdev, phy, path);
+ _dpk_reload_kip(rtwdev, dpk_kip_reg, kip_bkup, path);
+ _dpk_reload_rf(rtwdev, dpk_rf_reg, rf_bkup, path);
+ _dpk_bb_afe_restore(rtwdev, path);
+ _dpk_rxagc_onoff(rtwdev, path, true);
+
+ if (rtwdev->is_tssi_mode[path])
+ _dpk_tssi_pause(rtwdev, path, false);
+ }
+
+ _dpk_kip_pwr_clk_onoff(rtwdev, false);
+}
+
+static void _dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool force)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[DPK] ****** 8851B DPK Start (Ver: 0x%x, Cv: %d) ******\n",
+ DPK_VER_8851B, rtwdev->hal.cv);
+
+ _dpk_cal_select(rtwdev, force, phy, _kpath(rtwdev, phy));
+}
+
+static void _dpk_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+ s8 txagc_bb, txagc_bb_tp, txagc_ofst;
+ s16 pwsf_tssi_ofst;
+ s8 delta_ther = 0;
+ u8 path, kidx;
+ u8 txagc_rf;
+ u8 cur_ther;
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ kidx = dpk->cur_idx[path];
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] ================[S%d[%d] (CH %d)]================\n",
+ path, kidx, dpk->bp[path][kidx].ch);
+
+ txagc_rf = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13),
+ B_TXAGC_RF);
+ txagc_bb = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13),
+ MASKBYTE2);
+ txagc_bb_tp = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BTP + (path << 13),
+ B_TXAGC_BTP);
+
+ rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8),
+ B_KIP_RPT_SEL, 0xf);
+ cur_ther = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_TH);
+ txagc_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_OF);
+ pwsf_tssi_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8),
+ B_RPT_PER_TSSI);
+ pwsf_tssi_ofst = sign_extend32(pwsf_tssi_ofst, 12);
+
+ delta_ther = cur_ther - dpk->bp[path][kidx].ther_dpk;
+
+ delta_ther = delta_ther * 2 / 3;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] extra delta_ther = %d (0x%x / 0x%x@k)\n",
+ delta_ther, cur_ther, dpk->bp[path][kidx].ther_dpk);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] delta_txagc = %d (0x%x / 0x%x@k)\n",
+ txagc_rf - dpk->bp[path][kidx].txagc_dpk,
+ txagc_rf, dpk->bp[path][kidx].txagc_dpk);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] txagc_offset / pwsf_tssi_ofst = 0x%x / %+d\n",
+ txagc_ofst, pwsf_tssi_ofst);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] txagc_bb_tp / txagc_bb = 0x%x / 0x%x\n",
+ txagc_bb_tp, txagc_bb);
+
+ if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_DN) == 0x0 &&
+ txagc_rf != 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[DPK_TRK] New pwsf = 0x%x\n", 0x78 - delta_ther);
+
+ rtw89_phy_write32_mask(rtwdev,
+ R_DPD_BND + (path << 8) + (kidx << 2),
+ 0x07FC0000, 0x78 - delta_ther);
+ }
+ }
+}
+
+static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ u32 rf_reg5;
+ u32 rck_val;
+ u32 val;
+ int ret;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path);
+
+ rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);
+
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
+ rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%05x\n",
+ rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));
+
+ /* RCK trigger */
+ rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 30,
+ false, rtwdev, path, RR_RCKS, BIT(3));
+
+ rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] rck_val = 0x%x, ret = %d\n",
+ rck_val, ret);
+
+ rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val);
+ rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF 0x1b = 0x%x\n",
+ rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK));
+}
+
+static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_sys_defs_tbl);
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_sys_a_defs_2g_tbl,
+ &rtw8851b_tssi_sys_a_defs_5g_tbl);
+}
+
+static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_defs_a_tbl);
+}
+
+static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_he_tb_defs_a_tbl);
+}
+
+static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dck_defs_a_tbl);
+}
+
+static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+#define RTW8851B_TSSI_GET_VAL(ptr, idx) \
+({ \
+ s8 *__ptr = (ptr); \
+ u8 __idx = (idx), __i, __v; \
+ u32 __val = 0; \
+ for (__i = 0; __i < 4; __i++) { \
+ __v = (__ptr[__idx + __i]); \
+ __val |= (__v << (8 * __i)); \
+ } \
+ __val; \
+})
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 ch = chan->channel;
+ u8 subband = chan->subband_type;
+ const s8 *thm_up_a = NULL;
+ const s8 *thm_down_a = NULL;
+ u8 thermal = 0xff;
+ s8 thm_ofst[64] = {0};
+ u32 tmp = 0;
+ u8 i, j;
+
+ switch (subband) {
+ default:
+ case RTW89_CH_2G:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_p;
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_n;
+ break;
+ case RTW89_CH_5G_BAND_1:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[0];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[0];
+ break;
+ case RTW89_CH_5G_BAND_3:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[1];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[1];
+ break;
+ case RTW89_CH_5G_BAND_4:
+ thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[2];
+ thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[2];
+ break;
+ }
+
+ if (path == RF_PATH_A) {
+ thermal = tssi_info->thermal[RF_PATH_A];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] ch=%d thermal_pathA=0x%x\n", ch, thermal);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_DIS, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_TRK, 0x1);
+
+ if (thermal == 0xff) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, 32);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, 32);
+
+ for (i = 0; i < 64; i += 4) {
+ rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] write 0x%x val=0x%08x\n",
+ R_P0_TSSI_BASE + i, 0x0);
+ }
+
+ } else {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER,
+ thermal);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL,
+ thermal);
+
+ i = 0;
+ for (j = 0; j < 32; j++)
+ thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
+ -thm_down_a[i++] :
+ -thm_down_a[DELTA_SWINGIDX_SIZE - 1];
+
+ i = 1;
+ for (j = 63; j >= 32; j--)
+ thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
+ thm_up_a[i++] :
+ thm_up_a[DELTA_SWINGIDX_SIZE - 1];
+
+ for (i = 0; i < 64; i += 4) {
+ tmp = RTW8851B_TSSI_GET_VAL(thm_ofst, i);
+ rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, tmp);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] write 0x%x val=0x%08x\n",
+ 0x5c00 + i, tmp);
+ }
+ }
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x0);
+ }
+#undef RTW8851B_TSSI_GET_VAL
+}
+
+static void _tssi_set_dac_gain_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dac_gain_defs_a_tbl);
+}
+
+static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_slope_a_defs_2g_tbl,
+ &rtw8851b_tssi_slope_a_defs_5g_tbl);
+}
+
+static void _tssi_alignment_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path, bool all)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ enum rtw89_band band = chan->band_type;
+
+ rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
+ &rtw8851b_tssi_align_a_2g_defs_tbl,
+ &rtw8851b_tssi_align_a_5g_defs_tbl);
+}
+
+static void _tssi_set_tssi_slope(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_slope_defs_a_tbl);
+}
+
+static void _tssi_set_tssi_track(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_track_defs_a_tbl);
+}
+
+static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_mv_avg_defs_a_tbl);
+}
+
+static void _tssi_enable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ _tssi_set_tssi_track(rtwdev, phy, RF_PATH_A);
+ _tssi_set_txagc_offset_mv_avg(rtwdev, phy, RF_PATH_A);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXGA_V1, RR_TXGA_V1_TRK_EN, 0x1);
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_RFC, 0x3);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+
+ rtwdev->is_tssi_mode[RF_PATH_A] = true;
+}
+
+static void _tssi_disable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x1);
+
+ rtwdev->is_tssi_mode[RF_PATH_A] = false;
+}
+
+static u32 _tssi_get_cck_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 2:
+ return 0;
+ case 3 ... 5:
+ return 1;
+ case 6 ... 8:
+ return 2;
+ case 9 ... 11:
+ return 3;
+ case 12 ... 13:
+ return 4;
+ case 14:
+ return 5;
+ }
+
+ return 0;
+}
+
+#define TSSI_EXTRA_GROUP_BIT (BIT(31))
+#define TSSI_EXTRA_GROUP(idx) (TSSI_EXTRA_GROUP_BIT | (idx))
+#define IS_TSSI_EXTRA_GROUP(group) ((group) & TSSI_EXTRA_GROUP_BIT)
+#define TSSI_EXTRA_GET_GROUP_IDX1(group) ((group) & ~TSSI_EXTRA_GROUP_BIT)
+#define TSSI_EXTRA_GET_GROUP_IDX2(group) (TSSI_EXTRA_GET_GROUP_IDX1(group) + 1)
+
+static u32 _tssi_get_ofdm_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 2:
+ return 0;
+ case 3 ... 5:
+ return 1;
+ case 6 ... 8:
+ return 2;
+ case 9 ... 11:
+ return 3;
+ case 12 ... 14:
+ return 4;
+ case 36 ... 40:
+ return 5;
+ case 41 ... 43:
+ return TSSI_EXTRA_GROUP(5);
+ case 44 ... 48:
+ return 6;
+ case 49 ... 51:
+ return TSSI_EXTRA_GROUP(6);
+ case 52 ... 56:
+ return 7;
+ case 57 ... 59:
+ return TSSI_EXTRA_GROUP(7);
+ case 60 ... 64:
+ return 8;
+ case 100 ... 104:
+ return 9;
+ case 105 ... 107:
+ return TSSI_EXTRA_GROUP(9);
+ case 108 ... 112:
+ return 10;
+ case 113 ... 115:
+ return TSSI_EXTRA_GROUP(10);
+ case 116 ... 120:
+ return 11;
+ case 121 ... 123:
+ return TSSI_EXTRA_GROUP(11);
+ case 124 ... 128:
+ return 12;
+ case 129 ... 131:
+ return TSSI_EXTRA_GROUP(12);
+ case 132 ... 136:
+ return 13;
+ case 137 ... 139:
+ return TSSI_EXTRA_GROUP(13);
+ case 140 ... 144:
+ return 14;
+ case 149 ... 153:
+ return 15;
+ case 154 ... 156:
+ return TSSI_EXTRA_GROUP(15);
+ case 157 ... 161:
+ return 16;
+ case 162 ... 164:
+ return TSSI_EXTRA_GROUP(16);
+ case 165 ... 169:
+ return 17;
+ case 170 ... 172:
+ return TSSI_EXTRA_GROUP(17);
+ case 173 ... 177:
+ return 18;
+ }
+
+ return 0;
+}
+
+static u32 _tssi_get_trim_group(struct rtw89_dev *rtwdev, u8 ch)
+{
+ switch (ch) {
+ case 1 ... 8:
+ return 0;
+ case 9 ... 14:
+ return 1;
+ case 36 ... 48:
+ return 2;
+ case 52 ... 64:
+ return 3;
+ case 100 ... 112:
+ return 4;
+ case 116 ... 128:
+ return 5;
+ case 132 ... 144:
+ return 6;
+ case 149 ... 177:
+ return 7;
+ }
+
+ return 0;
+}
+
+static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 gidx, gidx_1st, gidx_2nd;
+ u8 ch = chan->channel;
+ s8 de_1st;
+ s8 de_2nd;
+ s8 val;
+
+ gidx = _tssi_get_ofdm_group(rtwdev, ch);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n", path, gidx);
+
+ if (IS_TSSI_EXTRA_GROUP(gidx)) {
+ gidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(gidx);
+ gidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(gidx);
+ de_1st = tssi_info->tssi_mcs[path][gidx_1st];
+ de_2nd = tssi_info->tssi_mcs[path][gidx_2nd];
+ val = (de_1st + de_2nd) / 2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
+ path, val, de_1st, de_2nd);
+ } else {
+ val = tssi_info->tssi_mcs[path][gidx];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
+ }
+
+ return val;
+}
+
+static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u32 tgidx, tgidx_1st, tgidx_2nd;
+ u8 ch = chan->channel;
+ s8 tde_1st;
+ s8 tde_2nd;
+ s8 val;
+
+ tgidx = _tssi_get_trim_group(rtwdev, ch);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
+ path, tgidx);
+
+ if (IS_TSSI_EXTRA_GROUP(tgidx)) {
+ tgidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
+ tgidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
+ tde_1st = tssi_info->tssi_trim[path][tgidx_1st];
+ tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd];
+ val = (tde_1st + tde_2nd) / 2;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
+ path, val, tde_1st, tde_2nd);
+ } else {
+ val = tssi_info->tssi_trim[path][tgidx];
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
+ path, val);
+ }
+
+ return val;
+}
+
+static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 ch = chan->channel;
+ u8 gidx;
+ s8 ofdm_de;
+ s8 trim_de;
+ s32 val;
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n",
+ phy, ch);
+
+ for (i = RF_PATH_A; i < RTW8851B_TSSI_PATH_NR; i++) {
+ gidx = _tssi_get_cck_group(rtwdev, ch);
+ trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i);
+ val = tssi_info->tssi_cck[i][gidx] + trim_de;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d cck[%d]=0x%x trim=0x%x\n",
+ i, gidx, tssi_info->tssi_cck[i][gidx], trim_de);
+
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_long[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_short[i], _TSSI_DE_MASK, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] Set TSSI CCK DE 0x%x[21:12]=0x%x\n",
+ _tssi_de_cck_long[i],
+ rtw89_phy_read32_mask(rtwdev, _tssi_de_cck_long[i],
+ _TSSI_DE_MASK));
+
+ ofdm_de = _tssi_get_ofdm_de(rtwdev, phy, i);
+ trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i);
+ val = ofdm_de + trim_de;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI][TRIM]: path=%d mcs=0x%x trim=0x%x\n",
+ i, ofdm_de, trim_de);
+
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_20m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_40m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m_80m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_5m[i], _TSSI_DE_MASK, val);
+ rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_10m[i], _TSSI_DE_MASK, val);
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+ "[TSSI] Set TSSI MCS DE 0x%x[21:12]=0x%x\n",
+ _tssi_de_mcs_20m[i],
+ rtw89_phy_read32_mask(rtwdev, _tssi_de_mcs_20m[i],
+ _TSSI_DE_MASK));
+ }
+}
+
+static void _tssi_alimentk_dump_result(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
+{
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[TSSI PA K]\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n"
+ "0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n",
+ R_TSSI_PA_K1 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K1 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K2 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K2 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM1 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM3 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K5 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K5 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM2 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD),
+ R_P0_TSSI_ALIM4 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD),
+ R_TSSI_PA_K8 + (path << 13),
+ rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K8 + (path << 13), MASKDWORD));
+}
+
+static void _tssi_alimentk_done(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, enum rtw89_rf_path path)
+{
+ struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+ u8 band;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s phy=%d path=%d\n", __func__, phy, path);
+
+ if (channel >= 1 && channel <= 14)
+ band = TSSI_ALIMK_2G;
+ else if (channel >= 36 && channel <= 64)
+ band = TSSI_ALIMK_5GL;
+ else if (channel >= 100 && channel <= 144)
+ band = TSSI_ALIMK_5GM;
+ else if (channel >= 149 && channel <= 177)
+ band = TSSI_ALIMK_5GH;
+ else
+ band = TSSI_ALIMK_2G;
+
+ if (tssi_info->alignment_done[path][band]) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][0]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][1]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][2]);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD,
+ tssi_info->alignment_value[path][band][3]);
+ }
+
+ _tssi_alimentk_dump_result(rtwdev, path);
+}
+
+static void rtw8851b_by_rate_dpd(struct rtw89_dev *rtwdev)
+{
+ rtw89_write32_mask(rtwdev, R_AX_PWR_SWING_OTHER_CTRL0,
+ B_AX_CFIR_BY_RATE_OFF_MASK, 0x21861);
+}
+
+void rtw8851b_dpk_init(struct rtw89_dev *rtwdev)
+{
+ rtw8851b_by_rate_dpd(rtwdev);
+}
+
+void rtw8851b_aack(struct rtw89_dev *rtwdev)
+{
+ u32 tmp05, tmpd3, ib[4];
+ u32 tmp;
+ int ret;
+ int rek;
+ int i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO AACK\n");
+
+ tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK);
+ tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_ST, 0x0);
+
+ for (rek = 0; rek < 4; rek++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201e);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201f);
+ fsleep(100);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp,
+ 1, 1000, false,
+ rtwdev, RF_PATH_A, 0xd0, BIT(16));
+ if (ret)
+ rtw89_warn(rtwdev, "[LCK]AACK timeout\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x1);
+ for (i = 0; i < 4; i++) {
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_SEL, i);
+ ib[i] = rtw89_read_rf(rtwdev, RF_PATH_A, RR_IBD, RR_IBD_VAL);
+ }
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x0);
+
+ if (ib[0] != 0 && ib[1] != 0 && ib[2] != 0 && ib[3] != 0)
+ break;
+ }
+
+ if (rek != 0)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]AACK rek = %d\n", rek);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3);
+}
+
+static void _lck_keep_thermal(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_lck_info *lck = &rtwdev->lck;
+
+ lck->thermal[RF_PATH_A] =
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[LCK] path=%d thermal=0x%x", RF_PATH_A, lck->thermal[RF_PATH_A]);
+}
+
+static void rtw8851b_lck(struct rtw89_dev *rtwdev)
+{
+ u32 tmp05, tmp18, tmpd3;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO LCK\n");
+
+ tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK);
+ tmp18 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ tmpd3 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+
+ _set_ch(rtwdev, tmp18);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RFREG_MASK, tmpd3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05);
+
+ _lck_keep_thermal(rtwdev);
+}
+
+#define RTW8851B_LCK_TH 8
+
+void rtw8851b_lck_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_lck_info *lck = &rtwdev->lck;
+ u8 cur_thermal;
+ int delta;
+
+ cur_thermal =
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[RF_PATH_A]);
+ delta = abs((int)cur_thermal - lck->thermal[RF_PATH_A]);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
+ "[LCK] path=%d current thermal=0x%x delta=0x%x\n",
+ RF_PATH_A, cur_thermal, delta);
+
+ if (delta >= RTW8851B_LCK_TH) {
+ rtw8851b_aack(rtwdev);
+ rtw8851b_lck(rtwdev);
+ }
+}
+
+void rtw8851b_lck_init(struct rtw89_dev *rtwdev)
+{
+ _lck_keep_thermal(rtwdev);
+}
+
+void rtw8851b_rck(struct rtw89_dev *rtwdev)
+{
+ _rck(rtwdev, RF_PATH_A);
+}
+
+void rtw8851b_dack(struct rtw89_dev *rtwdev)
+{
+ _dac_cal(rtwdev, false);
+}
+
+void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ _iqk_init(rtwdev);
+ _iqk(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ _rx_dck(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0);
+ u32 tx_en;
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START);
+ rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
+ _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx));
+
+ rtwdev->dpk.is_dpk_enable = true;
+ rtwdev->dpk.is_dpk_reload_en = false;
+ _dpk(rtwdev, phy_idx, false);
+
+ rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP);
+}
+
+void rtw8851b_dpk_track(struct rtw89_dev *rtwdev)
+{
+ _dpk_track(rtwdev);
+}
+
+void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en)
+{
+ u8 phy_map = rtw89_btc_phymap(rtwdev, phy, RF_A);
+ u8 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI] %s: phy=%d\n", __func__, phy);
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
+
+ _tssi_disable(rtwdev, phy);
+
+ for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) {
+ _tssi_set_sys(rtwdev, phy, i);
+ _tssi_ini_txpwr_ctrl_bb(rtwdev, phy, i);
+ _tssi_ini_txpwr_ctrl_bb_he_tb(rtwdev, phy, i);
+ _tssi_set_dck(rtwdev, phy, i);
+ _tssi_set_tmeter_tbl(rtwdev, phy, i);
+ _tssi_set_dac_gain_tbl(rtwdev, phy, i);
+ _tssi_slope_cal_org(rtwdev, phy, i);
+ _tssi_alignment_default(rtwdev, phy, i, true);
+ _tssi_set_tssi_slope(rtwdev, phy, i);
+ }
+
+ _tssi_enable(rtwdev, phy);
+ _tssi_set_efuse_to_de(rtwdev, phy);
+
+ rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP);
+}
+
+void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+ u32 i;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s phy=%d channel=%d\n", __func__, phy, channel);
+
+ _tssi_disable(rtwdev, phy);
+
+ for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) {
+ _tssi_set_sys(rtwdev, phy, i);
+ _tssi_set_tmeter_tbl(rtwdev, phy, i);
+ _tssi_slope_cal_org(rtwdev, phy, i);
+ _tssi_alignment_default(rtwdev, phy, i, true);
+ }
+
+ _tssi_enable(rtwdev, phy);
+ _tssi_set_efuse_to_de(rtwdev, phy);
+}
+
+static void rtw8851b_tssi_default_txagc(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, bool enable)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ u8 channel = chan->channel;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "======> %s ch=%d\n",
+ __func__, channel);
+
+ if (enable)
+ return;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s 1 SCAN_END Set 0x5818[7:0]=0x%x\n",
+ __func__,
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT));
+
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1);
+
+ _tssi_alimentk_done(rtwdev, phy, RF_PATH_A);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======>%s 2 SCAN_END Set 0x5818[7:0]=0x%x\n",
+ __func__,
+ rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT));
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "======> %s SCAN_END\n", __func__);
+}
+
+void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
+ enum rtw89_phy_idx phy_idx)
+{
+ if (scan_start)
+ rtw8851b_tssi_default_txagc(rtwdev, phy_idx, true);
+ else
+ rtw8851b_tssi_default_txagc(rtwdev, phy_idx, false);
+}
+
+static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ enum rtw89_bandwidth bw, bool dav)
+{
+ u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+ u32 rf_reg18;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+ rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+ if (rf_reg18 == INV_RF_DATA) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]Invalid RF_0x18 for Path-%d\n", path);
+ return;
+ }
+ rf_reg18 &= ~RR_CFGCH_BW;
+
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_5:
+ case RTW89_CHANNEL_WIDTH_10:
+ case RTW89_CHANNEL_WIDTH_20:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_20M);
+ break;
+ case RTW89_CHANNEL_WIDTH_40:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_40M);
+ break;
+ case RTW89_CHANNEL_WIDTH_80:
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_80M);
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]Fail to set CH\n");
+ }
+
+ rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+ RR_CFGCH_BW2) & RFREG_MASK;
+ rf_reg18 |= RR_CFGCH_BW2;
+ rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set %x at path%d, %x =0x%x\n",
+ bw, path, reg18_addr,
+ rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_bandwidth bw)
+{
+ _bw_setting(rtwdev, RF_PATH_A, bw, true);
+ _bw_setting(rtwdev, RF_PATH_A, bw, false);
+}
+
+static bool _set_s0_arfc18(struct rtw89_dev *rtwdev, u32 val)
+{
+ u32 bak;
+ u32 tmp;
+ int ret;
+
+ bak = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RR_LDO_SEL, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK, val);
+
+ ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp == 0, 1, 1000,
+ false, rtwdev, RF_PATH_A, RR_LPF, RR_LPF_BUSY);
+ if (ret)
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]LCK timeout\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK, bak);
+
+ return !!ret;
+}
+
+static void _lck_check(struct rtw89_dev *rtwdev)
+{
+ u32 tmp;
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN MMD reset\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x0);
+ }
+
+ udelay(10);
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]re-set RF 0x18\n");
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ _set_s0_arfc18(rtwdev, tmp);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+ }
+
+ if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN off/on\n");
+
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK, tmp);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK, tmp);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x0);
+
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+ tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+ _set_s0_arfc18(rtwdev, tmp);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]0xb2=%x, 0xc5=%x\n",
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_VCO, RFREG_MASK),
+ rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RFREG_MASK));
+ }
+}
+
+static void _set_ch(struct rtw89_dev *rtwdev, u32 val)
+{
+ bool timeout;
+
+ timeout = _set_s0_arfc18(rtwdev, val);
+ if (!timeout)
+ _lck_check(rtwdev);
+}
+
+static void _ch_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+ u8 central_ch, bool dav)
+{
+ u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+ bool is_2g_ch = central_ch <= 14;
+ u32 rf_reg18;
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+ rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+ rf_reg18 &= ~(RR_CFGCH_BAND1 | RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH |
+ RR_CFGCH_BCN | RR_CFGCH_BAND0 | RR_CFGCH_CH);
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_CH, central_ch);
+
+ if (!is_2g_ch)
+ rf_reg18 |= FIELD_PREP(RR_CFGCH_BAND1, CFGCH_BAND1_5G) |
+ FIELD_PREP(RR_CFGCH_BAND0, CFGCH_BAND0_5G);
+
+ rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+ RR_CFGCH_BW2) & RFREG_MASK;
+ rf_reg18 |= RR_CFGCH_BW2;
+
+ if (path == RF_PATH_A && dav)
+ _set_ch(rtwdev, rf_reg18);
+ else
+ rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+ rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 0);
+ rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 1);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK,
+ "[RFK]CH: %d for Path-%d, reg0x%x = 0x%x\n",
+ central_ch, path, reg18_addr,
+ rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch)
+{
+ _ch_setting(rtwdev, RF_PATH_A, central_ch, true);
+ _ch_setting(rtwdev, RF_PATH_A, central_ch, false);
+}
+
+static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_bandwidth bw,
+ enum rtw89_rf_path path)
+{
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1);
+ rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0x12);
+
+ if (bw == RTW89_CHANNEL_WIDTH_20)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x1b);
+ else if (bw == RTW89_CHANNEL_WIDTH_40)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x13);
+ else if (bw == RTW89_CHANNEL_WIDTH_80)
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0xb);
+ else
+ rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x3);
+
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set S%d RXBB BW 0x3F = 0x%x\n", path,
+ rtw89_read_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB));
+
+ rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0);
+}
+
+static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+ enum rtw89_bandwidth bw)
+{
+ u8 kpath, path;
+
+ kpath = _kpath(rtwdev, phy);
+
+ for (path = 0; path < RF_PATH_NUM_8851B; path++) {
+ if (!(kpath & BIT(path)))
+ continue;
+
+ _set_rxbb_bw(rtwdev, bw, path);
+ }
+}
+
+static void rtw8851b_ctrl_bw_ch(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy, u8 central_ch,
+ enum rtw89_band band, enum rtw89_bandwidth bw)
+{
+ _ctrl_ch(rtwdev, central_ch);
+ _ctrl_bw(rtwdev, phy, bw);
+ _rxbb_bw(rtwdev, phy, bw);
+}
+
+void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ rtw8851b_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type,
+ chan->band_width);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h
new file mode 100644
index 000000000000..b66a23d6d367
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#ifndef __RTW89_8851B_RFK_H__
+#define __RTW89_8851B_RFK_H__
+
+#include "core.h"
+
+void rtw8851b_aack(struct rtw89_dev *rtwdev);
+void rtw8851b_lck_init(struct rtw89_dev *rtwdev);
+void rtw8851b_lck_track(struct rtw89_dev *rtwdev);
+void rtw8851b_rck(struct rtw89_dev *rtwdev);
+void rtw8851b_dack(struct rtw89_dev *rtwdev);
+void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
+void rtw8851b_dpk_init(struct rtw89_dev *rtwdev);
+void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
+void rtw8851b_dpk_track(struct rtw89_dev *rtwdev);
+void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en);
+void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
+void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
+ enum rtw89_phy_idx phy_idx);
+void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx);
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
index bb724140df4f..c447f91a4bd0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
@@ -1273,6 +1273,25 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0xF0010000, 0x00000000},
{0xF0020000, 0x00000001},
{0xF0030000, 0x00000002},
+ {0xF0010001, 0x00000003},
+ {0xF0020001, 0x00000004},
+ {0xF0030001, 0x00000005},
+ {0xF0040001, 0x00000006},
+ {0xF0050001, 0x00000007},
+ {0xF0060001, 0x00000008},
+ {0x000, 0x00000000},
+ {0x0EF, 0x00080000},
+ {0x033, 0x00000003},
+ {0x03E, 0x00000150},
+ {0x03F, 0x0000D79C},
+ {0x0EF, 0x00000000},
+ {0x052, 0x000C3338},
+ {0x053, 0x000608AF},
+ {0x054, 0x00006C04},
+ {0x063, 0x000FC082},
+ {0x065, 0x00018122},
+ {0x000, 0x00010000},
+ {0x0FE, 0x0000005A},
{0x000, 0x00030000},
{0x018, 0x00013124},
{0x0EF, 0x00080000},
@@ -1834,8 +1853,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x059, 0x00050033},
{0x061, 0x0005F48A},
{0x062, 0x00077435},
- {0x063, 0x000F80A2},
- {0x065, 0x00018F22},
{0x067, 0x00008060},
{0x07E, 0x0009780B},
{0x0EE, 0x00000004},
@@ -2074,9 +2091,6 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x03F, 0x0001C3C3},
{0x0EF, 0x00000000},
{0x051, 0x0003D368},
- {0x052, 0x000A3338},
- {0x053, 0x000688AF},
- {0x054, 0x00012C04},
{0x058, 0x00084221},
{0x05B, 0x000EB000},
{0x100EE, 0x00002000},
@@ -2229,9 +2243,11 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_radioa_regs[] = {
{0x033, 0x00000000},
{0x03F, 0x00000004},
{0x0EF, 0x00000000},
+ {0x000, 0x00010000},
+ {0x0FE, 0x0000005A},
{0x005, 0x00000001},
{0x10005, 0x00000001},
- {0x0FE, 0x00000022},
+ {0x0FE, 0x00000028},
};
static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = {
@@ -2306,7 +2322,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = {
{0x8144, 0x0b040b03},
{0x8148, 0x07020b04},
{0x814c, 0x07020b04},
- {0x8150, 0xe4e40000},
+ {0x8150, 0xa0a00000},
{0x8158, 0xffffffff},
{0x815c, 0xffffffff},
{0x8160, 0xffffffff},
@@ -3305,7 +3321,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4
};
-const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
[0][0][RTW89_CN] = 0,
@@ -3326,8 +3342,8 @@ const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
[1][1][RTW89_ACMA] = 0,
[1][1][RTW89_CN] = 0,
[1][1][RTW89_ETSI] = 0,
- [1][1][RTW89_FCC] = 3,
- [1][1][RTW89_IC] = 3,
+ [1][1][RTW89_FCC] = 1,
+ [1][1][RTW89_IC] = 1,
[1][1][RTW89_KCC] = 0,
[1][1][RTW89_MKK] = 0,
[1][1][RTW89_UK] = 0,
@@ -4880,9 +4896,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][42] = 30,
[0][0][1][0][RTW89_WW][44] = 30,
[0][0][1][0][RTW89_WW][46] = 30,
- [0][0][1][0][RTW89_WW][48] = 72,
- [0][0][1][0][RTW89_WW][50] = 72,
- [0][0][1][0][RTW89_WW][52] = 72,
+ [0][0][1][0][RTW89_WW][48] = 68,
+ [0][0][1][0][RTW89_WW][50] = 68,
+ [0][0][1][0][RTW89_WW][52] = 68,
[0][1][1][0][RTW89_WW][0] = 0,
[0][1][1][0][RTW89_WW][2] = 0,
[0][1][1][0][RTW89_WW][4] = 0,
@@ -4936,9 +4952,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][42] = 30,
[0][0][2][0][RTW89_WW][44] = 30,
[0][0][2][0][RTW89_WW][46] = 30,
- [0][0][2][0][RTW89_WW][48] = 74,
- [0][0][2][0][RTW89_WW][50] = 76,
- [0][0][2][0][RTW89_WW][52] = 76,
+ [0][0][2][0][RTW89_WW][48] = 70,
+ [0][0][2][0][RTW89_WW][50] = 72,
+ [0][0][2][0][RTW89_WW][52] = 72,
[0][1][2][0][RTW89_WW][0] = 0,
[0][1][2][0][RTW89_WW][2] = 0,
[0][1][2][0][RTW89_WW][4] = 0,
@@ -4995,11 +5011,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_WW][48] = 0,
[0][1][2][1][RTW89_WW][50] = 0,
[0][1][2][1][RTW89_WW][52] = 0,
- [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][1] = 60,
[1][0][2][0][RTW89_WW][5] = 62,
[1][0][2][0][RTW89_WW][9] = 64,
- [1][0][2][0][RTW89_WW][13] = 64,
- [1][0][2][0][RTW89_WW][16] = 66,
+ [1][0][2][0][RTW89_WW][13] = 60,
+ [1][0][2][0][RTW89_WW][16] = 62,
[1][0][2][0][RTW89_WW][20] = 66,
[1][0][2][0][RTW89_WW][24] = 66,
[1][0][2][0][RTW89_WW][28] = 66,
@@ -5007,8 +5023,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][36] = 76,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
- [1][0][2][0][RTW89_WW][47] = 84,
- [1][0][2][0][RTW89_WW][51] = 84,
+ [1][0][2][0][RTW89_WW][47] = 80,
+ [1][0][2][0][RTW89_WW][51] = 80,
[1][1][2][0][RTW89_WW][1] = 0,
[1][1][2][0][RTW89_WW][5] = 0,
[1][1][2][0][RTW89_WW][9] = 0,
@@ -5037,13 +5053,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][43] = 0,
[1][1][2][1][RTW89_WW][47] = 0,
[1][1][2][1][RTW89_WW][51] = 0,
- [2][0][2][0][RTW89_WW][3] = 62,
- [2][0][2][0][RTW89_WW][11] = 62,
- [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][3] = 60,
+ [2][0][2][0][RTW89_WW][11] = 58,
+ [2][0][2][0][RTW89_WW][18] = 62,
[2][0][2][0][RTW89_WW][26] = 64,
[2][0][2][0][RTW89_WW][34] = 72,
[2][0][2][0][RTW89_WW][41] = 30,
- [2][0][2][0][RTW89_WW][49] = 74,
+ [2][0][2][0][RTW89_WW][49] = 70,
[2][1][2][0][RTW89_WW][3] = 0,
[2][1][2][0][RTW89_WW][11] = 0,
[2][1][2][0][RTW89_WW][18] = 0,
@@ -5067,7 +5083,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_WW][7] = 0,
[3][1][2][1][RTW89_WW][22] = 0,
[3][1][2][1][RTW89_WW][45] = 0,
- [0][0][1][0][RTW89_FCC][0] = 80,
+ [0][0][1][0][RTW89_FCC][0] = 76,
[0][0][1][0][RTW89_ETSI][0] = 58,
[0][0][1][0][RTW89_MKK][0] = 60,
[0][0][1][0][RTW89_IC][0] = 62,
@@ -5123,7 +5139,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 58,
[0][0][1][0][RTW89_CN][12] = 60,
[0][0][1][0][RTW89_UK][12] = 58,
- [0][0][1][0][RTW89_FCC][14] = 78,
+ [0][0][1][0][RTW89_FCC][14] = 74,
[0][0][1][0][RTW89_ETSI][14] = 58,
[0][0][1][0][RTW89_MKK][14] = 60,
[0][0][1][0][RTW89_IC][14] = 64,
@@ -5131,10 +5147,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 58,
[0][0][1][0][RTW89_CN][14] = 60,
[0][0][1][0][RTW89_UK][14] = 58,
- [0][0][1][0][RTW89_FCC][15] = 78,
+ [0][0][1][0][RTW89_FCC][15] = 74,
[0][0][1][0][RTW89_ETSI][15] = 58,
[0][0][1][0][RTW89_MKK][15] = 78,
- [0][0][1][0][RTW89_IC][15] = 78,
+ [0][0][1][0][RTW89_IC][15] = 74,
[0][0][1][0][RTW89_KCC][15] = 78,
[0][0][1][0][RTW89_ACMA][15] = 58,
[0][0][1][0][RTW89_CN][15] = 127,
@@ -5211,10 +5227,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 60,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 60,
- [0][0][1][0][RTW89_FCC][35] = 72,
+ [0][0][1][0][RTW89_FCC][35] = 68,
[0][0][1][0][RTW89_ETSI][35] = 60,
[0][0][1][0][RTW89_MKK][35] = 78,
- [0][0][1][0][RTW89_IC][35] = 72,
+ [0][0][1][0][RTW89_IC][35] = 68,
[0][0][1][0][RTW89_KCC][35] = 74,
[0][0][1][0][RTW89_ACMA][35] = 60,
[0][0][1][0][RTW89_CN][35] = 127,
@@ -5267,7 +5283,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 78,
[0][0][1][0][RTW89_CN][46] = 78,
[0][0][1][0][RTW89_UK][46] = 58,
- [0][0][1][0][RTW89_FCC][48] = 72,
+ [0][0][1][0][RTW89_FCC][48] = 68,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
[0][0][1][0][RTW89_IC][48] = 127,
@@ -5275,7 +5291,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
- [0][0][1][0][RTW89_FCC][50] = 72,
+ [0][0][1][0][RTW89_FCC][50] = 68,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
[0][0][1][0][RTW89_IC][50] = 127,
@@ -5283,7 +5299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
- [0][0][1][0][RTW89_FCC][52] = 72,
+ [0][0][1][0][RTW89_FCC][52] = 68,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
[0][0][1][0][RTW89_IC][52] = 127,
@@ -5515,7 +5531,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
- [0][0][2][0][RTW89_FCC][0] = 78,
+ [0][0][2][0][RTW89_FCC][0] = 74,
[0][0][2][0][RTW89_ETSI][0] = 62,
[0][0][2][0][RTW89_MKK][0] = 62,
[0][0][2][0][RTW89_IC][0] = 64,
@@ -5571,7 +5587,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 62,
[0][0][2][0][RTW89_CN][12] = 62,
[0][0][2][0][RTW89_UK][12] = 62,
- [0][0][2][0][RTW89_FCC][14] = 76,
+ [0][0][2][0][RTW89_FCC][14] = 72,
[0][0][2][0][RTW89_ETSI][14] = 62,
[0][0][2][0][RTW89_MKK][14] = 62,
[0][0][2][0][RTW89_IC][14] = 64,
@@ -5579,10 +5595,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 62,
[0][0][2][0][RTW89_CN][14] = 62,
[0][0][2][0][RTW89_UK][14] = 62,
- [0][0][2][0][RTW89_FCC][15] = 76,
+ [0][0][2][0][RTW89_FCC][15] = 72,
[0][0][2][0][RTW89_ETSI][15] = 60,
[0][0][2][0][RTW89_MKK][15] = 78,
- [0][0][2][0][RTW89_IC][15] = 76,
+ [0][0][2][0][RTW89_IC][15] = 72,
[0][0][2][0][RTW89_KCC][15] = 78,
[0][0][2][0][RTW89_ACMA][15] = 60,
[0][0][2][0][RTW89_CN][15] = 127,
@@ -5659,10 +5675,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 62,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 62,
- [0][0][2][0][RTW89_FCC][35] = 72,
+ [0][0][2][0][RTW89_FCC][35] = 68,
[0][0][2][0][RTW89_ETSI][35] = 62,
[0][0][2][0][RTW89_MKK][35] = 78,
- [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_IC][35] = 68,
[0][0][2][0][RTW89_KCC][35] = 74,
[0][0][2][0][RTW89_ACMA][35] = 62,
[0][0][2][0][RTW89_CN][35] = 127,
@@ -5715,7 +5731,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 78,
[0][0][2][0][RTW89_CN][46] = 78,
[0][0][2][0][RTW89_UK][46] = 60,
- [0][0][2][0][RTW89_FCC][48] = 74,
+ [0][0][2][0][RTW89_FCC][48] = 70,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
[0][0][2][0][RTW89_IC][48] = 127,
@@ -5723,7 +5739,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
- [0][0][2][0][RTW89_FCC][50] = 76,
+ [0][0][2][0][RTW89_FCC][50] = 72,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
[0][0][2][0][RTW89_IC][50] = 127,
@@ -5731,7 +5747,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
- [0][0][2][0][RTW89_FCC][52] = 76,
+ [0][0][2][0][RTW89_FCC][52] = 72,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
[0][0][2][0][RTW89_IC][52] = 127,
@@ -6187,10 +6203,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
- [1][0][2][0][RTW89_FCC][1] = 68,
+ [1][0][2][0][RTW89_FCC][1] = 64,
[1][0][2][0][RTW89_ETSI][1] = 64,
[1][0][2][0][RTW89_MKK][1] = 64,
- [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 60,
[1][0][2][0][RTW89_KCC][1] = 74,
[1][0][2][0][RTW89_ACMA][1] = 64,
[1][0][2][0][RTW89_CN][1] = 64,
@@ -6211,18 +6227,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 64,
[1][0][2][0][RTW89_CN][9] = 64,
[1][0][2][0][RTW89_UK][9] = 64,
- [1][0][2][0][RTW89_FCC][13] = 66,
+ [1][0][2][0][RTW89_FCC][13] = 62,
[1][0][2][0][RTW89_ETSI][13] = 64,
[1][0][2][0][RTW89_MKK][13] = 64,
- [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 60,
[1][0][2][0][RTW89_KCC][13] = 72,
[1][0][2][0][RTW89_ACMA][13] = 64,
[1][0][2][0][RTW89_CN][13] = 64,
[1][0][2][0][RTW89_UK][13] = 64,
- [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_FCC][16] = 62,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 80,
- [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_IC][16] = 62,
[1][0][2][0][RTW89_KCC][16] = 74,
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
@@ -6230,7 +6246,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][20] = 80,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 80,
- [1][0][2][0][RTW89_IC][20] = 80,
+ [1][0][2][0][RTW89_IC][20] = 76,
[1][0][2][0][RTW89_KCC][20] = 74,
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
@@ -6251,10 +6267,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
- [1][0][2][0][RTW89_FCC][32] = 76,
+ [1][0][2][0][RTW89_FCC][32] = 72,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 80,
- [1][0][2][0][RTW89_IC][32] = 76,
+ [1][0][2][0][RTW89_IC][32] = 72,
[1][0][2][0][RTW89_KCC][32] = 78,
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
@@ -6270,7 +6286,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][39] = 84,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
- [1][0][2][0][RTW89_IC][39] = 84,
+ [1][0][2][0][RTW89_IC][39] = 80,
[1][0][2][0][RTW89_KCC][39] = 68,
[1][0][2][0][RTW89_ACMA][39] = 80,
[1][0][2][0][RTW89_CN][39] = 70,
@@ -6283,7 +6299,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 80,
[1][0][2][0][RTW89_CN][43] = 80,
[1][0][2][0][RTW89_UK][43] = 64,
- [1][0][2][0][RTW89_FCC][47] = 84,
+ [1][0][2][0][RTW89_FCC][47] = 80,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
[1][0][2][0][RTW89_IC][47] = 127,
@@ -6291,7 +6307,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
- [1][0][2][0][RTW89_FCC][51] = 84,
+ [1][0][2][0][RTW89_FCC][51] = 80,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
[1][0][2][0][RTW89_IC][51] = 127,
@@ -6523,26 +6539,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
- [2][0][2][0][RTW89_FCC][3] = 76,
+ [2][0][2][0][RTW89_FCC][3] = 72,
[2][0][2][0][RTW89_ETSI][3] = 64,
[2][0][2][0][RTW89_MKK][3] = 62,
- [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_IC][3] = 60,
[2][0][2][0][RTW89_KCC][3] = 72,
[2][0][2][0][RTW89_ACMA][3] = 64,
[2][0][2][0][RTW89_CN][3] = 64,
[2][0][2][0][RTW89_UK][3] = 64,
- [2][0][2][0][RTW89_FCC][11] = 64,
+ [2][0][2][0][RTW89_FCC][11] = 60,
[2][0][2][0][RTW89_ETSI][11] = 64,
[2][0][2][0][RTW89_MKK][11] = 64,
- [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_IC][11] = 58,
[2][0][2][0][RTW89_KCC][11] = 72,
[2][0][2][0][RTW89_ACMA][11] = 64,
[2][0][2][0][RTW89_CN][11] = 64,
[2][0][2][0][RTW89_UK][11] = 64,
- [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_FCC][18] = 62,
[2][0][2][0][RTW89_ETSI][18] = 64,
[2][0][2][0][RTW89_MKK][18] = 72,
- [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_IC][18] = 62,
[2][0][2][0][RTW89_KCC][18] = 72,
[2][0][2][0][RTW89_ACMA][18] = 64,
[2][0][2][0][RTW89_CN][18] = 127,
@@ -6558,7 +6574,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][34] = 76,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 72,
- [2][0][2][0][RTW89_IC][34] = 76,
+ [2][0][2][0][RTW89_IC][34] = 72,
[2][0][2][0][RTW89_KCC][34] = 72,
[2][0][2][0][RTW89_ACMA][34] = 72,
[2][0][2][0][RTW89_CN][34] = 127,
@@ -6566,12 +6582,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][41] = 76,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
- [2][0][2][0][RTW89_IC][41] = 76,
+ [2][0][2][0][RTW89_IC][41] = 72,
[2][0][2][0][RTW89_KCC][41] = 64,
[2][0][2][0][RTW89_ACMA][41] = 72,
[2][0][2][0][RTW89_CN][41] = 72,
[2][0][2][0][RTW89_UK][41] = 64,
- [2][0][2][0][RTW89_FCC][49] = 74,
+ [2][0][2][0][RTW89_FCC][49] = 70,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
[2][0][2][0][RTW89_IC][49] = 127,
@@ -10590,9 +10606,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][42] = 30,
[0][0][1][0][RTW89_WW][44] = 30,
[0][0][1][0][RTW89_WW][46] = 30,
- [0][0][1][0][RTW89_WW][48] = 72,
- [0][0][1][0][RTW89_WW][50] = 72,
- [0][0][1][0][RTW89_WW][52] = 72,
+ [0][0][1][0][RTW89_WW][48] = 68,
+ [0][0][1][0][RTW89_WW][50] = 68,
+ [0][0][1][0][RTW89_WW][52] = 68,
[0][1][1][0][RTW89_WW][0] = 0,
[0][1][1][0][RTW89_WW][2] = 0,
[0][1][1][0][RTW89_WW][4] = 0,
@@ -10646,9 +10662,9 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][42] = 30,
[0][0][2][0][RTW89_WW][44] = 30,
[0][0][2][0][RTW89_WW][46] = 30,
- [0][0][2][0][RTW89_WW][48] = 74,
- [0][0][2][0][RTW89_WW][50] = 74,
- [0][0][2][0][RTW89_WW][52] = 74,
+ [0][0][2][0][RTW89_WW][48] = 70,
+ [0][0][2][0][RTW89_WW][50] = 70,
+ [0][0][2][0][RTW89_WW][52] = 70,
[0][1][2][0][RTW89_WW][0] = 0,
[0][1][2][0][RTW89_WW][2] = 0,
[0][1][2][0][RTW89_WW][4] = 0,
@@ -10705,11 +10721,11 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_WW][48] = 0,
[0][1][2][1][RTW89_WW][50] = 0,
[0][1][2][1][RTW89_WW][52] = 0,
- [1][0][2][0][RTW89_WW][1] = 64,
+ [1][0][2][0][RTW89_WW][1] = 60,
[1][0][2][0][RTW89_WW][5] = 62,
[1][0][2][0][RTW89_WW][9] = 64,
- [1][0][2][0][RTW89_WW][13] = 64,
- [1][0][2][0][RTW89_WW][16] = 66,
+ [1][0][2][0][RTW89_WW][13] = 60,
+ [1][0][2][0][RTW89_WW][16] = 62,
[1][0][2][0][RTW89_WW][20] = 66,
[1][0][2][0][RTW89_WW][24] = 66,
[1][0][2][0][RTW89_WW][28] = 66,
@@ -10717,8 +10733,8 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][36] = 76,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
- [1][0][2][0][RTW89_WW][47] = 80,
- [1][0][2][0][RTW89_WW][51] = 80,
+ [1][0][2][0][RTW89_WW][47] = 76,
+ [1][0][2][0][RTW89_WW][51] = 76,
[1][1][2][0][RTW89_WW][1] = 0,
[1][1][2][0][RTW89_WW][5] = 0,
[1][1][2][0][RTW89_WW][9] = 0,
@@ -10747,13 +10763,13 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][43] = 0,
[1][1][2][1][RTW89_WW][47] = 0,
[1][1][2][1][RTW89_WW][51] = 0,
- [2][0][2][0][RTW89_WW][3] = 62,
- [2][0][2][0][RTW89_WW][11] = 62,
- [2][0][2][0][RTW89_WW][18] = 64,
+ [2][0][2][0][RTW89_WW][3] = 60,
+ [2][0][2][0][RTW89_WW][11] = 58,
+ [2][0][2][0][RTW89_WW][18] = 62,
[2][0][2][0][RTW89_WW][26] = 64,
[2][0][2][0][RTW89_WW][34] = 68,
[2][0][2][0][RTW89_WW][41] = 30,
- [2][0][2][0][RTW89_WW][49] = 72,
+ [2][0][2][0][RTW89_WW][49] = 68,
[2][1][2][0][RTW89_WW][3] = 0,
[2][1][2][0][RTW89_WW][11] = 0,
[2][1][2][0][RTW89_WW][18] = 0,
@@ -10777,7 +10793,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_WW][7] = 0,
[3][1][2][1][RTW89_WW][22] = 0,
[3][1][2][1][RTW89_WW][45] = 0,
- [0][0][1][0][RTW89_FCC][0] = 78,
+ [0][0][1][0][RTW89_FCC][0] = 74,
[0][0][1][0][RTW89_ETSI][0] = 58,
[0][0][1][0][RTW89_MKK][0] = 60,
[0][0][1][0][RTW89_IC][0] = 62,
@@ -10833,7 +10849,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 58,
[0][0][1][0][RTW89_CN][12] = 60,
[0][0][1][0][RTW89_UK][12] = 58,
- [0][0][1][0][RTW89_FCC][14] = 76,
+ [0][0][1][0][RTW89_FCC][14] = 72,
[0][0][1][0][RTW89_ETSI][14] = 58,
[0][0][1][0][RTW89_MKK][14] = 60,
[0][0][1][0][RTW89_IC][14] = 62,
@@ -10841,10 +10857,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 58,
[0][0][1][0][RTW89_CN][14] = 60,
[0][0][1][0][RTW89_UK][14] = 58,
- [0][0][1][0][RTW89_FCC][15] = 76,
+ [0][0][1][0][RTW89_FCC][15] = 72,
[0][0][1][0][RTW89_ETSI][15] = 58,
[0][0][1][0][RTW89_MKK][15] = 74,
- [0][0][1][0][RTW89_IC][15] = 76,
+ [0][0][1][0][RTW89_IC][15] = 72,
[0][0][1][0][RTW89_KCC][15] = 74,
[0][0][1][0][RTW89_ACMA][15] = 58,
[0][0][1][0][RTW89_CN][15] = 127,
@@ -10921,10 +10937,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 60,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 60,
- [0][0][1][0][RTW89_FCC][35] = 70,
+ [0][0][1][0][RTW89_FCC][35] = 66,
[0][0][1][0][RTW89_ETSI][35] = 60,
[0][0][1][0][RTW89_MKK][35] = 74,
- [0][0][1][0][RTW89_IC][35] = 70,
+ [0][0][1][0][RTW89_IC][35] = 66,
[0][0][1][0][RTW89_KCC][35] = 74,
[0][0][1][0][RTW89_ACMA][35] = 60,
[0][0][1][0][RTW89_CN][35] = 127,
@@ -10977,7 +10993,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 74,
[0][0][1][0][RTW89_CN][46] = 74,
[0][0][1][0][RTW89_UK][46] = 58,
- [0][0][1][0][RTW89_FCC][48] = 72,
+ [0][0][1][0][RTW89_FCC][48] = 68,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
[0][0][1][0][RTW89_IC][48] = 127,
@@ -10985,7 +11001,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
- [0][0][1][0][RTW89_FCC][50] = 72,
+ [0][0][1][0][RTW89_FCC][50] = 68,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
[0][0][1][0][RTW89_IC][50] = 127,
@@ -10993,7 +11009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
- [0][0][1][0][RTW89_FCC][52] = 72,
+ [0][0][1][0][RTW89_FCC][52] = 68,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
[0][0][1][0][RTW89_IC][52] = 127,
@@ -11225,7 +11241,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
- [0][0][2][0][RTW89_FCC][0] = 76,
+ [0][0][2][0][RTW89_FCC][0] = 72,
[0][0][2][0][RTW89_ETSI][0] = 62,
[0][0][2][0][RTW89_MKK][0] = 62,
[0][0][2][0][RTW89_IC][0] = 64,
@@ -11281,7 +11297,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 62,
[0][0][2][0][RTW89_CN][12] = 62,
[0][0][2][0][RTW89_UK][12] = 62,
- [0][0][2][0][RTW89_FCC][14] = 74,
+ [0][0][2][0][RTW89_FCC][14] = 70,
[0][0][2][0][RTW89_ETSI][14] = 62,
[0][0][2][0][RTW89_MKK][14] = 62,
[0][0][2][0][RTW89_IC][14] = 64,
@@ -11289,10 +11305,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 62,
[0][0][2][0][RTW89_CN][14] = 62,
[0][0][2][0][RTW89_UK][14] = 62,
- [0][0][2][0][RTW89_FCC][15] = 74,
+ [0][0][2][0][RTW89_FCC][15] = 70,
[0][0][2][0][RTW89_ETSI][15] = 60,
[0][0][2][0][RTW89_MKK][15] = 74,
- [0][0][2][0][RTW89_IC][15] = 74,
+ [0][0][2][0][RTW89_IC][15] = 70,
[0][0][2][0][RTW89_KCC][15] = 74,
[0][0][2][0][RTW89_ACMA][15] = 60,
[0][0][2][0][RTW89_CN][15] = 127,
@@ -11369,10 +11385,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 62,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 62,
- [0][0][2][0][RTW89_FCC][35] = 72,
+ [0][0][2][0][RTW89_FCC][35] = 68,
[0][0][2][0][RTW89_ETSI][35] = 62,
[0][0][2][0][RTW89_MKK][35] = 74,
- [0][0][2][0][RTW89_IC][35] = 72,
+ [0][0][2][0][RTW89_IC][35] = 68,
[0][0][2][0][RTW89_KCC][35] = 74,
[0][0][2][0][RTW89_ACMA][35] = 62,
[0][0][2][0][RTW89_CN][35] = 127,
@@ -11425,7 +11441,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 74,
[0][0][2][0][RTW89_CN][46] = 74,
[0][0][2][0][RTW89_UK][46] = 60,
- [0][0][2][0][RTW89_FCC][48] = 74,
+ [0][0][2][0][RTW89_FCC][48] = 70,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
[0][0][2][0][RTW89_IC][48] = 127,
@@ -11433,7 +11449,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
- [0][0][2][0][RTW89_FCC][50] = 74,
+ [0][0][2][0][RTW89_FCC][50] = 70,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
[0][0][2][0][RTW89_IC][50] = 127,
@@ -11441,7 +11457,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
- [0][0][2][0][RTW89_FCC][52] = 74,
+ [0][0][2][0][RTW89_FCC][52] = 70,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
[0][0][2][0][RTW89_IC][52] = 127,
@@ -11897,10 +11913,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
- [1][0][2][0][RTW89_FCC][1] = 66,
+ [1][0][2][0][RTW89_FCC][1] = 62,
[1][0][2][0][RTW89_ETSI][1] = 64,
[1][0][2][0][RTW89_MKK][1] = 64,
- [1][0][2][0][RTW89_IC][1] = 64,
+ [1][0][2][0][RTW89_IC][1] = 60,
[1][0][2][0][RTW89_KCC][1] = 74,
[1][0][2][0][RTW89_ACMA][1] = 64,
[1][0][2][0][RTW89_CN][1] = 64,
@@ -11921,18 +11937,18 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 64,
[1][0][2][0][RTW89_CN][9] = 64,
[1][0][2][0][RTW89_UK][9] = 64,
- [1][0][2][0][RTW89_FCC][13] = 64,
+ [1][0][2][0][RTW89_FCC][13] = 60,
[1][0][2][0][RTW89_ETSI][13] = 64,
[1][0][2][0][RTW89_MKK][13] = 64,
- [1][0][2][0][RTW89_IC][13] = 64,
+ [1][0][2][0][RTW89_IC][13] = 60,
[1][0][2][0][RTW89_KCC][13] = 72,
[1][0][2][0][RTW89_ACMA][13] = 64,
[1][0][2][0][RTW89_CN][13] = 64,
[1][0][2][0][RTW89_UK][13] = 64,
- [1][0][2][0][RTW89_FCC][16] = 66,
+ [1][0][2][0][RTW89_FCC][16] = 62,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 76,
- [1][0][2][0][RTW89_IC][16] = 66,
+ [1][0][2][0][RTW89_IC][16] = 62,
[1][0][2][0][RTW89_KCC][16] = 74,
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
@@ -11940,7 +11956,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][20] = 80,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 76,
- [1][0][2][0][RTW89_IC][20] = 80,
+ [1][0][2][0][RTW89_IC][20] = 76,
[1][0][2][0][RTW89_KCC][20] = 74,
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
@@ -11961,10 +11977,10 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
- [1][0][2][0][RTW89_FCC][32] = 74,
+ [1][0][2][0][RTW89_FCC][32] = 70,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 76,
- [1][0][2][0][RTW89_IC][32] = 74,
+ [1][0][2][0][RTW89_IC][32] = 70,
[1][0][2][0][RTW89_KCC][32] = 76,
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
@@ -11980,7 +11996,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_FCC][39] = 80,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
- [1][0][2][0][RTW89_IC][39] = 80,
+ [1][0][2][0][RTW89_IC][39] = 76,
[1][0][2][0][RTW89_KCC][39] = 68,
[1][0][2][0][RTW89_ACMA][39] = 76,
[1][0][2][0][RTW89_CN][39] = 70,
@@ -11993,7 +12009,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 76,
[1][0][2][0][RTW89_CN][43] = 76,
[1][0][2][0][RTW89_UK][43] = 64,
- [1][0][2][0][RTW89_FCC][47] = 80,
+ [1][0][2][0][RTW89_FCC][47] = 76,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
[1][0][2][0][RTW89_IC][47] = 127,
@@ -12001,7 +12017,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
- [1][0][2][0][RTW89_FCC][51] = 80,
+ [1][0][2][0][RTW89_FCC][51] = 76,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
[1][0][2][0][RTW89_IC][51] = 127,
@@ -12233,26 +12249,26 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
- [2][0][2][0][RTW89_FCC][3] = 72,
+ [2][0][2][0][RTW89_FCC][3] = 68,
[2][0][2][0][RTW89_ETSI][3] = 64,
[2][0][2][0][RTW89_MKK][3] = 62,
- [2][0][2][0][RTW89_IC][3] = 64,
+ [2][0][2][0][RTW89_IC][3] = 60,
[2][0][2][0][RTW89_KCC][3] = 68,
[2][0][2][0][RTW89_ACMA][3] = 64,
[2][0][2][0][RTW89_CN][3] = 64,
[2][0][2][0][RTW89_UK][3] = 64,
- [2][0][2][0][RTW89_FCC][11] = 62,
+ [2][0][2][0][RTW89_FCC][11] = 58,
[2][0][2][0][RTW89_ETSI][11] = 64,
[2][0][2][0][RTW89_MKK][11] = 64,
- [2][0][2][0][RTW89_IC][11] = 62,
+ [2][0][2][0][RTW89_IC][11] = 58,
[2][0][2][0][RTW89_KCC][11] = 68,
[2][0][2][0][RTW89_ACMA][11] = 64,
[2][0][2][0][RTW89_CN][11] = 64,
[2][0][2][0][RTW89_UK][11] = 64,
- [2][0][2][0][RTW89_FCC][18] = 66,
+ [2][0][2][0][RTW89_FCC][18] = 62,
[2][0][2][0][RTW89_ETSI][18] = 64,
[2][0][2][0][RTW89_MKK][18] = 68,
- [2][0][2][0][RTW89_IC][18] = 66,
+ [2][0][2][0][RTW89_IC][18] = 62,
[2][0][2][0][RTW89_KCC][18] = 68,
[2][0][2][0][RTW89_ACMA][18] = 64,
[2][0][2][0][RTW89_CN][18] = 127,
@@ -12268,7 +12284,7 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][34] = 72,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 68,
- [2][0][2][0][RTW89_IC][34] = 72,
+ [2][0][2][0][RTW89_IC][34] = 68,
[2][0][2][0][RTW89_KCC][34] = 68,
[2][0][2][0][RTW89_ACMA][34] = 68,
[2][0][2][0][RTW89_CN][34] = 127,
@@ -12276,12 +12292,12 @@ const s8 rtw89_8851b_txpwr_lmt_5g_type2[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_FCC][41] = 72,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
- [2][0][2][0][RTW89_IC][41] = 72,
+ [2][0][2][0][RTW89_IC][41] = 68,
[2][0][2][0][RTW89_KCC][41] = 64,
[2][0][2][0][RTW89_ACMA][41] = 68,
[2][0][2][0][RTW89_CN][41] = 68,
[2][0][2][0][RTW89_UK][41] = 64,
- [2][0][2][0][RTW89_FCC][49] = 72,
+ [2][0][2][0][RTW89_FCC][49] = 68,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
[2][0][2][0][RTW89_IC][49] = 127,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
index f2e673ba39c8..a8737de02f66 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
@@ -13,7 +13,7 @@ extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table;
extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8851b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg;
-extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8851b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms;
extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[];
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
new file mode 100644
index 000000000000..0f7711c50bd1
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2022-2023 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "pci.h"
+#include "reg.h"
+#include "rtw8851b.h"
+
+static const struct rtw89_pci_info rtw8851b_pci_info = {
+ .txbd_trunc_mode = MAC_AX_BD_TRUNC,
+ .rxbd_trunc_mode = MAC_AX_BD_TRUNC,
+ .rxbd_mode = MAC_AX_RXBD_PKT,
+ .tag_mode = MAC_AX_TAG_MULTI,
+ .tx_burst = MAC_AX_TX_BURST_2048B,
+ .rx_burst = MAC_AX_RX_BURST_128B,
+ .wd_dma_idle_intvl = MAC_AX_WD_DMA_INTVL_256NS,
+ .wd_dma_act_intvl = MAC_AX_WD_DMA_INTVL_256NS,
+ .multi_tag_num = MAC_AX_TAG_NUM_8,
+ .lbc_en = MAC_AX_PCIE_ENABLE,
+ .lbc_tmr = MAC_AX_LBC_TMR_2MS,
+ .autok_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
+
+ .init_cfg_reg = R_AX_PCIE_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN,
+ .rxhci_en_bit = B_AX_RXHCI_EN,
+ .rxbd_mode_bit = B_AX_RXBD_MODE,
+ .exp_ctrl_reg = R_AX_PCIE_EXP_CTRL,
+ .max_tag_num_mask = B_AX_MAX_TAG_NUM,
+ .rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
+ .txbd_rwptr_clr2_reg = 0,
+ .dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK_V1},
+ .dma_stop2 = {0},
+ .dma_busy1 = {R_AX_PCIE_DMA_BUSY1, DMA_BUSY1_CHECK_V1},
+ .dma_busy2_reg = 0,
+ .dma_busy3_reg = R_AX_PCIE_DMA_BUSY1,
+
+ .rpwm_addr = R_AX_PCIE_HRPWM,
+ .cpwm_addr = R_AX_CPWM,
+ .tx_dma_ch_mask = BIT(RTW89_TXCH_ACH4) | BIT(RTW89_TXCH_ACH5) |
+ BIT(RTW89_TXCH_ACH6) | BIT(RTW89_TXCH_ACH7) |
+ BIT(RTW89_TXCH_CH10) | BIT(RTW89_TXCH_CH11),
+ .bd_idx_addr_low_power = NULL,
+ .dma_addr_set = &rtw89_pci_ch_dma_addr_set,
+ .bd_ram_table = &rtw89_bd_ram_table_single,
+
+ .ltr_set = rtw89_pci_ltr_set,
+ .fill_txaddr_info = rtw89_pci_fill_txaddr_info,
+ .config_intr_mask = rtw89_pci_config_intr_mask,
+ .enable_intr = rtw89_pci_enable_intr,
+ .disable_intr = rtw89_pci_disable_intr,
+ .recognize_intrs = rtw89_pci_recognize_intrs,
+};
+
+static const struct rtw89_driver_info rtw89_8851be_info = {
+ .chip = &rtw8851b_chip_info,
+ .bus = {
+ .pci = &rtw8851b_pci_info,
+ },
+};
+
+static const struct pci_device_id rtw89_8851be_id_table[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb851),
+ .driver_data = (kernel_ulong_t)&rtw89_8851be_info,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(pci, rtw89_8851be_id_table);
+
+static struct pci_driver rtw89_8851be_driver = {
+ .name = "rtw89_8851be",
+ .id_table = rtw89_8851be_id_table,
+ .probe = rtw89_pci_probe,
+ .remove = rtw89_pci_remove,
+ .driver.pm = &rtw89_pm_ops,
+};
+module_pci_driver(rtw89_8851be_driver);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851BE driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index d7930efd89b7..6257414a3b4b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -463,6 +463,12 @@ static const struct rtw89_imr_info rtw8852a_imr_info = {
.tmac_imr_set = B_AX_TMAC_IMR_SET,
};
+static const struct rtw89_xtal_info rtw8852a_xtal_info = {
+ .xcap_reg = R_AX_XTAL_ON_CTRL0,
+ .sc_xo_mask = B_AX_XTAL_SC_XO_MASK,
+ .sc_xi_mask = B_AX_XTAL_SC_XI_MASK,
+};
+
static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = {
.ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0},
.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
@@ -1332,7 +1338,6 @@ static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start)
static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev)
{
rtw8852a_dpk_track(rtwdev);
- rtw8852a_iqk_track(rtwdev);
rtw8852a_tssi_track(rtwdev);
}
@@ -2026,6 +2031,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.read_efuse = rtw8852a_read_efuse,
.read_phycap = rtw8852a_read_phycap,
.fem_setup = rtw8852a_fem_setup,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852a_rfk_init,
.rfk_channel = rtw8852a_rfk_channel,
.rfk_band_changed = rtw8852a_rfk_band_changed,
@@ -2043,6 +2049,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
.pwr_on_func = NULL,
.pwr_off_func = NULL,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
@@ -2069,6 +2076,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.fw_format_max = RTW8852A_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
+ .small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 3500,
.dis_2g_40m_ul_ofdma = true,
@@ -2085,6 +2093,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.rf_table = {&rtw89_8852a_phy_radioa_table,
&rtw89_8852a_phy_radiob_table,},
.nctl_table = &rtw89_8852a_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852a_byr_table,
.dflt_parms = &rtw89_8852a_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2097,6 +2106,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
+ .support_unii4 = false,
.support_ul_tb_ctrl = false,
.hw_sec_hdr = false,
.rf_path_num = 2,
@@ -2107,7 +2117,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.scam_num = 128,
.bacam_num = 2,
.bacam_dynamic_num = 4,
- .bacam_v1 = false,
+ .bacam_ver = RTW89_BACAM_V0,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 1536,
@@ -2159,6 +2169,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852a,
#endif
+ .xtal_info = &rtw8852a_xtal_info,
};
EXPORT_SYMBOL(rtw8852a_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
index cd6c39b7f802..d86429e4a35f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
@@ -1284,11 +1284,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp = 0x0;
bool flag = 0x0;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path,
- iqk_info->thermal[path]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path,
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path,
iqk_info->lok_cor_fail[0][path]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path,
@@ -1536,28 +1533,6 @@ static void _iqk_dbcc(struct rtw89_dev *rtwdev, u8 path)
_iqk_afebb_restore(rtwdev, phy_idx, path);
}
-static void _iqk_track(struct rtw89_dev *rtwdev)
-{
- struct rtw89_iqk_info *iqk = &rtwdev->iqk;
- u8 path = 0x0;
- u8 cur_ther;
-
- if (iqk->iqk_band[0] == RTW89_BAND_2G)
- return;
- if (iqk->iqk_bw[0] < RTW89_CHANNEL_WIDTH_80)
- return;
-
- /* only check path 0 */
- for (path = 0; path < 1; path++) {
- cur_ther = ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
-
- if (abs(cur_ther - iqk->thermal[path]) > RTW8852A_IQK_THR_REK)
- iqk->thermal_rek_en = true;
- else
- iqk->thermal_rek_en = false;
- }
-}
-
static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
u32 rf_reg5, rck_val = 0;
@@ -1616,7 +1591,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) {
@@ -1645,7 +1619,6 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_debug(rtwdev, RTW89_DBG_RFK,
"[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852A_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
@@ -3655,11 +3628,6 @@ void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP);
}
-void rtw8852a_iqk_track(struct rtw89_dev *rtwdev)
-{
- _iqk_track(rtwdev);
-}
-
void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
bool is_afe)
{
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
index ea36553a76b7..fa058ccc8616 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.h
@@ -10,7 +10,6 @@
void rtw8852a_rck(struct rtw89_dev *rtwdev);
void rtw8852a_dack(struct rtw89_dev *rtwdev);
void rtw8852a_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
-void rtw8852a_iqk_track(struct rtw89_dev *rtwdev);
void rtw8852a_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
bool is_afe);
void rtw8852a_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 6da1b603a9a9..718f993da62a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -2454,6 +2454,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.read_efuse = rtw8852b_read_efuse,
.read_phycap = rtw8852b_read_phycap,
.fem_setup = NULL,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852b_rfk_init,
.rfk_channel = rtw8852b_rfk_channel,
.rfk_band_changed = rtw8852b_rfk_band_changed,
@@ -2471,6 +2472,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852b_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852b_pwr_on_func,
.pwr_off_func = rtw8852b_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path,
@@ -2506,6 +2508,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.fw_format_max = RTW8852B_FW_FORMAT_MAX,
.try_ce_fw = true,
.fifo_size = 196608,
+ .small_fifo_size = true,
.dle_scc_rsvd_size = 98304,
.max_amsdu_limit = 3500,
.dis_2g_40m_ul_ofdma = true,
@@ -2522,6 +2525,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.rf_table = {&rtw89_8852b_phy_radioa_table,
&rtw89_8852b_phy_radiob_table,},
.nctl_table = &rtw89_8852b_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852b_byr_table,
.dflt_parms = &rtw89_8852b_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2534,6 +2538,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.support_bands = BIT(NL80211_BAND_2GHZ) |
BIT(NL80211_BAND_5GHZ),
.support_bw160 = false,
+ .support_unii4 = true,
.support_ul_tb_ctrl = true,
.hw_sec_hdr = false,
.rf_path_num = 2,
@@ -2544,7 +2549,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.scam_num = 128,
.bacam_num = 2,
.bacam_dynamic_num = 4,
- .bacam_v1 = false,
+ .bacam_ver = RTW89_BACAM_V0,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
@@ -2598,6 +2603,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852b,
#endif
+ .xtal_info = NULL,
};
EXPORT_SYMBOL(rtw8852b_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
index 722ae34b09c1..259df67836a0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
@@ -846,7 +846,7 @@ static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
case ID_NBTXK:
rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x0);
rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x011);
- iqk_cmd = 0x308 | (1 << (4 + path));
+ iqk_cmd = 0x408 | (1 << (4 + path));
break;
case ID_NBRXK:
rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_EN, 0x1);
@@ -1078,7 +1078,7 @@ static bool _iqk_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8
{
struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
bool kfail;
- u8 gp = 0x3;
+ u8 gp = 0x2;
switch (iqk_info->iqk_band[path]) {
case RTW89_BAND_2G:
@@ -1317,10 +1317,6 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp;
bool flag;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
-
flag = iqk_info->lok_cor_fail[0][path];
rtw89_phy_write32_mask(rtwdev, R_IQKINF, B_IQKINF_FCOR << (path * 4), flag);
flag = iqk_info->lok_fin_fail[0][path];
@@ -1568,7 +1564,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
@@ -1622,9 +1617,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
rtw89_debug(rtwdev, RTW89_DBG_RFK,
- "[IQK]==========IQK strat!!!!!==========\n");
+ "[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852B_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
index 904cdb9e56fa..17124d851a22 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
@@ -14666,7 +14666,7 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
[0][0][RTW89_CHILE] = 0,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
index 5f4161496a58..7ef217629f46 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
@@ -14,7 +14,7 @@ extern const struct rtw89_phy_table rtw89_8852b_phy_radiob_table;
extern const struct rtw89_phy_table rtw89_8852b_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852b_byr_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg;
-extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8852b_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index ceb819a62efc..9c7c9812d4f4 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2762,6 +2762,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.read_efuse = rtw8852c_read_efuse,
.read_phycap = rtw8852c_read_phycap,
.fem_setup = NULL,
+ .rfe_gpio = NULL,
.rfk_init = rtw8852c_rfk_init,
.rfk_channel = rtw8852c_rfk_channel,
.rfk_band_changed = rtw8852c_rfk_band_changed,
@@ -2779,6 +2780,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
.pwr_on_func = rtw8852c_pwr_on_func,
.pwr_off_func = rtw8852c_pwr_off_func,
+ .query_rxdesc = rtw89_core_query_rxdesc,
.fill_txdesc = rtw89_core_fill_txdesc_v1,
.fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1,
.cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1,
@@ -2805,6 +2807,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.fw_format_max = RTW8852C_FW_FORMAT_MAX,
.try_ce_fw = false,
.fifo_size = 458752,
+ .small_fifo_size = false,
.dle_scc_rsvd_size = 0,
.max_amsdu_limit = 8000,
.dis_2g_40m_ul_ofdma = false,
@@ -2821,6 +2824,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.rf_table = {&rtw89_8852c_phy_radiob_table,
&rtw89_8852c_phy_radioa_table,},
.nctl_table = &rtw89_8852c_phy_nctl_table,
+ .nctl_post_table = NULL,
.byr_table = &rtw89_8852c_byr_table,
.dflt_parms = &rtw89_8852c_dflt_parms,
.rfe_parms_conf = NULL,
@@ -2834,6 +2838,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
BIT(NL80211_BAND_5GHZ) |
BIT(NL80211_BAND_6GHZ),
.support_bw160 = true,
+ .support_unii4 = true,
.support_ul_tb_ctrl = false,
.hw_sec_hdr = true,
.rf_path_num = 2,
@@ -2844,7 +2849,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.scam_num = 128,
.bacam_num = 8,
.bacam_dynamic_num = 8,
- .bacam_v1 = true,
+ .bacam_ver = RTW89_BACAM_V0_EXT,
.sec_ctrl_efuse_size = 4,
.physical_efuse_size = 1216,
.logical_efuse_size = 2048,
@@ -2897,6 +2902,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
#ifdef CONFIG_PM
.wowlan_stub = &rtw_wowlan_stub_8852c,
#endif
+ .xtal_info = NULL,
};
EXPORT_SYMBOL(rtw8852c_chip_info);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index 2c0bc3a4ab3b..de7714f871d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -1261,11 +1261,8 @@ static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
u32 tmp;
bool flag;
- iqk_info->thermal[path] =
- ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]);
- iqk_info->thermal_rek_en = false;
- rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %d\n", path,
- iqk_info->thermal[path]);
+ rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path,
+ ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]));
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path,
iqk_info->lok_cor_fail[0][path]);
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path,
@@ -1502,7 +1499,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev)
iqk_info->iqk_sram_en = false;
iqk_info->iqk_cfir_en = false;
iqk_info->iqk_xym_en = false;
- iqk_info->thermal_rek_en = false;
iqk_info->iqk_times = 0x0;
for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) {
@@ -1529,9 +1525,8 @@ static void _doiqk(struct rtw89_dev *rtwdev, bool force,
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
rtw89_debug(rtwdev, RTW89_DBG_RFK,
- "[IQK]==========IQK strat!!!!!==========\n");
+ "[IQK]==========IQK start!!!!!==========\n");
iqk_info->iqk_times++;
- iqk_info->kcount = 0;
iqk_info->version = RTW8852C_IQK_VER;
rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
index 7011e5a6f8fd..4b272fdf1fd7 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
@@ -2551,19 +2551,27 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0xF0040001, 0x0000000A},
{0xF0050001, 0x0000000B},
{0xF0070001, 0x0000000C},
- {0xF0320001, 0x0000000D},
- {0xF0330001, 0x0000000E},
- {0xF0340001, 0x0000000F},
- {0xF0350001, 0x00000010},
- {0xF0360001, 0x00000011},
- {0xF03F0001, 0x00000012},
- {0xF0400001, 0x00000013},
+ {0xF0150001, 0x0000000D},
+ {0xF0160001, 0x0000000E},
+ {0xF0320001, 0x0000000F},
+ {0xF0330001, 0x00000010},
+ {0xF0340001, 0x00000011},
+ {0xF0350001, 0x00000012},
+ {0xF0360001, 0x00000013},
+ {0xF03F0001, 0x00000014},
+ {0xF0400001, 0x00000015},
{0x005, 0x00000000},
{0x10005, 0x00000000},
{0x000, 0x00030001},
{0x10000, 0x00030000},
{0x018, 0x00011124},
{0x10018, 0x00011124},
+ {0x0A3, 0x000B9204},
+ {0x0AD, 0x00091E0F},
+ {0x05D, 0x00001012},
+ {0x05C, 0x00061C5C},
+ {0x062, 0x00055220},
+ {0x0D3, 0x00000103},
{0x0EF, 0x00080000},
{0x033, 0x00000001},
{0x03E, 0x00000620},
@@ -2636,6 +2644,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
@@ -2716,6 +2730,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000CC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000CC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000CC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000CC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000CC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2760,6 +2778,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000C4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000C4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000C4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000C4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000C4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2804,6 +2826,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000BC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2848,6 +2874,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000B4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2892,6 +2922,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000AC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2936,6 +2970,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2980,6 +3018,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000009C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3024,6 +3066,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000094},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3068,6 +3114,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000008C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3112,6 +3162,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000084},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3156,6 +3210,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000BC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000BC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000BC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3200,6 +3258,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000B4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000B4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000B4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3244,6 +3306,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000AC},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000AC},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000AC},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3288,6 +3354,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000000A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000000A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000000A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3332,6 +3402,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000009C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000009C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000009C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3376,6 +3450,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000094},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000094},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000094},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3420,6 +3498,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000008C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000008C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000008C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3464,6 +3546,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000084},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000084},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000084},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3508,6 +3594,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000003C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000003C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000003C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000003C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3552,6 +3642,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000034},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000034},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000034},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000034},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000034},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3596,6 +3690,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000002C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000002C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000002C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000002C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000002C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3640,6 +3738,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000024},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000024},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000024},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000024},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000024},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3684,6 +3786,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000001C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000001C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000001C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000001C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000001C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3728,6 +3834,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000014},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000014},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000014},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000014},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000014},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3772,6 +3882,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000000C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000000C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000000C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000000C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000000C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3816,6 +3930,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000004},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000004},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000004},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000004},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000004},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3873,6 +3991,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x08F, 0x000D1352},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3936,6 +4058,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000007},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -4472,6 +4598,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000EFFF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -4810,6 +4940,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x00050112},
{0x030, 0x00058101},
{0x030, 0x00060001},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000085ED},
{0x030, 0x000105CC},
@@ -5157,6 +5313,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x000300FF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000300FF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000300FF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000300FF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000300FF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5178,11 +5338,268 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x0EF, 0x00000000},
{0x06E, 0x00077A18},
{0x06D, 0x00000C31},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
{0x06A, 0x000E0F8A},
{0x06B, 0x000018A0},
{0x06F, 0x000F81FC},
{0x05E, 0x0000001F},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x05E, 0x0000001F},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x05E, 0x0000001F},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0xA0000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x05E, 0x0000001F},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000200},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x0003D407},
{0x030, 0x00035A87},
{0x030, 0x0002CF07},
@@ -5191,14 +5608,225 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x030, 0x00014F07},
{0x030, 0x0000CF07},
{0x030, 0x00004F07},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000000},
{0x0EB, 0x00080000},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x00008038},
{0x030, 0x00010038},
{0x030, 0x00018038},
{0x030, 0x00020038},
{0x030, 0x00028038},
{0x030, 0x00030038},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xB0000000, 0x00000000},
{0x030, 0x0003803C},
{0x030, 0x0004003C},
{0x030, 0x0004803C},
@@ -5235,6 +5863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x095, 0x00000008},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5280,6 +5912,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5324,6 +5960,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5368,6 +6008,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5412,6 +6056,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5456,6 +6104,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5500,6 +6152,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5548,6 +6204,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5592,6 +6252,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5636,6 +6300,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5680,6 +6348,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5724,6 +6396,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5768,6 +6444,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5812,6 +6492,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5856,6 +6540,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5900,6 +6588,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5944,6 +6636,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -5988,6 +6684,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6032,6 +6732,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6076,6 +6780,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6120,6 +6828,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6164,6 +6876,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6208,6 +6924,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -6252,20 +6972,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -6296,20 +7020,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -6340,20 +7068,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -6384,20 +7116,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -6428,20 +7164,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -6472,20 +7212,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -6516,20 +7260,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -6560,20 +7308,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -6604,20 +7356,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -6648,20 +7404,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -6692,20 +7452,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -6736,20 +7500,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -6780,20 +7548,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -6824,20 +7596,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -6868,20 +7644,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -6912,20 +7692,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -6956,20 +7740,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -7000,20 +7788,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -7044,20 +7836,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -7088,20 +7884,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -7132,20 +7932,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -7176,20 +7980,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -7220,20 +8028,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -7264,20 +8076,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -7308,20 +8124,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -7352,20 +8172,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -7396,20 +8220,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -7440,20 +8268,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -7484,20 +8316,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -7528,20 +8364,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -9436,7 +10276,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9581,7 +10421,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9600,60 +10440,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -9697,7 +10537,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007115B},
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
+ {0x10030, 0x00071D17},
{0x10030, 0x000720DF},
{0x10030, 0x000724D9},
{0x10030, 0x000728A1},
@@ -9726,7 +10566,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -9745,60 +10585,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -9842,7 +10682,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007115B},
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
+ {0x10030, 0x00071D17},
{0x10030, 0x000720DF},
{0x10030, 0x000724D9},
{0x10030, 0x000728A1},
@@ -9871,6 +10711,296 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -9949,73 +11079,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10094,73 +11224,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10239,73 +11369,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -10384,73 +11514,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
+ {0x10030, 0x0006C411},
{0x10030, 0x000701EF},
- {0x10030, 0x000705E7},
- {0x10030, 0x000709A7},
- {0x10030, 0x00070D61},
- {0x10030, 0x0007115B},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071CE5},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728A1},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
{0x10030, 0x000781EF},
{0x10030, 0x000785E9},
{0x10030, 0x000789E3},
{0x10030, 0x00078DA1},
{0x10030, 0x0007915F},
{0x10030, 0x00079559},
- {0x10030, 0x00079921},
- {0x10030, 0x00079D1B},
- {0x10030, 0x0007A0E3},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B823},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0xA0000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -11294,6 +12424,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x000338CC},
{0x10030, 0x00033C09},
{0x10030, 0x00034006},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280ED},
+ {0x10030, 0x000284EA},
+ {0x10030, 0x000288E7},
+ {0x10030, 0x00028CE4},
+ {0x10030, 0x000290E1},
+ {0x10030, 0x000294DE},
+ {0x10030, 0x000298DB},
+ {0x10030, 0x00029CD8},
+ {0x10030, 0x0002A0D5},
+ {0x10030, 0x0002A4D2},
+ {0x10030, 0x0002A8CF},
+ {0x10030, 0x0002AC0C},
+ {0x10030, 0x0002B009},
+ {0x10030, 0x0002B406},
+ {0x10030, 0x0002B803},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300EE},
+ {0x10030, 0x000304EB},
+ {0x10030, 0x000308E8},
+ {0x10030, 0x00030CE5},
+ {0x10030, 0x000310E2},
+ {0x10030, 0x000314DF},
+ {0x10030, 0x000318DC},
+ {0x10030, 0x00031CD9},
+ {0x10030, 0x000320D6},
+ {0x10030, 0x000324D3},
+ {0x10030, 0x000328D0},
+ {0x10030, 0x00032CCD},
+ {0x10030, 0x0003300A},
+ {0x10030, 0x00033407},
+ {0x10030, 0x00033804},
+ {0x10030, 0x00033C01},
+ {0x10030, 0x00034000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280ED},
+ {0x10030, 0x000284EA},
+ {0x10030, 0x000288E7},
+ {0x10030, 0x00028CE4},
+ {0x10030, 0x000290E1},
+ {0x10030, 0x000294DE},
+ {0x10030, 0x000298DB},
+ {0x10030, 0x00029CD8},
+ {0x10030, 0x0002A0D5},
+ {0x10030, 0x0002A4D2},
+ {0x10030, 0x0002A8CF},
+ {0x10030, 0x0002AC0C},
+ {0x10030, 0x0002B009},
+ {0x10030, 0x0002B406},
+ {0x10030, 0x0002B803},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300EE},
+ {0x10030, 0x000304EB},
+ {0x10030, 0x000308E8},
+ {0x10030, 0x00030CE5},
+ {0x10030, 0x000310E2},
+ {0x10030, 0x000314DF},
+ {0x10030, 0x000318DC},
+ {0x10030, 0x00031CD9},
+ {0x10030, 0x000320D6},
+ {0x10030, 0x000324D3},
+ {0x10030, 0x000328D0},
+ {0x10030, 0x00032CCD},
+ {0x10030, 0x0003300A},
+ {0x10030, 0x00033407},
+ {0x10030, 0x00033804},
+ {0x10030, 0x00033C01},
+ {0x10030, 0x00034000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000200FA},
{0x10030, 0x000204F7},
@@ -11841,6 +13075,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11885,6 +13123,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11941,6 +13183,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -11985,6 +13231,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12041,6 +13291,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12085,6 +13339,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12141,6 +13399,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12185,6 +13447,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12241,6 +13507,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12285,6 +13555,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12305,7 +13579,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x033, 0x00000070},
{0x03F, 0x00050002},
{0x033, 0x00000071},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00060032},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xA0000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xB0000000, 0x00000000},
{0x033, 0x00000072},
{0x03F, 0x00050042},
{0x033, 0x00000073},
@@ -12341,6 +13661,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12385,6 +13709,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12405,7 +13733,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x033, 0x00000078},
{0x03F, 0x00050002},
{0x033, 0x00000079},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00060032},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xA0000000, 0x00000000},
+ {0x03F, 0x00060032},
+ {0xB0000000, 0x00000000},
{0x033, 0x0000007A},
{0x03F, 0x00050042},
{0x033, 0x0000007B},
@@ -12441,6 +13815,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12485,6 +13863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12541,6 +13923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12585,6 +13971,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12641,6 +14031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12685,6 +14079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12741,6 +14139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12785,6 +14187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12841,6 +14247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12885,6 +14295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12941,6 +14355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -12985,6 +14403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13041,6 +14463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13085,6 +14511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13141,6 +14571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13185,6 +14619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13241,6 +14679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13285,6 +14727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13341,6 +14787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13385,6 +14835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13441,6 +14895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13485,6 +14943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13541,6 +15003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13585,6 +15051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13641,6 +15111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13685,6 +15159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13741,6 +15219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13785,6 +15267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13841,6 +15327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13885,6 +15375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13941,6 +15435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -13985,6 +15483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14041,6 +15543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14085,6 +15591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14141,6 +15651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14185,6 +15699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14241,6 +15759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14285,6 +15807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14341,6 +15867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14385,6 +15915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14441,6 +15975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14485,6 +16023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14541,6 +16083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14585,6 +16131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14669,6 +16219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00025003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14719,6 +16273,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0002D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14769,6 +16327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x00035003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14819,6 +16381,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x10030, 0x0003D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -14882,6 +16448,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
@@ -14952,6 +16524,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
@@ -15022,6 +16600,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
@@ -15092,6 +16676,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
@@ -15119,7 +16709,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
{0xB0000000, 0x00000000},
{0x10030, 0x0007F003},
{0x100EE, 0x00000000},
- {0x0FE, 0x00000048},
+ {0x0FE, 0x00000063},
};
static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
@@ -15136,13 +16726,15 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0xF0040001, 0x0000000A},
{0xF0050001, 0x0000000B},
{0xF0070001, 0x0000000C},
- {0xF0320001, 0x0000000D},
- {0xF0330001, 0x0000000E},
- {0xF0340001, 0x0000000F},
- {0xF0350001, 0x00000010},
- {0xF0360001, 0x00000011},
- {0xF03F0001, 0x00000012},
- {0xF0400001, 0x00000013},
+ {0xF0150001, 0x0000000D},
+ {0xF0160001, 0x0000000E},
+ {0xF0320001, 0x0000000F},
+ {0xF0330001, 0x00000010},
+ {0xF0340001, 0x00000011},
+ {0xF0350001, 0x00000012},
+ {0xF0360001, 0x00000013},
+ {0xF03F0001, 0x00000014},
+ {0xF0400001, 0x00000015},
{0x005, 0x00000000},
{0x10005, 0x00000000},
{0x0B9, 0x00020440},
@@ -15150,6 +16742,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10000, 0x00030000},
{0x018, 0x00011124},
{0x10018, 0x00011124},
+ {0x0A3, 0x000B9204},
+ {0x0AD, 0x00091E0F},
+ {0x05D, 0x00001012},
+ {0x05C, 0x00079C5C},
+ {0x062, 0x00055220},
+ {0x0D3, 0x00000103},
{0x05F, 0x00000038},
{0x097, 0x00043200},
{0x0A6, 0x00066DB7},
@@ -15253,6 +16851,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x067, 0x0000D300},
+ {0x0DA, 0x000D4000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x067, 0x0000D300},
{0x0DA, 0x000D4000},
@@ -15319,6 +16923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x08F, 0x000D1352},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x08F, 0x000D1352},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x08F, 0x000D1352},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -15382,6 +16990,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000007},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000017},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000007},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -15918,6 +17530,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000EFFF},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000EFFF},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000EFFF},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16256,6 +17872,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x030, 0x00050112},
{0x030, 0x00058101},
{0x030, 0x00060001},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x000085ED},
+ {0x030, 0x000105CC},
+ {0x030, 0x000184AA},
+ {0x030, 0x00020388},
+ {0x030, 0x00028377},
+ {0x030, 0x00030377},
+ {0x030, 0x00038255},
+ {0x030, 0x00040244},
+ {0x030, 0x00048133},
+ {0x030, 0x00050112},
+ {0x030, 0x00058101},
+ {0x030, 0x00060001},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x000085ED},
{0x030, 0x000105CC},
@@ -16582,11 +18224,291 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x0EF, 0x00000000},
{0x06E, 0x00077A18},
{0x06D, 0x00000C31},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x06A, 0x000E0F8A},
{0x06B, 0x000018A0},
{0x06F, 0x000F81FC},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0380},
+ {0x06B, 0x00003CA0},
+ {0x06F, 0x000C01FC},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0xA0000000, 0x00000000},
+ {0x06A, 0x000E0F8A},
+ {0x06B, 0x000018A0},
+ {0x06F, 0x000F81FC},
+ {0xB0000000, 0x00000000},
{0x05E, 0x0000001F},
{0x0EF, 0x00000200},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x030, 0x0003E207},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x0003D407},
{0x030, 0x00035A87},
{0x030, 0x0002CF07},
@@ -16595,14 +18517,180 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x030, 0x00014F07},
{0x030, 0x0000CF07},
{0x030, 0x00004F07},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x0003D407},
+ {0x030, 0x00035A87},
+ {0x030, 0x0002CF07},
+ {0x030, 0x00024F07},
+ {0x030, 0x0001CF07},
+ {0x030, 0x00014F07},
+ {0x030, 0x0000CF07},
+ {0x030, 0x00004F07},
+ {0xB0000000, 0x00000000},
{0x0EF, 0x00000000},
{0x0EB, 0x00080000},
+ {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
{0x030, 0x00008038},
{0x030, 0x00010038},
{0x030, 0x00018038},
{0x030, 0x00020038},
{0x030, 0x00028038},
{0x030, 0x00030038},
+ {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x0000803C},
+ {0x030, 0x0001003C},
+ {0x030, 0x0001803C},
+ {0x030, 0x0002003C},
+ {0x030, 0x0002803C},
+ {0x030, 0x0003003C},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xA0000000, 0x00000000},
+ {0x030, 0x00008038},
+ {0x030, 0x00010038},
+ {0x030, 0x00018038},
+ {0x030, 0x00020038},
+ {0x030, 0x00028038},
+ {0x030, 0x00030038},
+ {0xB0000000, 0x00000000},
{0x030, 0x0003803C},
{0x030, 0x0004003C},
{0x030, 0x0004803C},
@@ -16639,6 +18727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x095, 0x00000008},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x095, 0x00000008},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x095, 0x00000008},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16684,6 +18776,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16728,6 +18824,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16772,6 +18872,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16816,6 +18920,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16860,6 +18968,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16904,6 +19016,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16948,6 +19064,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -16992,6 +19112,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17036,6 +19160,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17080,6 +19208,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17124,6 +19256,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17168,6 +19304,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17212,6 +19352,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17256,6 +19400,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17300,6 +19448,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17344,6 +19496,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17388,6 +19544,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17432,6 +19592,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17476,6 +19640,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17520,6 +19688,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17564,6 +19736,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17608,6 +19784,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17652,6 +19832,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17696,6 +19880,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -17740,20 +19928,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -17784,20 +19976,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -17828,20 +20024,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -17872,20 +20072,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -17916,20 +20120,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -17960,20 +20168,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18004,20 +20216,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18048,20 +20264,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18092,20 +20312,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18136,20 +20360,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18180,20 +20408,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18224,20 +20456,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18268,20 +20504,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -18312,20 +20552,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18356,20 +20600,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18400,20 +20648,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18444,20 +20696,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18488,20 +20744,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18532,20 +20792,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18576,20 +20840,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18620,20 +20888,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -18664,20 +20936,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -18708,20 +20984,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000002E6},
+ {0x03F, 0x000002E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000002E6},
{0xB0000000, 0x00000000},
@@ -18752,20 +21032,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000003E7},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000003E7},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000003E7},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000003E6},
+ {0x03F, 0x000003E7},
{0xA0000000, 0x00000000},
{0x03F, 0x000003E6},
{0xB0000000, 0x00000000},
@@ -18796,20 +21080,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000152},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00000152},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000152},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x00000052},
+ {0x03F, 0x00000152},
{0xA0000000, 0x00000000},
{0x03F, 0x00000052},
{0xB0000000, 0x00000000},
@@ -18840,20 +21128,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000015A},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000015A},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000015A},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000005A},
+ {0x03F, 0x0000015A},
{0xA0000000, 0x00000000},
{0x03F, 0x0000005A},
{0xB0000000, 0x00000000},
@@ -18884,20 +21176,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000019C},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x0000019C},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x0000019C},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000009C},
+ {0x03F, 0x0000019C},
{0xA0000000, 0x00000000},
{0x03F, 0x0000009C},
{0xB0000000, 0x00000000},
@@ -18928,20 +21224,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001A4},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001A4},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001A4},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x0000019C},
+ {0x03F, 0x000001A4},
{0xA0000000, 0x00000000},
{0x03F, 0x0000019C},
{0xB0000000, 0x00000000},
@@ -18972,20 +21272,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000001E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000001E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000001E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001A4},
+ {0x03F, 0x000001E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001A4},
{0xB0000000, 0x00000000},
@@ -19016,20 +21320,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x000002E6},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x000002E6},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x000002E6},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90340001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
- {0x03F, 0x000001E6},
+ {0x03F, 0x000002E6},
{0xA0000000, 0x00000000},
{0x03F, 0x000001E6},
{0xB0000000, 0x00000000},
@@ -20924,7 +23232,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21069,7 +23377,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21088,60 +23396,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -21186,7 +23494,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
{0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
+ {0x10030, 0x00072111},
{0x10030, 0x000724D9},
{0x10030, 0x000728D3},
{0x10030, 0x00072C67},
@@ -21214,7 +23522,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
- {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
{0x10030, 0x000009E3},
@@ -21233,60 +23541,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00003C5F},
{0x10030, 0x00004059},
{0x10030, 0x00004453},
- {0x10030, 0x000201A7},
- {0x10030, 0x000205A1},
- {0x10030, 0x0002099B},
- {0x10030, 0x00020D95},
- {0x10030, 0x0002115B},
- {0x10030, 0x00021555},
- {0x10030, 0x00021921},
- {0x10030, 0x00021D1B},
- {0x10030, 0x000220E3},
- {0x10030, 0x000224DD},
+ {0x10030, 0x000201EF},
+ {0x10030, 0x000205E9},
+ {0x10030, 0x000209E3},
+ {0x10030, 0x00020DA3},
+ {0x10030, 0x00021161},
+ {0x10030, 0x0002155B},
+ {0x10030, 0x0002191F},
+ {0x10030, 0x00021D19},
+ {0x10030, 0x000220E1},
+ {0x10030, 0x000224DB},
{0x10030, 0x000228A3},
{0x10030, 0x00022C9D},
{0x10030, 0x00023063},
{0x10030, 0x0002345D},
{0x10030, 0x00023823},
- {0x10030, 0x00023C1D},
- {0x10030, 0x00024017},
- {0x10030, 0x00024411},
- {0x10030, 0x000281A9},
- {0x10030, 0x000285A3},
- {0x10030, 0x0002899D},
- {0x10030, 0x00028D97},
- {0x10030, 0x0002915D},
- {0x10030, 0x00029557},
- {0x10030, 0x0002991F},
- {0x10030, 0x00029D19},
- {0x10030, 0x0002A0E1},
- {0x10030, 0x0002A4DB},
+ {0x10030, 0x00023C1B},
+ {0x10030, 0x00024015},
+ {0x10030, 0x0002440F},
+ {0x10030, 0x000281EF},
+ {0x10030, 0x000285E7},
+ {0x10030, 0x000289A7},
+ {0x10030, 0x00028D65},
+ {0x10030, 0x0002915F},
+ {0x10030, 0x00029523},
+ {0x10030, 0x0002991D},
+ {0x10030, 0x00029CE5},
+ {0x10030, 0x0002A0DF},
+ {0x10030, 0x0002A4A7},
{0x10030, 0x0002A8A1},
- {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002AC67},
{0x10030, 0x0002B061},
- {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B427},
{0x10030, 0x0002B821},
- {0x10030, 0x0002BC1B},
- {0x10030, 0x0002C015},
- {0x10030, 0x0002C40F},
- {0x10030, 0x000301A9},
- {0x10030, 0x000305A3},
- {0x10030, 0x0003099D},
- {0x10030, 0x00030D97},
- {0x10030, 0x0003115D},
- {0x10030, 0x00031557},
+ {0x10030, 0x0002BC19},
+ {0x10030, 0x0002C013},
+ {0x10030, 0x0002C40D},
+ {0x10030, 0x000301EF},
+ {0x10030, 0x000305E7},
+ {0x10030, 0x000309A7},
+ {0x10030, 0x00030D65},
+ {0x10030, 0x0003115F},
+ {0x10030, 0x00031525},
{0x10030, 0x0003191F},
- {0x10030, 0x00031D19},
+ {0x10030, 0x00031CE7},
{0x10030, 0x000320E1},
- {0x10030, 0x000324DB},
- {0x10030, 0x000328A1},
- {0x10030, 0x00032C9B},
- {0x10030, 0x00033061},
- {0x10030, 0x0003345B},
- {0x10030, 0x00033821},
- {0x10030, 0x00033C1B},
- {0x10030, 0x00034015},
- {0x10030, 0x0003440F},
+ {0x10030, 0x000324A9},
+ {0x10030, 0x000328A3},
+ {0x10030, 0x00032C69},
+ {0x10030, 0x00033063},
+ {0x10030, 0x00033429},
+ {0x10030, 0x00033823},
+ {0x10030, 0x00033C1D},
+ {0x10030, 0x00034013},
+ {0x10030, 0x0003440D},
{0x10030, 0x000601F1},
{0x10030, 0x000605E9},
{0x10030, 0x000609A9},
@@ -21331,7 +23639,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00071523},
{0x10030, 0x0007191D},
{0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
+ {0x10030, 0x00072111},
{0x10030, 0x000724D9},
{0x10030, 0x000728D3},
{0x10030, 0x00072C67},
@@ -21359,6 +23667,296 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0007BC1D},
{0x10030, 0x0007C017},
{0x10030, 0x0007C40F},
+ {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
+ {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000001EF},
+ {0x10030, 0x000005E9},
+ {0x10030, 0x000009E3},
+ {0x10030, 0x00000DDD},
+ {0x10030, 0x000011D7},
+ {0x10030, 0x0000159F},
+ {0x10030, 0x00001999},
+ {0x10030, 0x00001D5F},
+ {0x10030, 0x00002159},
+ {0x10030, 0x0000251F},
+ {0x10030, 0x00002919},
+ {0x10030, 0x00002CDF},
+ {0x10030, 0x000030D9},
+ {0x10030, 0x0000349F},
+ {0x10030, 0x00003899},
+ {0x10030, 0x00003C5F},
+ {0x10030, 0x00004059},
+ {0x10030, 0x00004453},
+ {0x10030, 0x000201A7},
+ {0x10030, 0x000205A1},
+ {0x10030, 0x0002099B},
+ {0x10030, 0x00020D95},
+ {0x10030, 0x0002115B},
+ {0x10030, 0x00021555},
+ {0x10030, 0x00021921},
+ {0x10030, 0x00021D1B},
+ {0x10030, 0x000220E3},
+ {0x10030, 0x000224DD},
+ {0x10030, 0x000228A3},
+ {0x10030, 0x00022C9D},
+ {0x10030, 0x00023063},
+ {0x10030, 0x0002345D},
+ {0x10030, 0x00023823},
+ {0x10030, 0x00023C1D},
+ {0x10030, 0x00024017},
+ {0x10030, 0x00024411},
+ {0x10030, 0x000281A9},
+ {0x10030, 0x000285A3},
+ {0x10030, 0x0002899D},
+ {0x10030, 0x00028D97},
+ {0x10030, 0x0002915D},
+ {0x10030, 0x00029557},
+ {0x10030, 0x0002991F},
+ {0x10030, 0x00029D19},
+ {0x10030, 0x0002A0E1},
+ {0x10030, 0x0002A4DB},
+ {0x10030, 0x0002A8A1},
+ {0x10030, 0x0002AC9B},
+ {0x10030, 0x0002B061},
+ {0x10030, 0x0002B45B},
+ {0x10030, 0x0002B821},
+ {0x10030, 0x0002BC1B},
+ {0x10030, 0x0002C015},
+ {0x10030, 0x0002C40F},
+ {0x10030, 0x000301A9},
+ {0x10030, 0x000305A3},
+ {0x10030, 0x0003099D},
+ {0x10030, 0x00030D97},
+ {0x10030, 0x0003115D},
+ {0x10030, 0x00031557},
+ {0x10030, 0x0003191F},
+ {0x10030, 0x00031D19},
+ {0x10030, 0x000320E1},
+ {0x10030, 0x000324DB},
+ {0x10030, 0x000328A1},
+ {0x10030, 0x00032C9B},
+ {0x10030, 0x00033061},
+ {0x10030, 0x0003345B},
+ {0x10030, 0x00033821},
+ {0x10030, 0x00033C1B},
+ {0x10030, 0x00034015},
+ {0x10030, 0x0003440F},
+ {0x10030, 0x000601F1},
+ {0x10030, 0x000605E9},
+ {0x10030, 0x000609A9},
+ {0x10030, 0x00060D65},
+ {0x10030, 0x0006115F},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
+ {0x10030, 0x000681EF},
+ {0x10030, 0x000685E7},
+ {0x10030, 0x000689A7},
+ {0x10030, 0x00068D61},
+ {0x10030, 0x0006915B},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
+ {0x10030, 0x0006B429},
+ {0x10030, 0x0006B823},
+ {0x10030, 0x0006BC1D},
+ {0x10030, 0x0006C017},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
+ {0x10030, 0x000705E9},
+ {0x10030, 0x000709A9},
+ {0x10030, 0x00070D63},
+ {0x10030, 0x0007115D},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90350001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21437,73 +24035,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90360001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21582,73 +24180,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21727,73 +24325,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0x90400001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -21872,73 +24470,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000609A9},
{0x10030, 0x00060D65},
{0x10030, 0x0006115F},
- {0x10030, 0x00061525},
- {0x10030, 0x0006191F},
- {0x10030, 0x00061CE7},
- {0x10030, 0x000620E1},
- {0x10030, 0x000624DB},
- {0x10030, 0x000628A3},
- {0x10030, 0x00062C69},
- {0x10030, 0x00063063},
- {0x10030, 0x00063429},
- {0x10030, 0x00063823},
- {0x10030, 0x00063C1D},
- {0x10030, 0x00064013},
- {0x10030, 0x0006440D},
+ {0x10030, 0x00061527},
+ {0x10030, 0x00061921},
+ {0x10030, 0x00061CE9},
+ {0x10030, 0x000620E3},
+ {0x10030, 0x000624DD},
+ {0x10030, 0x000628A5},
+ {0x10030, 0x00062C6B},
+ {0x10030, 0x00063065},
+ {0x10030, 0x0006342B},
+ {0x10030, 0x00063825},
+ {0x10030, 0x00063C1F},
+ {0x10030, 0x00064019},
+ {0x10030, 0x00064413},
{0x10030, 0x000681EF},
{0x10030, 0x000685E7},
{0x10030, 0x000689A7},
{0x10030, 0x00068D61},
{0x10030, 0x0006915B},
- {0x10030, 0x00069523},
- {0x10030, 0x0006991D},
- {0x10030, 0x00069CE5},
- {0x10030, 0x0006A0DF},
- {0x10030, 0x0006A4A7},
- {0x10030, 0x0006A8A1},
- {0x10030, 0x0006AC67},
- {0x10030, 0x0006B061},
+ {0x10030, 0x00069525},
+ {0x10030, 0x0006991F},
+ {0x10030, 0x00069CE7},
+ {0x10030, 0x0006A0E1},
+ {0x10030, 0x0006A4A9},
+ {0x10030, 0x0006A8A3},
+ {0x10030, 0x0006AC69},
+ {0x10030, 0x0006B063},
{0x10030, 0x0006B429},
{0x10030, 0x0006B823},
{0x10030, 0x0006BC1D},
{0x10030, 0x0006C017},
- {0x10030, 0x0006C40D},
- {0x10030, 0x000701F1},
+ {0x10030, 0x0006C411},
+ {0x10030, 0x000701EF},
{0x10030, 0x000705E9},
{0x10030, 0x000709A9},
{0x10030, 0x00070D63},
{0x10030, 0x0007115D},
- {0x10030, 0x00071523},
- {0x10030, 0x0007191D},
- {0x10030, 0x00071D17},
- {0x10030, 0x000720DF},
- {0x10030, 0x000724D9},
- {0x10030, 0x000728D3},
- {0x10030, 0x00072C67},
- {0x10030, 0x00073061},
- {0x10030, 0x00073427},
- {0x10030, 0x00073821},
- {0x10030, 0x00073C1B},
- {0x10030, 0x00074015},
- {0x10030, 0x0007440D},
- {0x10030, 0x000781F1},
- {0x10030, 0x000785EB},
- {0x10030, 0x000789E5},
- {0x10030, 0x00078DA3},
- {0x10030, 0x00079161},
- {0x10030, 0x0007955B},
- {0x10030, 0x00079923},
- {0x10030, 0x00079D1D},
- {0x10030, 0x0007A117},
- {0x10030, 0x0007A4DD},
- {0x10030, 0x0007A8D7},
- {0x10030, 0x0007AC9D},
- {0x10030, 0x0007B063},
- {0x10030, 0x0007B45D},
- {0x10030, 0x0007B857},
- {0x10030, 0x0007BC1D},
- {0x10030, 0x0007C017},
- {0x10030, 0x0007C40F},
+ {0x10030, 0x00071525},
+ {0x10030, 0x0007191F},
+ {0x10030, 0x00071D19},
+ {0x10030, 0x000720E1},
+ {0x10030, 0x000724DB},
+ {0x10030, 0x000728A3},
+ {0x10030, 0x00072C69},
+ {0x10030, 0x00073063},
+ {0x10030, 0x00073429},
+ {0x10030, 0x00073823},
+ {0x10030, 0x00073C1D},
+ {0x10030, 0x00074017},
+ {0x10030, 0x00074411},
+ {0x10030, 0x000781EF},
+ {0x10030, 0x000785E9},
+ {0x10030, 0x000789E3},
+ {0x10030, 0x00078DA1},
+ {0x10030, 0x0007915F},
+ {0x10030, 0x00079559},
+ {0x10030, 0x0007991F},
+ {0x10030, 0x00079D19},
+ {0x10030, 0x0007A0DF},
+ {0x10030, 0x0007A4D9},
+ {0x10030, 0x0007A8D3},
+ {0x10030, 0x0007AC99},
+ {0x10030, 0x0007B05F},
+ {0x10030, 0x0007B459},
+ {0x10030, 0x0007B81F},
+ {0x10030, 0x0007BC19},
+ {0x10030, 0x0007C013},
+ {0x10030, 0x0007C40D},
{0xA0000000, 0x00000000},
{0x10030, 0x000001EF},
{0x10030, 0x000005E9},
@@ -22782,6 +25380,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x000338CC},
{0x10030, 0x00033C09},
{0x10030, 0x00034006},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280E7},
+ {0x10030, 0x000284E4},
+ {0x10030, 0x000288E1},
+ {0x10030, 0x00028CDE},
+ {0x10030, 0x000290DB},
+ {0x10030, 0x000294D8},
+ {0x10030, 0x000298D5},
+ {0x10030, 0x00029CD2},
+ {0x10030, 0x0002A0CF},
+ {0x10030, 0x0002A40C},
+ {0x10030, 0x0002A809},
+ {0x10030, 0x0002AC06},
+ {0x10030, 0x0002B003},
+ {0x10030, 0x0002B400},
+ {0x10030, 0x0002B800},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300E7},
+ {0x10030, 0x000304E4},
+ {0x10030, 0x000308E1},
+ {0x10030, 0x00030CDE},
+ {0x10030, 0x000310DB},
+ {0x10030, 0x000314D8},
+ {0x10030, 0x000318D5},
+ {0x10030, 0x00031CD2},
+ {0x10030, 0x000320CF},
+ {0x10030, 0x000324CC},
+ {0x10030, 0x00032809},
+ {0x10030, 0x00032C06},
+ {0x10030, 0x00033003},
+ {0x10030, 0x00033400},
+ {0x10030, 0x00033800},
+ {0x10030, 0x00033C00},
+ {0x10030, 0x00034000},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x000200E8},
+ {0x10030, 0x000204E5},
+ {0x10030, 0x000208E2},
+ {0x10030, 0x00020CDF},
+ {0x10030, 0x000210DC},
+ {0x10030, 0x000214D9},
+ {0x10030, 0x000218D6},
+ {0x10030, 0x00021CD3},
+ {0x10030, 0x000220D0},
+ {0x10030, 0x0002240D},
+ {0x10030, 0x0002280A},
+ {0x10030, 0x00022C07},
+ {0x10030, 0x00023004},
+ {0x10030, 0x00023401},
+ {0x10030, 0x00023800},
+ {0x10030, 0x00023C00},
+ {0x10030, 0x00024000},
+ {0x10030, 0x000280E7},
+ {0x10030, 0x000284E4},
+ {0x10030, 0x000288E1},
+ {0x10030, 0x00028CDE},
+ {0x10030, 0x000290DB},
+ {0x10030, 0x000294D8},
+ {0x10030, 0x000298D5},
+ {0x10030, 0x00029CD2},
+ {0x10030, 0x0002A0CF},
+ {0x10030, 0x0002A40C},
+ {0x10030, 0x0002A809},
+ {0x10030, 0x0002AC06},
+ {0x10030, 0x0002B003},
+ {0x10030, 0x0002B400},
+ {0x10030, 0x0002B800},
+ {0x10030, 0x0002BC00},
+ {0x10030, 0x0002C000},
+ {0x10030, 0x000300E7},
+ {0x10030, 0x000304E4},
+ {0x10030, 0x000308E1},
+ {0x10030, 0x00030CDE},
+ {0x10030, 0x000310DB},
+ {0x10030, 0x000314D8},
+ {0x10030, 0x000318D5},
+ {0x10030, 0x00031CD2},
+ {0x10030, 0x000320CF},
+ {0x10030, 0x000324CC},
+ {0x10030, 0x00032809},
+ {0x10030, 0x00032C06},
+ {0x10030, 0x00033003},
+ {0x10030, 0x00033400},
+ {0x10030, 0x00033800},
+ {0x10030, 0x00033C00},
+ {0x10030, 0x00034000},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x000200FA},
{0x10030, 0x000204F7},
@@ -23329,6 +26031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23373,6 +26079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23429,6 +26139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23473,6 +26187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23529,6 +26247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23573,6 +26295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23629,6 +26355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23673,6 +26403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23729,6 +26463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23773,6 +26511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23829,6 +26571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23873,6 +26619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23929,6 +26679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -23973,6 +26727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24029,6 +26787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24073,6 +26835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24129,6 +26895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24173,6 +26943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24229,6 +27003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24273,6 +27051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24329,6 +27111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24373,6 +27159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24429,6 +27219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24473,6 +27267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24529,6 +27327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24573,6 +27375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24629,6 +27435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24673,6 +27483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24729,6 +27543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24773,6 +27591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24829,6 +27651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24873,6 +27699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24929,6 +27759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -24973,6 +27807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25029,6 +27867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25073,6 +27915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25129,6 +27975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25173,6 +28023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25229,6 +28083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25273,6 +28131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25329,6 +28191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25373,6 +28239,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25429,6 +28299,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25473,6 +28347,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25529,6 +28407,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25573,6 +28455,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25629,6 +28515,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25673,6 +28563,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25729,6 +28623,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25773,6 +28671,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25829,6 +28731,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25873,6 +28779,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25929,6 +28839,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -25973,6 +28887,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26029,6 +28947,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26073,6 +28995,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x00000003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x03F, 0x00008002},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x03F, 0x00000003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26157,6 +29083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00025003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00025003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00025003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26207,6 +29137,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0002D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0002D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0002D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26257,6 +29191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x00035003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00035003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00035003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26307,6 +29245,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x10030, 0x0003D003},
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0003D003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0003D003},
{0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -26370,6 +29312,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00065003},
+ {0x10030, 0x00066003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00065003},
{0x10030, 0x00066003},
@@ -26440,6 +29388,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0006D003},
+ {0x10030, 0x0006E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0006D003},
{0x10030, 0x0006E003},
@@ -26510,6 +29464,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x00075003},
+ {0x10030, 0x00076003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x00075003},
{0x10030, 0x00076003},
@@ -26580,6 +29540,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x90070001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
+ {0x90150001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
+ {0x90160001, 0x00000000}, {0x40000000, 0x00000000},
+ {0x10030, 0x0007D003},
+ {0x10030, 0x0007E003},
{0x90320001, 0x00000000}, {0x40000000, 0x00000000},
{0x10030, 0x0007D003},
{0x10030, 0x0007E003},
@@ -26621,7 +29587,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
{0x03F, 0x0000000A},
{0x0ED, 0x00000000},
{0x100EE, 0x00000000},
- {0x0FE, 0x00000048},
+ {0x0FE, 0x00000063},
};
static const struct rtw89_reg2_def rtw89_8852c_phy_nctl_regs[] = {
@@ -28430,11 +31396,11 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = {
{ 2, 0, 1, 4, 4, 0x383c4040, },
{ 2, 0, 2, 0, 4, 0x40404040, },
{ 2, 0, 2, 4, 4, 0x34383c40, },
- { 2, 0, 2, 8, 4, 0x24282c30, },
+ { 2, 0, 2, 8, 4, 0x20282c30, },
{ 2, 0, 3, 0, 4, 0x40404040, },
{ 2, 1, 2, 0, 4, 0x40404040, },
{ 2, 1, 2, 4, 4, 0x34383c40, },
- { 2, 1, 2, 8, 4, 0x24282c30, },
+ { 2, 1, 2, 8, 4, 0x20282c30, },
{ 2, 1, 3, 0, 4, 0x40404040, },
{ 2, 0, 4, 0, 4, 0x00000000, },
};
@@ -28559,35 +31525,53 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = {
3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5
};
-const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM] = {
[0][0][RTW89_ACMA] = 0,
+ [0][0][RTW89_CHILE] = 0,
[0][0][RTW89_CN] = 0,
[0][0][RTW89_ETSI] = 0,
[0][0][RTW89_FCC] = 1,
[0][0][RTW89_IC] = 1,
[0][0][RTW89_KCC] = 0,
+ [0][0][RTW89_MEXICO] = 1,
[0][0][RTW89_MKK] = 0,
+ [0][0][RTW89_QATAR] = 0,
[0][0][RTW89_UK] = 0,
+ [0][0][RTW89_UKRAINE] = 0,
[0][1][RTW89_ACMA] = 0,
+ [0][1][RTW89_CHILE] = 0,
[0][1][RTW89_CN] = 0,
[0][1][RTW89_ETSI] = 0,
[0][1][RTW89_FCC] = 3,
[0][1][RTW89_IC] = 3,
[0][1][RTW89_KCC] = 0,
+ [0][1][RTW89_MEXICO] = 3,
[0][1][RTW89_MKK] = 0,
+ [0][1][RTW89_QATAR] = 0,
[0][1][RTW89_UK] = 0,
+ [0][1][RTW89_UKRAINE] = 0,
[1][1][RTW89_ACMA] = 0,
+ [1][1][RTW89_CHILE] = 0,
[1][1][RTW89_CN] = 0,
[1][1][RTW89_ETSI] = 0,
[1][1][RTW89_FCC] = 3,
[1][1][RTW89_IC] = 3,
[1][1][RTW89_KCC] = 0,
+ [1][1][RTW89_MEXICO] = 3,
[1][1][RTW89_MKK] = 0,
+ [1][1][RTW89_QATAR] = 0,
[1][1][RTW89_UK] = 0,
+ [1][1][RTW89_UKRAINE] = 0,
+ [2][1][RTW89_ACMA] = 0,
+ [2][1][RTW89_CHILE] = 0,
[2][1][RTW89_ETSI] = 0,
[2][1][RTW89_FCC] = 0,
+ [2][1][RTW89_IC] = 0,
[2][1][RTW89_KCC] = 0,
+ [2][1][RTW89_MKK] = 0,
+ [2][1][RTW89_QATAR] = 0,
+ [2][1][RTW89_UK] = 0,
};
static
@@ -28770,6 +31754,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][0] = 60,
[0][0][0][0][RTW89_CN][0] = 58,
[0][0][0][0][RTW89_UK][0] = 60,
+ [0][0][0][0][RTW89_MEXICO][0] = 76,
+ [0][0][0][0][RTW89_UKRAINE][0] = 60,
+ [0][0][0][0][RTW89_CHILE][0] = 76,
+ [0][0][0][0][RTW89_QATAR][0] = 60,
[0][0][0][0][RTW89_FCC][1] = 76,
[0][0][0][0][RTW89_ETSI][1] = 60,
[0][0][0][0][RTW89_MKK][1] = 68,
@@ -28778,6 +31766,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][1] = 60,
[0][0][0][0][RTW89_CN][1] = 58,
[0][0][0][0][RTW89_UK][1] = 60,
+ [0][0][0][0][RTW89_MEXICO][1] = 76,
+ [0][0][0][0][RTW89_UKRAINE][1] = 60,
+ [0][0][0][0][RTW89_CHILE][1] = 68,
+ [0][0][0][0][RTW89_QATAR][1] = 60,
[0][0][0][0][RTW89_FCC][2] = 76,
[0][0][0][0][RTW89_ETSI][2] = 60,
[0][0][0][0][RTW89_MKK][2] = 68,
@@ -28786,6 +31778,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][2] = 60,
[0][0][0][0][RTW89_CN][2] = 58,
[0][0][0][0][RTW89_UK][2] = 60,
+ [0][0][0][0][RTW89_MEXICO][2] = 76,
+ [0][0][0][0][RTW89_UKRAINE][2] = 60,
+ [0][0][0][0][RTW89_CHILE][2] = 68,
+ [0][0][0][0][RTW89_QATAR][2] = 60,
[0][0][0][0][RTW89_FCC][3] = 76,
[0][0][0][0][RTW89_ETSI][3] = 60,
[0][0][0][0][RTW89_MKK][3] = 68,
@@ -28794,6 +31790,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][3] = 60,
[0][0][0][0][RTW89_CN][3] = 58,
[0][0][0][0][RTW89_UK][3] = 60,
+ [0][0][0][0][RTW89_MEXICO][3] = 76,
+ [0][0][0][0][RTW89_UKRAINE][3] = 60,
+ [0][0][0][0][RTW89_CHILE][3] = 68,
+ [0][0][0][0][RTW89_QATAR][3] = 60,
[0][0][0][0][RTW89_FCC][4] = 76,
[0][0][0][0][RTW89_ETSI][4] = 60,
[0][0][0][0][RTW89_MKK][4] = 68,
@@ -28802,6 +31802,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][4] = 60,
[0][0][0][0][RTW89_CN][4] = 58,
[0][0][0][0][RTW89_UK][4] = 60,
+ [0][0][0][0][RTW89_MEXICO][4] = 76,
+ [0][0][0][0][RTW89_UKRAINE][4] = 60,
+ [0][0][0][0][RTW89_CHILE][4] = 68,
+ [0][0][0][0][RTW89_QATAR][4] = 60,
[0][0][0][0][RTW89_FCC][5] = 76,
[0][0][0][0][RTW89_ETSI][5] = 60,
[0][0][0][0][RTW89_MKK][5] = 68,
@@ -28810,6 +31814,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][5] = 60,
[0][0][0][0][RTW89_CN][5] = 58,
[0][0][0][0][RTW89_UK][5] = 60,
+ [0][0][0][0][RTW89_MEXICO][5] = 76,
+ [0][0][0][0][RTW89_UKRAINE][5] = 60,
+ [0][0][0][0][RTW89_CHILE][5] = 76,
+ [0][0][0][0][RTW89_QATAR][5] = 60,
[0][0][0][0][RTW89_FCC][6] = 76,
[0][0][0][0][RTW89_ETSI][6] = 60,
[0][0][0][0][RTW89_MKK][6] = 68,
@@ -28818,6 +31826,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][6] = 60,
[0][0][0][0][RTW89_CN][6] = 58,
[0][0][0][0][RTW89_UK][6] = 60,
+ [0][0][0][0][RTW89_MEXICO][6] = 76,
+ [0][0][0][0][RTW89_UKRAINE][6] = 60,
+ [0][0][0][0][RTW89_CHILE][6] = 76,
+ [0][0][0][0][RTW89_QATAR][6] = 60,
[0][0][0][0][RTW89_FCC][7] = 76,
[0][0][0][0][RTW89_ETSI][7] = 60,
[0][0][0][0][RTW89_MKK][7] = 68,
@@ -28826,6 +31838,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][7] = 60,
[0][0][0][0][RTW89_CN][7] = 58,
[0][0][0][0][RTW89_UK][7] = 60,
+ [0][0][0][0][RTW89_MEXICO][7] = 76,
+ [0][0][0][0][RTW89_UKRAINE][7] = 60,
+ [0][0][0][0][RTW89_CHILE][7] = 76,
+ [0][0][0][0][RTW89_QATAR][7] = 60,
[0][0][0][0][RTW89_FCC][8] = 76,
[0][0][0][0][RTW89_ETSI][8] = 60,
[0][0][0][0][RTW89_MKK][8] = 68,
@@ -28834,6 +31850,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][8] = 60,
[0][0][0][0][RTW89_CN][8] = 58,
[0][0][0][0][RTW89_UK][8] = 60,
+ [0][0][0][0][RTW89_MEXICO][8] = 76,
+ [0][0][0][0][RTW89_UKRAINE][8] = 60,
+ [0][0][0][0][RTW89_CHILE][8] = 76,
+ [0][0][0][0][RTW89_QATAR][8] = 60,
[0][0][0][0][RTW89_FCC][9] = 76,
[0][0][0][0][RTW89_ETSI][9] = 60,
[0][0][0][0][RTW89_MKK][9] = 68,
@@ -28842,6 +31862,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][9] = 60,
[0][0][0][0][RTW89_CN][9] = 58,
[0][0][0][0][RTW89_UK][9] = 60,
+ [0][0][0][0][RTW89_MEXICO][9] = 76,
+ [0][0][0][0][RTW89_UKRAINE][9] = 60,
+ [0][0][0][0][RTW89_CHILE][9] = 76,
+ [0][0][0][0][RTW89_QATAR][9] = 60,
[0][0][0][0][RTW89_FCC][10] = 76,
[0][0][0][0][RTW89_ETSI][10] = 60,
[0][0][0][0][RTW89_MKK][10] = 68,
@@ -28850,6 +31874,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][10] = 60,
[0][0][0][0][RTW89_CN][10] = 58,
[0][0][0][0][RTW89_UK][10] = 60,
+ [0][0][0][0][RTW89_MEXICO][10] = 76,
+ [0][0][0][0][RTW89_UKRAINE][10] = 60,
+ [0][0][0][0][RTW89_CHILE][10] = 76,
+ [0][0][0][0][RTW89_QATAR][10] = 60,
[0][0][0][0][RTW89_FCC][11] = 58,
[0][0][0][0][RTW89_ETSI][11] = 60,
[0][0][0][0][RTW89_MKK][11] = 68,
@@ -28858,6 +31886,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][11] = 60,
[0][0][0][0][RTW89_CN][11] = 58,
[0][0][0][0][RTW89_UK][11] = 60,
+ [0][0][0][0][RTW89_MEXICO][11] = 58,
+ [0][0][0][0][RTW89_UKRAINE][11] = 60,
+ [0][0][0][0][RTW89_CHILE][11] = 58,
+ [0][0][0][0][RTW89_QATAR][11] = 60,
[0][0][0][0][RTW89_FCC][12] = 46,
[0][0][0][0][RTW89_ETSI][12] = 60,
[0][0][0][0][RTW89_MKK][12] = 68,
@@ -28866,6 +31898,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][12] = 60,
[0][0][0][0][RTW89_CN][12] = 58,
[0][0][0][0][RTW89_UK][12] = 60,
+ [0][0][0][0][RTW89_MEXICO][12] = 46,
+ [0][0][0][0][RTW89_UKRAINE][12] = 60,
+ [0][0][0][0][RTW89_CHILE][12] = 46,
+ [0][0][0][0][RTW89_QATAR][12] = 60,
[0][0][0][0][RTW89_FCC][13] = 127,
[0][0][0][0][RTW89_ETSI][13] = 127,
[0][0][0][0][RTW89_MKK][13] = 72,
@@ -28874,6 +31910,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][0][0][RTW89_ACMA][13] = 127,
[0][0][0][0][RTW89_CN][13] = 127,
[0][0][0][0][RTW89_UK][13] = 127,
+ [0][0][0][0][RTW89_MEXICO][13] = 127,
+ [0][0][0][0][RTW89_UKRAINE][13] = 127,
+ [0][0][0][0][RTW89_CHILE][13] = 127,
+ [0][0][0][0][RTW89_QATAR][13] = 127,
[0][1][0][0][RTW89_FCC][0] = 76,
[0][1][0][0][RTW89_ETSI][0] = 48,
[0][1][0][0][RTW89_MKK][0] = 58,
@@ -28882,6 +31922,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][0] = 48,
[0][1][0][0][RTW89_CN][0] = 42,
[0][1][0][0][RTW89_UK][0] = 48,
+ [0][1][0][0][RTW89_MEXICO][0] = 76,
+ [0][1][0][0][RTW89_UKRAINE][0] = 48,
+ [0][1][0][0][RTW89_CHILE][0] = 76,
+ [0][1][0][0][RTW89_QATAR][0] = 48,
[0][1][0][0][RTW89_FCC][1] = 76,
[0][1][0][0][RTW89_ETSI][1] = 48,
[0][1][0][0][RTW89_MKK][1] = 58,
@@ -28890,6 +31934,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][1] = 48,
[0][1][0][0][RTW89_CN][1] = 42,
[0][1][0][0][RTW89_UK][1] = 48,
+ [0][1][0][0][RTW89_MEXICO][1] = 76,
+ [0][1][0][0][RTW89_UKRAINE][1] = 48,
+ [0][1][0][0][RTW89_CHILE][1] = 54,
+ [0][1][0][0][RTW89_QATAR][1] = 48,
[0][1][0][0][RTW89_FCC][2] = 76,
[0][1][0][0][RTW89_ETSI][2] = 48,
[0][1][0][0][RTW89_MKK][2] = 58,
@@ -28898,6 +31946,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][2] = 48,
[0][1][0][0][RTW89_CN][2] = 42,
[0][1][0][0][RTW89_UK][2] = 48,
+ [0][1][0][0][RTW89_MEXICO][2] = 76,
+ [0][1][0][0][RTW89_UKRAINE][2] = 48,
+ [0][1][0][0][RTW89_CHILE][2] = 54,
+ [0][1][0][0][RTW89_QATAR][2] = 48,
[0][1][0][0][RTW89_FCC][3] = 76,
[0][1][0][0][RTW89_ETSI][3] = 48,
[0][1][0][0][RTW89_MKK][3] = 58,
@@ -28906,6 +31958,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][3] = 48,
[0][1][0][0][RTW89_CN][3] = 42,
[0][1][0][0][RTW89_UK][3] = 48,
+ [0][1][0][0][RTW89_MEXICO][3] = 76,
+ [0][1][0][0][RTW89_UKRAINE][3] = 48,
+ [0][1][0][0][RTW89_CHILE][3] = 54,
+ [0][1][0][0][RTW89_QATAR][3] = 48,
[0][1][0][0][RTW89_FCC][4] = 76,
[0][1][0][0][RTW89_ETSI][4] = 48,
[0][1][0][0][RTW89_MKK][4] = 58,
@@ -28914,6 +31970,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][4] = 48,
[0][1][0][0][RTW89_CN][4] = 42,
[0][1][0][0][RTW89_UK][4] = 48,
+ [0][1][0][0][RTW89_MEXICO][4] = 76,
+ [0][1][0][0][RTW89_UKRAINE][4] = 48,
+ [0][1][0][0][RTW89_CHILE][4] = 54,
+ [0][1][0][0][RTW89_QATAR][4] = 48,
[0][1][0][0][RTW89_FCC][5] = 76,
[0][1][0][0][RTW89_ETSI][5] = 48,
[0][1][0][0][RTW89_MKK][5] = 58,
@@ -28922,6 +31982,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][5] = 48,
[0][1][0][0][RTW89_CN][5] = 42,
[0][1][0][0][RTW89_UK][5] = 48,
+ [0][1][0][0][RTW89_MEXICO][5] = 76,
+ [0][1][0][0][RTW89_UKRAINE][5] = 48,
+ [0][1][0][0][RTW89_CHILE][5] = 76,
+ [0][1][0][0][RTW89_QATAR][5] = 48,
[0][1][0][0][RTW89_FCC][6] = 76,
[0][1][0][0][RTW89_ETSI][6] = 48,
[0][1][0][0][RTW89_MKK][6] = 58,
@@ -28930,6 +31994,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][6] = 48,
[0][1][0][0][RTW89_CN][6] = 42,
[0][1][0][0][RTW89_UK][6] = 48,
+ [0][1][0][0][RTW89_MEXICO][6] = 76,
+ [0][1][0][0][RTW89_UKRAINE][6] = 48,
+ [0][1][0][0][RTW89_CHILE][6] = 76,
+ [0][1][0][0][RTW89_QATAR][6] = 48,
[0][1][0][0][RTW89_FCC][7] = 76,
[0][1][0][0][RTW89_ETSI][7] = 48,
[0][1][0][0][RTW89_MKK][7] = 58,
@@ -28938,6 +32006,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][7] = 48,
[0][1][0][0][RTW89_CN][7] = 42,
[0][1][0][0][RTW89_UK][7] = 48,
+ [0][1][0][0][RTW89_MEXICO][7] = 76,
+ [0][1][0][0][RTW89_UKRAINE][7] = 48,
+ [0][1][0][0][RTW89_CHILE][7] = 76,
+ [0][1][0][0][RTW89_QATAR][7] = 48,
[0][1][0][0][RTW89_FCC][8] = 76,
[0][1][0][0][RTW89_ETSI][8] = 48,
[0][1][0][0][RTW89_MKK][8] = 58,
@@ -28946,6 +32018,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][8] = 48,
[0][1][0][0][RTW89_CN][8] = 42,
[0][1][0][0][RTW89_UK][8] = 48,
+ [0][1][0][0][RTW89_MEXICO][8] = 76,
+ [0][1][0][0][RTW89_UKRAINE][8] = 48,
+ [0][1][0][0][RTW89_CHILE][8] = 76,
+ [0][1][0][0][RTW89_QATAR][8] = 48,
[0][1][0][0][RTW89_FCC][9] = 70,
[0][1][0][0][RTW89_ETSI][9] = 48,
[0][1][0][0][RTW89_MKK][9] = 58,
@@ -28954,6 +32030,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][9] = 48,
[0][1][0][0][RTW89_CN][9] = 42,
[0][1][0][0][RTW89_UK][9] = 48,
+ [0][1][0][0][RTW89_MEXICO][9] = 70,
+ [0][1][0][0][RTW89_UKRAINE][9] = 48,
+ [0][1][0][0][RTW89_CHILE][9] = 70,
+ [0][1][0][0][RTW89_QATAR][9] = 48,
[0][1][0][0][RTW89_FCC][10] = 72,
[0][1][0][0][RTW89_ETSI][10] = 48,
[0][1][0][0][RTW89_MKK][10] = 58,
@@ -28962,6 +32042,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][10] = 48,
[0][1][0][0][RTW89_CN][10] = 42,
[0][1][0][0][RTW89_UK][10] = 48,
+ [0][1][0][0][RTW89_MEXICO][10] = 72,
+ [0][1][0][0][RTW89_UKRAINE][10] = 48,
+ [0][1][0][0][RTW89_CHILE][10] = 72,
+ [0][1][0][0][RTW89_QATAR][10] = 48,
[0][1][0][0][RTW89_FCC][11] = 44,
[0][1][0][0][RTW89_ETSI][11] = 48,
[0][1][0][0][RTW89_MKK][11] = 58,
@@ -28970,6 +32054,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][11] = 48,
[0][1][0][0][RTW89_CN][11] = 42,
[0][1][0][0][RTW89_UK][11] = 48,
+ [0][1][0][0][RTW89_MEXICO][11] = 44,
+ [0][1][0][0][RTW89_UKRAINE][11] = 48,
+ [0][1][0][0][RTW89_CHILE][11] = 44,
+ [0][1][0][0][RTW89_QATAR][11] = 48,
[0][1][0][0][RTW89_FCC][12] = 18,
[0][1][0][0][RTW89_ETSI][12] = 48,
[0][1][0][0][RTW89_MKK][12] = 58,
@@ -28978,6 +32066,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][12] = 48,
[0][1][0][0][RTW89_CN][12] = 42,
[0][1][0][0][RTW89_UK][12] = 48,
+ [0][1][0][0][RTW89_MEXICO][12] = 18,
+ [0][1][0][0][RTW89_UKRAINE][12] = 48,
+ [0][1][0][0][RTW89_CHILE][12] = 18,
+ [0][1][0][0][RTW89_QATAR][12] = 48,
[0][1][0][0][RTW89_FCC][13] = 127,
[0][1][0][0][RTW89_ETSI][13] = 127,
[0][1][0][0][RTW89_MKK][13] = 60,
@@ -28986,6 +32078,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][0][0][RTW89_ACMA][13] = 127,
[0][1][0][0][RTW89_CN][13] = 127,
[0][1][0][0][RTW89_UK][13] = 127,
+ [0][1][0][0][RTW89_MEXICO][13] = 127,
+ [0][1][0][0][RTW89_UKRAINE][13] = 127,
+ [0][1][0][0][RTW89_CHILE][13] = 127,
+ [0][1][0][0][RTW89_QATAR][13] = 127,
[1][0][0][0][RTW89_FCC][0] = 127,
[1][0][0][0][RTW89_ETSI][0] = 127,
[1][0][0][0][RTW89_MKK][0] = 127,
@@ -28994,6 +32090,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][0] = 127,
[1][0][0][0][RTW89_CN][0] = 127,
[1][0][0][0][RTW89_UK][0] = 127,
+ [1][0][0][0][RTW89_MEXICO][0] = 127,
+ [1][0][0][0][RTW89_UKRAINE][0] = 127,
+ [1][0][0][0][RTW89_CHILE][0] = 127,
+ [1][0][0][0][RTW89_QATAR][0] = 127,
[1][0][0][0][RTW89_FCC][1] = 127,
[1][0][0][0][RTW89_ETSI][1] = 127,
[1][0][0][0][RTW89_MKK][1] = 127,
@@ -29002,6 +32102,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][1] = 127,
[1][0][0][0][RTW89_CN][1] = 127,
[1][0][0][0][RTW89_UK][1] = 127,
+ [1][0][0][0][RTW89_MEXICO][1] = 127,
+ [1][0][0][0][RTW89_UKRAINE][1] = 127,
+ [1][0][0][0][RTW89_CHILE][1] = 127,
+ [1][0][0][0][RTW89_QATAR][1] = 127,
[1][0][0][0][RTW89_FCC][2] = 44,
[1][0][0][0][RTW89_ETSI][2] = 60,
[1][0][0][0][RTW89_MKK][2] = 66,
@@ -29010,6 +32114,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][2] = 60,
[1][0][0][0][RTW89_CN][2] = 58,
[1][0][0][0][RTW89_UK][2] = 60,
+ [1][0][0][0][RTW89_MEXICO][2] = 44,
+ [1][0][0][0][RTW89_UKRAINE][2] = 60,
+ [1][0][0][0][RTW89_CHILE][2] = 44,
+ [1][0][0][0][RTW89_QATAR][2] = 60,
[1][0][0][0][RTW89_FCC][3] = 60,
[1][0][0][0][RTW89_ETSI][3] = 60,
[1][0][0][0][RTW89_MKK][3] = 66,
@@ -29018,6 +32126,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][3] = 60,
[1][0][0][0][RTW89_CN][3] = 58,
[1][0][0][0][RTW89_UK][3] = 60,
+ [1][0][0][0][RTW89_MEXICO][3] = 60,
+ [1][0][0][0][RTW89_UKRAINE][3] = 60,
+ [1][0][0][0][RTW89_CHILE][3] = 60,
+ [1][0][0][0][RTW89_QATAR][3] = 60,
[1][0][0][0][RTW89_FCC][4] = 60,
[1][0][0][0][RTW89_ETSI][4] = 60,
[1][0][0][0][RTW89_MKK][4] = 66,
@@ -29026,6 +32138,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][4] = 60,
[1][0][0][0][RTW89_CN][4] = 58,
[1][0][0][0][RTW89_UK][4] = 60,
+ [1][0][0][0][RTW89_MEXICO][4] = 60,
+ [1][0][0][0][RTW89_UKRAINE][4] = 60,
+ [1][0][0][0][RTW89_CHILE][4] = 60,
+ [1][0][0][0][RTW89_QATAR][4] = 60,
[1][0][0][0][RTW89_FCC][5] = 62,
[1][0][0][0][RTW89_ETSI][5] = 60,
[1][0][0][0][RTW89_MKK][5] = 66,
@@ -29034,6 +32150,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][5] = 60,
[1][0][0][0][RTW89_CN][5] = 58,
[1][0][0][0][RTW89_UK][5] = 60,
+ [1][0][0][0][RTW89_MEXICO][5] = 62,
+ [1][0][0][0][RTW89_UKRAINE][5] = 60,
+ [1][0][0][0][RTW89_CHILE][5] = 62,
+ [1][0][0][0][RTW89_QATAR][5] = 60,
[1][0][0][0][RTW89_FCC][6] = 46,
[1][0][0][0][RTW89_ETSI][6] = 60,
[1][0][0][0][RTW89_MKK][6] = 66,
@@ -29042,6 +32162,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][6] = 60,
[1][0][0][0][RTW89_CN][6] = 58,
[1][0][0][0][RTW89_UK][6] = 60,
+ [1][0][0][0][RTW89_MEXICO][6] = 46,
+ [1][0][0][0][RTW89_UKRAINE][6] = 60,
+ [1][0][0][0][RTW89_CHILE][6] = 46,
+ [1][0][0][0][RTW89_QATAR][6] = 60,
[1][0][0][0][RTW89_FCC][7] = 46,
[1][0][0][0][RTW89_ETSI][7] = 60,
[1][0][0][0][RTW89_MKK][7] = 66,
@@ -29050,6 +32174,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][7] = 60,
[1][0][0][0][RTW89_CN][7] = 58,
[1][0][0][0][RTW89_UK][7] = 60,
+ [1][0][0][0][RTW89_MEXICO][7] = 46,
+ [1][0][0][0][RTW89_UKRAINE][7] = 60,
+ [1][0][0][0][RTW89_CHILE][7] = 46,
+ [1][0][0][0][RTW89_QATAR][7] = 60,
[1][0][0][0][RTW89_FCC][8] = 28,
[1][0][0][0][RTW89_ETSI][8] = 60,
[1][0][0][0][RTW89_MKK][8] = 66,
@@ -29058,6 +32186,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][8] = 60,
[1][0][0][0][RTW89_CN][8] = 58,
[1][0][0][0][RTW89_UK][8] = 60,
+ [1][0][0][0][RTW89_MEXICO][8] = 28,
+ [1][0][0][0][RTW89_UKRAINE][8] = 60,
+ [1][0][0][0][RTW89_CHILE][8] = 28,
+ [1][0][0][0][RTW89_QATAR][8] = 60,
[1][0][0][0][RTW89_FCC][9] = 26,
[1][0][0][0][RTW89_ETSI][9] = 60,
[1][0][0][0][RTW89_MKK][9] = 66,
@@ -29066,6 +32198,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][9] = 60,
[1][0][0][0][RTW89_CN][9] = 58,
[1][0][0][0][RTW89_UK][9] = 60,
+ [1][0][0][0][RTW89_MEXICO][9] = 26,
+ [1][0][0][0][RTW89_UKRAINE][9] = 60,
+ [1][0][0][0][RTW89_CHILE][9] = 26,
+ [1][0][0][0][RTW89_QATAR][9] = 60,
[1][0][0][0][RTW89_FCC][10] = 26,
[1][0][0][0][RTW89_ETSI][10] = 60,
[1][0][0][0][RTW89_MKK][10] = 66,
@@ -29074,6 +32210,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][10] = 60,
[1][0][0][0][RTW89_CN][10] = 58,
[1][0][0][0][RTW89_UK][10] = 60,
+ [1][0][0][0][RTW89_MEXICO][10] = 26,
+ [1][0][0][0][RTW89_UKRAINE][10] = 60,
+ [1][0][0][0][RTW89_CHILE][10] = 26,
+ [1][0][0][0][RTW89_QATAR][10] = 60,
[1][0][0][0][RTW89_FCC][11] = 127,
[1][0][0][0][RTW89_ETSI][11] = 127,
[1][0][0][0][RTW89_MKK][11] = 127,
@@ -29082,6 +32222,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][11] = 127,
[1][0][0][0][RTW89_CN][11] = 127,
[1][0][0][0][RTW89_UK][11] = 127,
+ [1][0][0][0][RTW89_MEXICO][11] = 127,
+ [1][0][0][0][RTW89_UKRAINE][11] = 127,
+ [1][0][0][0][RTW89_CHILE][11] = 127,
+ [1][0][0][0][RTW89_QATAR][11] = 127,
[1][0][0][0][RTW89_FCC][12] = 127,
[1][0][0][0][RTW89_ETSI][12] = 127,
[1][0][0][0][RTW89_MKK][12] = 127,
@@ -29090,6 +32234,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][12] = 127,
[1][0][0][0][RTW89_CN][12] = 127,
[1][0][0][0][RTW89_UK][12] = 127,
+ [1][0][0][0][RTW89_MEXICO][12] = 127,
+ [1][0][0][0][RTW89_UKRAINE][12] = 127,
+ [1][0][0][0][RTW89_CHILE][12] = 127,
+ [1][0][0][0][RTW89_QATAR][12] = 127,
[1][0][0][0][RTW89_FCC][13] = 127,
[1][0][0][0][RTW89_ETSI][13] = 127,
[1][0][0][0][RTW89_MKK][13] = 127,
@@ -29098,6 +32246,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][0][0][RTW89_ACMA][13] = 127,
[1][0][0][0][RTW89_CN][13] = 127,
[1][0][0][0][RTW89_UK][13] = 127,
+ [1][0][0][0][RTW89_MEXICO][13] = 127,
+ [1][0][0][0][RTW89_UKRAINE][13] = 127,
+ [1][0][0][0][RTW89_CHILE][13] = 127,
+ [1][0][0][0][RTW89_QATAR][13] = 127,
[1][1][0][0][RTW89_FCC][0] = 127,
[1][1][0][0][RTW89_ETSI][0] = 127,
[1][1][0][0][RTW89_MKK][0] = 127,
@@ -29106,6 +32258,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][0] = 127,
[1][1][0][0][RTW89_CN][0] = 127,
[1][1][0][0][RTW89_UK][0] = 127,
+ [1][1][0][0][RTW89_MEXICO][0] = 127,
+ [1][1][0][0][RTW89_UKRAINE][0] = 127,
+ [1][1][0][0][RTW89_CHILE][0] = 127,
+ [1][1][0][0][RTW89_QATAR][0] = 127,
[1][1][0][0][RTW89_FCC][1] = 127,
[1][1][0][0][RTW89_ETSI][1] = 127,
[1][1][0][0][RTW89_MKK][1] = 127,
@@ -29114,6 +32270,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][1] = 127,
[1][1][0][0][RTW89_CN][1] = 127,
[1][1][0][0][RTW89_UK][1] = 127,
+ [1][1][0][0][RTW89_MEXICO][1] = 127,
+ [1][1][0][0][RTW89_UKRAINE][1] = 127,
+ [1][1][0][0][RTW89_CHILE][1] = 127,
+ [1][1][0][0][RTW89_QATAR][1] = 127,
[1][1][0][0][RTW89_FCC][2] = 46,
[1][1][0][0][RTW89_ETSI][2] = 48,
[1][1][0][0][RTW89_MKK][2] = 58,
@@ -29122,6 +32282,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][2] = 48,
[1][1][0][0][RTW89_CN][2] = 46,
[1][1][0][0][RTW89_UK][2] = 48,
+ [1][1][0][0][RTW89_MEXICO][2] = 46,
+ [1][1][0][0][RTW89_UKRAINE][2] = 48,
+ [1][1][0][0][RTW89_CHILE][2] = 46,
+ [1][1][0][0][RTW89_QATAR][2] = 48,
[1][1][0][0][RTW89_FCC][3] = 46,
[1][1][0][0][RTW89_ETSI][3] = 48,
[1][1][0][0][RTW89_MKK][3] = 58,
@@ -29130,6 +32294,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][3] = 48,
[1][1][0][0][RTW89_CN][3] = 46,
[1][1][0][0][RTW89_UK][3] = 48,
+ [1][1][0][0][RTW89_MEXICO][3] = 46,
+ [1][1][0][0][RTW89_UKRAINE][3] = 48,
+ [1][1][0][0][RTW89_CHILE][3] = 46,
+ [1][1][0][0][RTW89_QATAR][3] = 48,
[1][1][0][0][RTW89_FCC][4] = 46,
[1][1][0][0][RTW89_ETSI][4] = 48,
[1][1][0][0][RTW89_MKK][4] = 58,
@@ -29138,6 +32306,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][4] = 48,
[1][1][0][0][RTW89_CN][4] = 46,
[1][1][0][0][RTW89_UK][4] = 48,
+ [1][1][0][0][RTW89_MEXICO][4] = 46,
+ [1][1][0][0][RTW89_UKRAINE][4] = 48,
+ [1][1][0][0][RTW89_CHILE][4] = 46,
+ [1][1][0][0][RTW89_QATAR][4] = 48,
[1][1][0][0][RTW89_FCC][5] = 48,
[1][1][0][0][RTW89_ETSI][5] = 48,
[1][1][0][0][RTW89_MKK][5] = 58,
@@ -29146,6 +32318,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][5] = 48,
[1][1][0][0][RTW89_CN][5] = 46,
[1][1][0][0][RTW89_UK][5] = 48,
+ [1][1][0][0][RTW89_MEXICO][5] = 48,
+ [1][1][0][0][RTW89_UKRAINE][5] = 48,
+ [1][1][0][0][RTW89_CHILE][5] = 48,
+ [1][1][0][0][RTW89_QATAR][5] = 48,
[1][1][0][0][RTW89_FCC][6] = 40,
[1][1][0][0][RTW89_ETSI][6] = 48,
[1][1][0][0][RTW89_MKK][6] = 58,
@@ -29154,6 +32330,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][6] = 48,
[1][1][0][0][RTW89_CN][6] = 46,
[1][1][0][0][RTW89_UK][6] = 48,
+ [1][1][0][0][RTW89_MEXICO][6] = 40,
+ [1][1][0][0][RTW89_UKRAINE][6] = 48,
+ [1][1][0][0][RTW89_CHILE][6] = 40,
+ [1][1][0][0][RTW89_QATAR][6] = 48,
[1][1][0][0][RTW89_FCC][7] = 40,
[1][1][0][0][RTW89_ETSI][7] = 48,
[1][1][0][0][RTW89_MKK][7] = 58,
@@ -29162,6 +32342,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][7] = 48,
[1][1][0][0][RTW89_CN][7] = 46,
[1][1][0][0][RTW89_UK][7] = 48,
+ [1][1][0][0][RTW89_MEXICO][7] = 40,
+ [1][1][0][0][RTW89_UKRAINE][7] = 48,
+ [1][1][0][0][RTW89_CHILE][7] = 40,
+ [1][1][0][0][RTW89_QATAR][7] = 48,
[1][1][0][0][RTW89_FCC][8] = 14,
[1][1][0][0][RTW89_ETSI][8] = 48,
[1][1][0][0][RTW89_MKK][8] = 58,
@@ -29170,6 +32354,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][8] = 48,
[1][1][0][0][RTW89_CN][8] = 46,
[1][1][0][0][RTW89_UK][8] = 48,
+ [1][1][0][0][RTW89_MEXICO][8] = 14,
+ [1][1][0][0][RTW89_UKRAINE][8] = 48,
+ [1][1][0][0][RTW89_CHILE][8] = 14,
+ [1][1][0][0][RTW89_QATAR][8] = 48,
[1][1][0][0][RTW89_FCC][9] = 14,
[1][1][0][0][RTW89_ETSI][9] = 48,
[1][1][0][0][RTW89_MKK][9] = 58,
@@ -29178,6 +32366,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][9] = 48,
[1][1][0][0][RTW89_CN][9] = 46,
[1][1][0][0][RTW89_UK][9] = 48,
+ [1][1][0][0][RTW89_MEXICO][9] = 14,
+ [1][1][0][0][RTW89_UKRAINE][9] = 48,
+ [1][1][0][0][RTW89_CHILE][9] = 14,
+ [1][1][0][0][RTW89_QATAR][9] = 48,
[1][1][0][0][RTW89_FCC][10] = 12,
[1][1][0][0][RTW89_ETSI][10] = 48,
[1][1][0][0][RTW89_MKK][10] = 56,
@@ -29186,6 +32378,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][10] = 48,
[1][1][0][0][RTW89_CN][10] = 46,
[1][1][0][0][RTW89_UK][10] = 48,
+ [1][1][0][0][RTW89_MEXICO][10] = 12,
+ [1][1][0][0][RTW89_UKRAINE][10] = 48,
+ [1][1][0][0][RTW89_CHILE][10] = 12,
+ [1][1][0][0][RTW89_QATAR][10] = 48,
[1][1][0][0][RTW89_FCC][11] = 127,
[1][1][0][0][RTW89_ETSI][11] = 127,
[1][1][0][0][RTW89_MKK][11] = 127,
@@ -29194,6 +32390,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][11] = 127,
[1][1][0][0][RTW89_CN][11] = 127,
[1][1][0][0][RTW89_UK][11] = 127,
+ [1][1][0][0][RTW89_MEXICO][11] = 127,
+ [1][1][0][0][RTW89_UKRAINE][11] = 127,
+ [1][1][0][0][RTW89_CHILE][11] = 127,
+ [1][1][0][0][RTW89_QATAR][11] = 127,
[1][1][0][0][RTW89_FCC][12] = 127,
[1][1][0][0][RTW89_ETSI][12] = 127,
[1][1][0][0][RTW89_MKK][12] = 127,
@@ -29202,6 +32402,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][12] = 127,
[1][1][0][0][RTW89_CN][12] = 127,
[1][1][0][0][RTW89_UK][12] = 127,
+ [1][1][0][0][RTW89_MEXICO][12] = 127,
+ [1][1][0][0][RTW89_UKRAINE][12] = 127,
+ [1][1][0][0][RTW89_CHILE][12] = 127,
+ [1][1][0][0][RTW89_QATAR][12] = 127,
[1][1][0][0][RTW89_FCC][13] = 127,
[1][1][0][0][RTW89_ETSI][13] = 127,
[1][1][0][0][RTW89_MKK][13] = 127,
@@ -29210,6 +32414,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][0][0][RTW89_ACMA][13] = 127,
[1][1][0][0][RTW89_CN][13] = 127,
[1][1][0][0][RTW89_UK][13] = 127,
+ [1][1][0][0][RTW89_MEXICO][13] = 127,
+ [1][1][0][0][RTW89_UKRAINE][13] = 127,
+ [1][1][0][0][RTW89_CHILE][13] = 127,
+ [1][1][0][0][RTW89_QATAR][13] = 127,
[0][0][1][0][RTW89_FCC][0] = 66,
[0][0][1][0][RTW89_ETSI][0] = 60,
[0][0][1][0][RTW89_MKK][0] = 76,
@@ -29218,6 +32426,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][0] = 60,
[0][0][1][0][RTW89_CN][0] = 58,
[0][0][1][0][RTW89_UK][0] = 60,
+ [0][0][1][0][RTW89_MEXICO][0] = 66,
+ [0][0][1][0][RTW89_UKRAINE][0] = 60,
+ [0][0][1][0][RTW89_CHILE][0] = 66,
+ [0][0][1][0][RTW89_QATAR][0] = 60,
[0][0][1][0][RTW89_FCC][1] = 68,
[0][0][1][0][RTW89_ETSI][1] = 60,
[0][0][1][0][RTW89_MKK][1] = 78,
@@ -29226,6 +32438,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][1] = 60,
[0][0][1][0][RTW89_CN][1] = 58,
[0][0][1][0][RTW89_UK][1] = 60,
+ [0][0][1][0][RTW89_MEXICO][1] = 68,
+ [0][0][1][0][RTW89_UKRAINE][1] = 60,
+ [0][0][1][0][RTW89_CHILE][1] = 68,
+ [0][0][1][0][RTW89_QATAR][1] = 60,
[0][0][1][0][RTW89_FCC][2] = 72,
[0][0][1][0][RTW89_ETSI][2] = 60,
[0][0][1][0][RTW89_MKK][2] = 78,
@@ -29234,6 +32450,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][2] = 60,
[0][0][1][0][RTW89_CN][2] = 58,
[0][0][1][0][RTW89_UK][2] = 60,
+ [0][0][1][0][RTW89_MEXICO][2] = 72,
+ [0][0][1][0][RTW89_UKRAINE][2] = 60,
+ [0][0][1][0][RTW89_CHILE][2] = 62,
+ [0][0][1][0][RTW89_QATAR][2] = 60,
[0][0][1][0][RTW89_FCC][3] = 76,
[0][0][1][0][RTW89_ETSI][3] = 60,
[0][0][1][0][RTW89_MKK][3] = 78,
@@ -29242,6 +32462,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][3] = 60,
[0][0][1][0][RTW89_CN][3] = 58,
[0][0][1][0][RTW89_UK][3] = 60,
+ [0][0][1][0][RTW89_MEXICO][3] = 76,
+ [0][0][1][0][RTW89_UKRAINE][3] = 60,
+ [0][0][1][0][RTW89_CHILE][3] = 62,
+ [0][0][1][0][RTW89_QATAR][3] = 60,
[0][0][1][0][RTW89_FCC][4] = 80,
[0][0][1][0][RTW89_ETSI][4] = 60,
[0][0][1][0][RTW89_MKK][4] = 78,
@@ -29250,6 +32474,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][4] = 60,
[0][0][1][0][RTW89_CN][4] = 58,
[0][0][1][0][RTW89_UK][4] = 60,
+ [0][0][1][0][RTW89_MEXICO][4] = 80,
+ [0][0][1][0][RTW89_UKRAINE][4] = 60,
+ [0][0][1][0][RTW89_CHILE][4] = 62,
+ [0][0][1][0][RTW89_QATAR][4] = 60,
[0][0][1][0][RTW89_FCC][5] = 80,
[0][0][1][0][RTW89_ETSI][5] = 60,
[0][0][1][0][RTW89_MKK][5] = 78,
@@ -29258,6 +32486,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][5] = 60,
[0][0][1][0][RTW89_CN][5] = 58,
[0][0][1][0][RTW89_UK][5] = 60,
+ [0][0][1][0][RTW89_MEXICO][5] = 80,
+ [0][0][1][0][RTW89_UKRAINE][5] = 60,
+ [0][0][1][0][RTW89_CHILE][5] = 80,
+ [0][0][1][0][RTW89_QATAR][5] = 60,
[0][0][1][0][RTW89_FCC][6] = 80,
[0][0][1][0][RTW89_ETSI][6] = 60,
[0][0][1][0][RTW89_MKK][6] = 76,
@@ -29266,6 +32498,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][6] = 60,
[0][0][1][0][RTW89_CN][6] = 58,
[0][0][1][0][RTW89_UK][6] = 60,
+ [0][0][1][0][RTW89_MEXICO][6] = 80,
+ [0][0][1][0][RTW89_UKRAINE][6] = 60,
+ [0][0][1][0][RTW89_CHILE][6] = 70,
+ [0][0][1][0][RTW89_QATAR][6] = 60,
[0][0][1][0][RTW89_FCC][7] = 80,
[0][0][1][0][RTW89_ETSI][7] = 60,
[0][0][1][0][RTW89_MKK][7] = 78,
@@ -29274,6 +32510,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][7] = 60,
[0][0][1][0][RTW89_CN][7] = 58,
[0][0][1][0][RTW89_UK][7] = 60,
+ [0][0][1][0][RTW89_MEXICO][7] = 80,
+ [0][0][1][0][RTW89_UKRAINE][7] = 60,
+ [0][0][1][0][RTW89_CHILE][7] = 70,
+ [0][0][1][0][RTW89_QATAR][7] = 60,
[0][0][1][0][RTW89_FCC][8] = 80,
[0][0][1][0][RTW89_ETSI][8] = 60,
[0][0][1][0][RTW89_MKK][8] = 78,
@@ -29282,6 +32522,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][8] = 60,
[0][0][1][0][RTW89_CN][8] = 58,
[0][0][1][0][RTW89_UK][8] = 60,
+ [0][0][1][0][RTW89_MEXICO][8] = 80,
+ [0][0][1][0][RTW89_UKRAINE][8] = 60,
+ [0][0][1][0][RTW89_CHILE][8] = 70,
+ [0][0][1][0][RTW89_QATAR][8] = 60,
[0][0][1][0][RTW89_FCC][9] = 76,
[0][0][1][0][RTW89_ETSI][9] = 60,
[0][0][1][0][RTW89_MKK][9] = 78,
@@ -29290,6 +32534,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][9] = 60,
[0][0][1][0][RTW89_CN][9] = 58,
[0][0][1][0][RTW89_UK][9] = 60,
+ [0][0][1][0][RTW89_MEXICO][9] = 76,
+ [0][0][1][0][RTW89_UKRAINE][9] = 60,
+ [0][0][1][0][RTW89_CHILE][9] = 76,
+ [0][0][1][0][RTW89_QATAR][9] = 60,
[0][0][1][0][RTW89_FCC][10] = 66,
[0][0][1][0][RTW89_ETSI][10] = 60,
[0][0][1][0][RTW89_MKK][10] = 78,
@@ -29298,6 +32546,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][10] = 60,
[0][0][1][0][RTW89_CN][10] = 58,
[0][0][1][0][RTW89_UK][10] = 60,
+ [0][0][1][0][RTW89_MEXICO][10] = 66,
+ [0][0][1][0][RTW89_UKRAINE][10] = 60,
+ [0][0][1][0][RTW89_CHILE][10] = 66,
+ [0][0][1][0][RTW89_QATAR][10] = 60,
[0][0][1][0][RTW89_FCC][11] = 62,
[0][0][1][0][RTW89_ETSI][11] = 60,
[0][0][1][0][RTW89_MKK][11] = 78,
@@ -29306,6 +32558,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][11] = 60,
[0][0][1][0][RTW89_CN][11] = 58,
[0][0][1][0][RTW89_UK][11] = 60,
+ [0][0][1][0][RTW89_MEXICO][11] = 62,
+ [0][0][1][0][RTW89_UKRAINE][11] = 60,
+ [0][0][1][0][RTW89_CHILE][11] = 62,
+ [0][0][1][0][RTW89_QATAR][11] = 60,
[0][0][1][0][RTW89_FCC][12] = 60,
[0][0][1][0][RTW89_ETSI][12] = 60,
[0][0][1][0][RTW89_MKK][12] = 78,
@@ -29314,6 +32570,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 60,
[0][0][1][0][RTW89_CN][12] = 58,
[0][0][1][0][RTW89_UK][12] = 60,
+ [0][0][1][0][RTW89_MEXICO][12] = 60,
+ [0][0][1][0][RTW89_UKRAINE][12] = 60,
+ [0][0][1][0][RTW89_CHILE][12] = 60,
+ [0][0][1][0][RTW89_QATAR][12] = 60,
[0][0][1][0][RTW89_FCC][13] = 127,
[0][0][1][0][RTW89_ETSI][13] = 127,
[0][0][1][0][RTW89_MKK][13] = 127,
@@ -29322,6 +32582,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][13] = 127,
[0][0][1][0][RTW89_CN][13] = 127,
[0][0][1][0][RTW89_UK][13] = 127,
+ [0][0][1][0][RTW89_MEXICO][13] = 127,
+ [0][0][1][0][RTW89_UKRAINE][13] = 127,
+ [0][0][1][0][RTW89_CHILE][13] = 127,
+ [0][0][1][0][RTW89_QATAR][13] = 127,
[0][1][1][0][RTW89_FCC][0] = 66,
[0][1][1][0][RTW89_ETSI][0] = 48,
[0][1][1][0][RTW89_MKK][0] = 66,
@@ -29330,6 +32594,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][0] = 48,
[0][1][1][0][RTW89_CN][0] = 46,
[0][1][1][0][RTW89_UK][0] = 48,
+ [0][1][1][0][RTW89_MEXICO][0] = 66,
+ [0][1][1][0][RTW89_UKRAINE][0] = 48,
+ [0][1][1][0][RTW89_CHILE][0] = 66,
+ [0][1][1][0][RTW89_QATAR][0] = 48,
[0][1][1][0][RTW89_FCC][1] = 68,
[0][1][1][0][RTW89_ETSI][1] = 48,
[0][1][1][0][RTW89_MKK][1] = 66,
@@ -29338,6 +32606,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][1] = 48,
[0][1][1][0][RTW89_CN][1] = 46,
[0][1][1][0][RTW89_UK][1] = 48,
+ [0][1][1][0][RTW89_MEXICO][1] = 68,
+ [0][1][1][0][RTW89_UKRAINE][1] = 48,
+ [0][1][1][0][RTW89_CHILE][1] = 68,
+ [0][1][1][0][RTW89_QATAR][1] = 48,
[0][1][1][0][RTW89_FCC][2] = 72,
[0][1][1][0][RTW89_ETSI][2] = 48,
[0][1][1][0][RTW89_MKK][2] = 66,
@@ -29346,6 +32618,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][2] = 48,
[0][1][1][0][RTW89_CN][2] = 46,
[0][1][1][0][RTW89_UK][2] = 48,
+ [0][1][1][0][RTW89_MEXICO][2] = 72,
+ [0][1][1][0][RTW89_UKRAINE][2] = 48,
+ [0][1][1][0][RTW89_CHILE][2] = 54,
+ [0][1][1][0][RTW89_QATAR][2] = 48,
[0][1][1][0][RTW89_FCC][3] = 76,
[0][1][1][0][RTW89_ETSI][3] = 48,
[0][1][1][0][RTW89_MKK][3] = 66,
@@ -29354,6 +32630,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][3] = 48,
[0][1][1][0][RTW89_CN][3] = 46,
[0][1][1][0][RTW89_UK][3] = 48,
+ [0][1][1][0][RTW89_MEXICO][3] = 76,
+ [0][1][1][0][RTW89_UKRAINE][3] = 48,
+ [0][1][1][0][RTW89_CHILE][3] = 54,
+ [0][1][1][0][RTW89_QATAR][3] = 48,
[0][1][1][0][RTW89_FCC][4] = 80,
[0][1][1][0][RTW89_ETSI][4] = 48,
[0][1][1][0][RTW89_MKK][4] = 66,
@@ -29362,6 +32642,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][4] = 48,
[0][1][1][0][RTW89_CN][4] = 46,
[0][1][1][0][RTW89_UK][4] = 48,
+ [0][1][1][0][RTW89_MEXICO][4] = 80,
+ [0][1][1][0][RTW89_UKRAINE][4] = 48,
+ [0][1][1][0][RTW89_CHILE][4] = 54,
+ [0][1][1][0][RTW89_QATAR][4] = 48,
[0][1][1][0][RTW89_FCC][5] = 80,
[0][1][1][0][RTW89_ETSI][5] = 48,
[0][1][1][0][RTW89_MKK][5] = 66,
@@ -29370,6 +32654,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][5] = 48,
[0][1][1][0][RTW89_CN][5] = 46,
[0][1][1][0][RTW89_UK][5] = 48,
+ [0][1][1][0][RTW89_MEXICO][5] = 80,
+ [0][1][1][0][RTW89_UKRAINE][5] = 48,
+ [0][1][1][0][RTW89_CHILE][5] = 80,
+ [0][1][1][0][RTW89_QATAR][5] = 48,
[0][1][1][0][RTW89_FCC][6] = 80,
[0][1][1][0][RTW89_ETSI][6] = 48,
[0][1][1][0][RTW89_MKK][6] = 66,
@@ -29378,6 +32666,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][6] = 48,
[0][1][1][0][RTW89_CN][6] = 46,
[0][1][1][0][RTW89_UK][6] = 48,
+ [0][1][1][0][RTW89_MEXICO][6] = 80,
+ [0][1][1][0][RTW89_UKRAINE][6] = 48,
+ [0][1][1][0][RTW89_CHILE][6] = 56,
+ [0][1][1][0][RTW89_QATAR][6] = 48,
[0][1][1][0][RTW89_FCC][7] = 78,
[0][1][1][0][RTW89_ETSI][7] = 48,
[0][1][1][0][RTW89_MKK][7] = 66,
@@ -29386,6 +32678,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][7] = 48,
[0][1][1][0][RTW89_CN][7] = 46,
[0][1][1][0][RTW89_UK][7] = 48,
+ [0][1][1][0][RTW89_MEXICO][7] = 78,
+ [0][1][1][0][RTW89_UKRAINE][7] = 48,
+ [0][1][1][0][RTW89_CHILE][7] = 56,
+ [0][1][1][0][RTW89_QATAR][7] = 48,
[0][1][1][0][RTW89_FCC][8] = 74,
[0][1][1][0][RTW89_ETSI][8] = 48,
[0][1][1][0][RTW89_MKK][8] = 66,
@@ -29394,6 +32690,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][8] = 48,
[0][1][1][0][RTW89_CN][8] = 46,
[0][1][1][0][RTW89_UK][8] = 48,
+ [0][1][1][0][RTW89_MEXICO][8] = 74,
+ [0][1][1][0][RTW89_UKRAINE][8] = 48,
+ [0][1][1][0][RTW89_CHILE][8] = 56,
+ [0][1][1][0][RTW89_QATAR][8] = 48,
[0][1][1][0][RTW89_FCC][9] = 70,
[0][1][1][0][RTW89_ETSI][9] = 48,
[0][1][1][0][RTW89_MKK][9] = 66,
@@ -29402,6 +32702,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][9] = 48,
[0][1][1][0][RTW89_CN][9] = 46,
[0][1][1][0][RTW89_UK][9] = 48,
+ [0][1][1][0][RTW89_MEXICO][9] = 70,
+ [0][1][1][0][RTW89_UKRAINE][9] = 48,
+ [0][1][1][0][RTW89_CHILE][9] = 70,
+ [0][1][1][0][RTW89_QATAR][9] = 48,
[0][1][1][0][RTW89_FCC][10] = 62,
[0][1][1][0][RTW89_ETSI][10] = 48,
[0][1][1][0][RTW89_MKK][10] = 66,
@@ -29410,6 +32714,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][10] = 48,
[0][1][1][0][RTW89_CN][10] = 46,
[0][1][1][0][RTW89_UK][10] = 48,
+ [0][1][1][0][RTW89_MEXICO][10] = 62,
+ [0][1][1][0][RTW89_UKRAINE][10] = 48,
+ [0][1][1][0][RTW89_CHILE][10] = 62,
+ [0][1][1][0][RTW89_QATAR][10] = 48,
[0][1][1][0][RTW89_FCC][11] = 60,
[0][1][1][0][RTW89_ETSI][11] = 48,
[0][1][1][0][RTW89_MKK][11] = 66,
@@ -29418,6 +32726,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][11] = 48,
[0][1][1][0][RTW89_CN][11] = 46,
[0][1][1][0][RTW89_UK][11] = 48,
+ [0][1][1][0][RTW89_MEXICO][11] = 60,
+ [0][1][1][0][RTW89_UKRAINE][11] = 48,
+ [0][1][1][0][RTW89_CHILE][11] = 60,
+ [0][1][1][0][RTW89_QATAR][11] = 48,
[0][1][1][0][RTW89_FCC][12] = 36,
[0][1][1][0][RTW89_ETSI][12] = 48,
[0][1][1][0][RTW89_MKK][12] = 66,
@@ -29426,6 +32738,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][12] = 48,
[0][1][1][0][RTW89_CN][12] = 46,
[0][1][1][0][RTW89_UK][12] = 48,
+ [0][1][1][0][RTW89_MEXICO][12] = 36,
+ [0][1][1][0][RTW89_UKRAINE][12] = 48,
+ [0][1][1][0][RTW89_CHILE][12] = 36,
+ [0][1][1][0][RTW89_QATAR][12] = 48,
[0][1][1][0][RTW89_FCC][13] = 127,
[0][1][1][0][RTW89_ETSI][13] = 127,
[0][1][1][0][RTW89_MKK][13] = 127,
@@ -29434,6 +32750,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][13] = 127,
[0][1][1][0][RTW89_CN][13] = 127,
[0][1][1][0][RTW89_UK][13] = 127,
+ [0][1][1][0][RTW89_MEXICO][13] = 127,
+ [0][1][1][0][RTW89_UKRAINE][13] = 127,
+ [0][1][1][0][RTW89_CHILE][13] = 127,
+ [0][1][1][0][RTW89_QATAR][13] = 127,
[0][0][2][0][RTW89_FCC][0] = 66,
[0][0][2][0][RTW89_ETSI][0] = 60,
[0][0][2][0][RTW89_MKK][0] = 78,
@@ -29442,6 +32762,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][0] = 60,
[0][0][2][0][RTW89_CN][0] = 58,
[0][0][2][0][RTW89_UK][0] = 60,
+ [0][0][2][0][RTW89_MEXICO][0] = 66,
+ [0][0][2][0][RTW89_UKRAINE][0] = 60,
+ [0][0][2][0][RTW89_CHILE][0] = 66,
+ [0][0][2][0][RTW89_QATAR][0] = 60,
[0][0][2][0][RTW89_FCC][1] = 70,
[0][0][2][0][RTW89_ETSI][1] = 60,
[0][0][2][0][RTW89_MKK][1] = 78,
@@ -29450,6 +32774,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][1] = 60,
[0][0][2][0][RTW89_CN][1] = 58,
[0][0][2][0][RTW89_UK][1] = 60,
+ [0][0][2][0][RTW89_MEXICO][1] = 70,
+ [0][0][2][0][RTW89_UKRAINE][1] = 60,
+ [0][0][2][0][RTW89_CHILE][1] = 70,
+ [0][0][2][0][RTW89_QATAR][1] = 60,
[0][0][2][0][RTW89_FCC][2] = 74,
[0][0][2][0][RTW89_ETSI][2] = 60,
[0][0][2][0][RTW89_MKK][2] = 78,
@@ -29458,6 +32786,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][2] = 60,
[0][0][2][0][RTW89_CN][2] = 58,
[0][0][2][0][RTW89_UK][2] = 60,
+ [0][0][2][0][RTW89_MEXICO][2] = 74,
+ [0][0][2][0][RTW89_UKRAINE][2] = 60,
+ [0][0][2][0][RTW89_CHILE][2] = 64,
+ [0][0][2][0][RTW89_QATAR][2] = 60,
[0][0][2][0][RTW89_FCC][3] = 78,
[0][0][2][0][RTW89_ETSI][3] = 60,
[0][0][2][0][RTW89_MKK][3] = 78,
@@ -29466,6 +32798,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][3] = 60,
[0][0][2][0][RTW89_CN][3] = 58,
[0][0][2][0][RTW89_UK][3] = 60,
+ [0][0][2][0][RTW89_MEXICO][3] = 78,
+ [0][0][2][0][RTW89_UKRAINE][3] = 60,
+ [0][0][2][0][RTW89_CHILE][3] = 64,
+ [0][0][2][0][RTW89_QATAR][3] = 60,
[0][0][2][0][RTW89_FCC][4] = 80,
[0][0][2][0][RTW89_ETSI][4] = 60,
[0][0][2][0][RTW89_MKK][4] = 78,
@@ -29474,6 +32810,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][4] = 60,
[0][0][2][0][RTW89_CN][4] = 58,
[0][0][2][0][RTW89_UK][4] = 60,
+ [0][0][2][0][RTW89_MEXICO][4] = 80,
+ [0][0][2][0][RTW89_UKRAINE][4] = 60,
+ [0][0][2][0][RTW89_CHILE][4] = 64,
+ [0][0][2][0][RTW89_QATAR][4] = 60,
[0][0][2][0][RTW89_FCC][5] = 80,
[0][0][2][0][RTW89_ETSI][5] = 60,
[0][0][2][0][RTW89_MKK][5] = 78,
@@ -29482,6 +32822,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][5] = 60,
[0][0][2][0][RTW89_CN][5] = 58,
[0][0][2][0][RTW89_UK][5] = 60,
+ [0][0][2][0][RTW89_MEXICO][5] = 80,
+ [0][0][2][0][RTW89_UKRAINE][5] = 60,
+ [0][0][2][0][RTW89_CHILE][5] = 80,
+ [0][0][2][0][RTW89_QATAR][5] = 60,
[0][0][2][0][RTW89_FCC][6] = 80,
[0][0][2][0][RTW89_ETSI][6] = 60,
[0][0][2][0][RTW89_MKK][6] = 78,
@@ -29490,6 +32834,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][6] = 60,
[0][0][2][0][RTW89_CN][6] = 58,
[0][0][2][0][RTW89_UK][6] = 60,
+ [0][0][2][0][RTW89_MEXICO][6] = 80,
+ [0][0][2][0][RTW89_UKRAINE][6] = 60,
+ [0][0][2][0][RTW89_CHILE][6] = 68,
+ [0][0][2][0][RTW89_QATAR][6] = 60,
[0][0][2][0][RTW89_FCC][7] = 80,
[0][0][2][0][RTW89_ETSI][7] = 60,
[0][0][2][0][RTW89_MKK][7] = 78,
@@ -29498,6 +32846,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][7] = 60,
[0][0][2][0][RTW89_CN][7] = 58,
[0][0][2][0][RTW89_UK][7] = 60,
+ [0][0][2][0][RTW89_MEXICO][7] = 80,
+ [0][0][2][0][RTW89_UKRAINE][7] = 60,
+ [0][0][2][0][RTW89_CHILE][7] = 68,
+ [0][0][2][0][RTW89_QATAR][7] = 60,
[0][0][2][0][RTW89_FCC][8] = 78,
[0][0][2][0][RTW89_ETSI][8] = 60,
[0][0][2][0][RTW89_MKK][8] = 78,
@@ -29506,6 +32858,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][8] = 60,
[0][0][2][0][RTW89_CN][8] = 58,
[0][0][2][0][RTW89_UK][8] = 60,
+ [0][0][2][0][RTW89_MEXICO][8] = 78,
+ [0][0][2][0][RTW89_UKRAINE][8] = 60,
+ [0][0][2][0][RTW89_CHILE][8] = 68,
+ [0][0][2][0][RTW89_QATAR][8] = 60,
[0][0][2][0][RTW89_FCC][9] = 74,
[0][0][2][0][RTW89_ETSI][9] = 60,
[0][0][2][0][RTW89_MKK][9] = 78,
@@ -29514,6 +32870,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][9] = 60,
[0][0][2][0][RTW89_CN][9] = 58,
[0][0][2][0][RTW89_UK][9] = 60,
+ [0][0][2][0][RTW89_MEXICO][9] = 74,
+ [0][0][2][0][RTW89_UKRAINE][9] = 60,
+ [0][0][2][0][RTW89_CHILE][9] = 74,
+ [0][0][2][0][RTW89_QATAR][9] = 60,
[0][0][2][0][RTW89_FCC][10] = 62,
[0][0][2][0][RTW89_ETSI][10] = 60,
[0][0][2][0][RTW89_MKK][10] = 78,
@@ -29522,6 +32882,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][10] = 60,
[0][0][2][0][RTW89_CN][10] = 58,
[0][0][2][0][RTW89_UK][10] = 60,
+ [0][0][2][0][RTW89_MEXICO][10] = 62,
+ [0][0][2][0][RTW89_UKRAINE][10] = 60,
+ [0][0][2][0][RTW89_CHILE][10] = 62,
+ [0][0][2][0][RTW89_QATAR][10] = 60,
[0][0][2][0][RTW89_FCC][11] = 60,
[0][0][2][0][RTW89_ETSI][11] = 60,
[0][0][2][0][RTW89_MKK][11] = 78,
@@ -29530,6 +32894,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][11] = 60,
[0][0][2][0][RTW89_CN][11] = 58,
[0][0][2][0][RTW89_UK][11] = 60,
+ [0][0][2][0][RTW89_MEXICO][11] = 60,
+ [0][0][2][0][RTW89_UKRAINE][11] = 60,
+ [0][0][2][0][RTW89_CHILE][11] = 60,
+ [0][0][2][0][RTW89_QATAR][11] = 60,
[0][0][2][0][RTW89_FCC][12] = 38,
[0][0][2][0][RTW89_ETSI][12] = 60,
[0][0][2][0][RTW89_MKK][12] = 78,
@@ -29538,6 +32906,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 60,
[0][0][2][0][RTW89_CN][12] = 58,
[0][0][2][0][RTW89_UK][12] = 60,
+ [0][0][2][0][RTW89_MEXICO][12] = 38,
+ [0][0][2][0][RTW89_UKRAINE][12] = 60,
+ [0][0][2][0][RTW89_CHILE][12] = 38,
+ [0][0][2][0][RTW89_QATAR][12] = 60,
[0][0][2][0][RTW89_FCC][13] = 127,
[0][0][2][0][RTW89_ETSI][13] = 127,
[0][0][2][0][RTW89_MKK][13] = 127,
@@ -29546,6 +32918,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][13] = 127,
[0][0][2][0][RTW89_CN][13] = 127,
[0][0][2][0][RTW89_UK][13] = 127,
+ [0][0][2][0][RTW89_MEXICO][13] = 127,
+ [0][0][2][0][RTW89_UKRAINE][13] = 127,
+ [0][0][2][0][RTW89_CHILE][13] = 127,
+ [0][0][2][0][RTW89_QATAR][13] = 127,
[0][1][2][0][RTW89_FCC][0] = 64,
[0][1][2][0][RTW89_ETSI][0] = 48,
[0][1][2][0][RTW89_MKK][0] = 68,
@@ -29554,6 +32930,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][0] = 48,
[0][1][2][0][RTW89_CN][0] = 46,
[0][1][2][0][RTW89_UK][0] = 48,
+ [0][1][2][0][RTW89_MEXICO][0] = 64,
+ [0][1][2][0][RTW89_UKRAINE][0] = 48,
+ [0][1][2][0][RTW89_CHILE][0] = 64,
+ [0][1][2][0][RTW89_QATAR][0] = 48,
[0][1][2][0][RTW89_FCC][1] = 70,
[0][1][2][0][RTW89_ETSI][1] = 48,
[0][1][2][0][RTW89_MKK][1] = 68,
@@ -29562,6 +32942,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][1] = 48,
[0][1][2][0][RTW89_CN][1] = 46,
[0][1][2][0][RTW89_UK][1] = 48,
+ [0][1][2][0][RTW89_MEXICO][1] = 70,
+ [0][1][2][0][RTW89_UKRAINE][1] = 48,
+ [0][1][2][0][RTW89_CHILE][1] = 70,
+ [0][1][2][0][RTW89_QATAR][1] = 48,
[0][1][2][0][RTW89_FCC][2] = 74,
[0][1][2][0][RTW89_ETSI][2] = 48,
[0][1][2][0][RTW89_MKK][2] = 68,
@@ -29570,6 +32954,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][2] = 48,
[0][1][2][0][RTW89_CN][2] = 46,
[0][1][2][0][RTW89_UK][2] = 48,
+ [0][1][2][0][RTW89_MEXICO][2] = 74,
+ [0][1][2][0][RTW89_UKRAINE][2] = 48,
+ [0][1][2][0][RTW89_CHILE][2] = 56,
+ [0][1][2][0][RTW89_QATAR][2] = 48,
[0][1][2][0][RTW89_FCC][3] = 78,
[0][1][2][0][RTW89_ETSI][3] = 48,
[0][1][2][0][RTW89_MKK][3] = 68,
@@ -29578,6 +32966,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][3] = 48,
[0][1][2][0][RTW89_CN][3] = 46,
[0][1][2][0][RTW89_UK][3] = 48,
+ [0][1][2][0][RTW89_MEXICO][3] = 78,
+ [0][1][2][0][RTW89_UKRAINE][3] = 48,
+ [0][1][2][0][RTW89_CHILE][3] = 56,
+ [0][1][2][0][RTW89_QATAR][3] = 48,
[0][1][2][0][RTW89_FCC][4] = 80,
[0][1][2][0][RTW89_ETSI][4] = 48,
[0][1][2][0][RTW89_MKK][4] = 68,
@@ -29586,6 +32978,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][4] = 48,
[0][1][2][0][RTW89_CN][4] = 46,
[0][1][2][0][RTW89_UK][4] = 48,
+ [0][1][2][0][RTW89_MEXICO][4] = 80,
+ [0][1][2][0][RTW89_UKRAINE][4] = 48,
+ [0][1][2][0][RTW89_CHILE][4] = 56,
+ [0][1][2][0][RTW89_QATAR][4] = 48,
[0][1][2][0][RTW89_FCC][5] = 80,
[0][1][2][0][RTW89_ETSI][5] = 48,
[0][1][2][0][RTW89_MKK][5] = 68,
@@ -29594,6 +32990,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][5] = 48,
[0][1][2][0][RTW89_CN][5] = 46,
[0][1][2][0][RTW89_UK][5] = 48,
+ [0][1][2][0][RTW89_MEXICO][5] = 80,
+ [0][1][2][0][RTW89_UKRAINE][5] = 48,
+ [0][1][2][0][RTW89_CHILE][5] = 78,
+ [0][1][2][0][RTW89_QATAR][5] = 48,
[0][1][2][0][RTW89_FCC][6] = 80,
[0][1][2][0][RTW89_ETSI][6] = 48,
[0][1][2][0][RTW89_MKK][6] = 68,
@@ -29602,6 +33002,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][6] = 48,
[0][1][2][0][RTW89_CN][6] = 46,
[0][1][2][0][RTW89_UK][6] = 48,
+ [0][1][2][0][RTW89_MEXICO][6] = 80,
+ [0][1][2][0][RTW89_UKRAINE][6] = 48,
+ [0][1][2][0][RTW89_CHILE][6] = 54,
+ [0][1][2][0][RTW89_QATAR][6] = 48,
[0][1][2][0][RTW89_FCC][7] = 74,
[0][1][2][0][RTW89_ETSI][7] = 48,
[0][1][2][0][RTW89_MKK][7] = 68,
@@ -29610,6 +33014,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][7] = 48,
[0][1][2][0][RTW89_CN][7] = 46,
[0][1][2][0][RTW89_UK][7] = 48,
+ [0][1][2][0][RTW89_MEXICO][7] = 74,
+ [0][1][2][0][RTW89_UKRAINE][7] = 48,
+ [0][1][2][0][RTW89_CHILE][7] = 54,
+ [0][1][2][0][RTW89_QATAR][7] = 48,
[0][1][2][0][RTW89_FCC][8] = 70,
[0][1][2][0][RTW89_ETSI][8] = 48,
[0][1][2][0][RTW89_MKK][8] = 68,
@@ -29618,6 +33026,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][8] = 48,
[0][1][2][0][RTW89_CN][8] = 46,
[0][1][2][0][RTW89_UK][8] = 48,
+ [0][1][2][0][RTW89_MEXICO][8] = 70,
+ [0][1][2][0][RTW89_UKRAINE][8] = 48,
+ [0][1][2][0][RTW89_CHILE][8] = 54,
+ [0][1][2][0][RTW89_QATAR][8] = 48,
[0][1][2][0][RTW89_FCC][9] = 66,
[0][1][2][0][RTW89_ETSI][9] = 48,
[0][1][2][0][RTW89_MKK][9] = 68,
@@ -29626,6 +33038,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][9] = 48,
[0][1][2][0][RTW89_CN][9] = 46,
[0][1][2][0][RTW89_UK][9] = 48,
+ [0][1][2][0][RTW89_MEXICO][9] = 66,
+ [0][1][2][0][RTW89_UKRAINE][9] = 48,
+ [0][1][2][0][RTW89_CHILE][9] = 66,
+ [0][1][2][0][RTW89_QATAR][9] = 48,
[0][1][2][0][RTW89_FCC][10] = 58,
[0][1][2][0][RTW89_ETSI][10] = 48,
[0][1][2][0][RTW89_MKK][10] = 68,
@@ -29634,6 +33050,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][10] = 48,
[0][1][2][0][RTW89_CN][10] = 46,
[0][1][2][0][RTW89_UK][10] = 48,
+ [0][1][2][0][RTW89_MEXICO][10] = 58,
+ [0][1][2][0][RTW89_UKRAINE][10] = 48,
+ [0][1][2][0][RTW89_CHILE][10] = 58,
+ [0][1][2][0][RTW89_QATAR][10] = 48,
[0][1][2][0][RTW89_FCC][11] = 58,
[0][1][2][0][RTW89_ETSI][11] = 48,
[0][1][2][0][RTW89_MKK][11] = 68,
@@ -29642,6 +33062,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][11] = 48,
[0][1][2][0][RTW89_CN][11] = 46,
[0][1][2][0][RTW89_UK][11] = 48,
+ [0][1][2][0][RTW89_MEXICO][11] = 58,
+ [0][1][2][0][RTW89_UKRAINE][11] = 48,
+ [0][1][2][0][RTW89_CHILE][11] = 58,
+ [0][1][2][0][RTW89_QATAR][11] = 48,
[0][1][2][0][RTW89_FCC][12] = 16,
[0][1][2][0][RTW89_ETSI][12] = 48,
[0][1][2][0][RTW89_MKK][12] = 68,
@@ -29650,6 +33074,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][12] = 48,
[0][1][2][0][RTW89_CN][12] = 46,
[0][1][2][0][RTW89_UK][12] = 48,
+ [0][1][2][0][RTW89_MEXICO][12] = 16,
+ [0][1][2][0][RTW89_UKRAINE][12] = 48,
+ [0][1][2][0][RTW89_CHILE][12] = 16,
+ [0][1][2][0][RTW89_QATAR][12] = 48,
[0][1][2][0][RTW89_FCC][13] = 127,
[0][1][2][0][RTW89_ETSI][13] = 127,
[0][1][2][0][RTW89_MKK][13] = 127,
@@ -29658,6 +33086,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][13] = 127,
[0][1][2][0][RTW89_CN][13] = 127,
[0][1][2][0][RTW89_UK][13] = 127,
+ [0][1][2][0][RTW89_MEXICO][13] = 127,
+ [0][1][2][0][RTW89_UKRAINE][13] = 127,
+ [0][1][2][0][RTW89_CHILE][13] = 127,
+ [0][1][2][0][RTW89_QATAR][13] = 127,
[0][1][2][1][RTW89_FCC][0] = 64,
[0][1][2][1][RTW89_ETSI][0] = 36,
[0][1][2][1][RTW89_MKK][0] = 68,
@@ -29666,6 +33098,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][0] = 36,
[0][1][2][1][RTW89_CN][0] = 36,
[0][1][2][1][RTW89_UK][0] = 36,
+ [0][1][2][1][RTW89_MEXICO][0] = 64,
+ [0][1][2][1][RTW89_UKRAINE][0] = 36,
+ [0][1][2][1][RTW89_CHILE][0] = 64,
+ [0][1][2][1][RTW89_QATAR][0] = 36,
[0][1][2][1][RTW89_FCC][1] = 70,
[0][1][2][1][RTW89_ETSI][1] = 36,
[0][1][2][1][RTW89_MKK][1] = 68,
@@ -29674,6 +33110,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][1] = 36,
[0][1][2][1][RTW89_CN][1] = 34,
[0][1][2][1][RTW89_UK][1] = 36,
+ [0][1][2][1][RTW89_MEXICO][1] = 70,
+ [0][1][2][1][RTW89_UKRAINE][1] = 36,
+ [0][1][2][1][RTW89_CHILE][1] = 70,
+ [0][1][2][1][RTW89_QATAR][1] = 36,
[0][1][2][1][RTW89_FCC][2] = 74,
[0][1][2][1][RTW89_ETSI][2] = 36,
[0][1][2][1][RTW89_MKK][2] = 68,
@@ -29682,6 +33122,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][2] = 36,
[0][1][2][1][RTW89_CN][2] = 34,
[0][1][2][1][RTW89_UK][2] = 36,
+ [0][1][2][1][RTW89_MEXICO][2] = 74,
+ [0][1][2][1][RTW89_UKRAINE][2] = 36,
+ [0][1][2][1][RTW89_CHILE][2] = 44,
+ [0][1][2][1][RTW89_QATAR][2] = 36,
[0][1][2][1][RTW89_FCC][3] = 78,
[0][1][2][1][RTW89_ETSI][3] = 36,
[0][1][2][1][RTW89_MKK][3] = 68,
@@ -29690,6 +33134,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][3] = 36,
[0][1][2][1][RTW89_CN][3] = 34,
[0][1][2][1][RTW89_UK][3] = 36,
+ [0][1][2][1][RTW89_MEXICO][3] = 78,
+ [0][1][2][1][RTW89_UKRAINE][3] = 36,
+ [0][1][2][1][RTW89_CHILE][3] = 44,
+ [0][1][2][1][RTW89_QATAR][3] = 36,
[0][1][2][1][RTW89_FCC][4] = 80,
[0][1][2][1][RTW89_ETSI][4] = 36,
[0][1][2][1][RTW89_MKK][4] = 68,
@@ -29698,6 +33146,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][4] = 36,
[0][1][2][1][RTW89_CN][4] = 34,
[0][1][2][1][RTW89_UK][4] = 36,
+ [0][1][2][1][RTW89_MEXICO][4] = 80,
+ [0][1][2][1][RTW89_UKRAINE][4] = 36,
+ [0][1][2][1][RTW89_CHILE][4] = 44,
+ [0][1][2][1][RTW89_QATAR][4] = 36,
[0][1][2][1][RTW89_FCC][5] = 80,
[0][1][2][1][RTW89_ETSI][5] = 36,
[0][1][2][1][RTW89_MKK][5] = 68,
@@ -29706,6 +33158,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][5] = 36,
[0][1][2][1][RTW89_CN][5] = 34,
[0][1][2][1][RTW89_UK][5] = 36,
+ [0][1][2][1][RTW89_MEXICO][5] = 80,
+ [0][1][2][1][RTW89_UKRAINE][5] = 36,
+ [0][1][2][1][RTW89_CHILE][5] = 74,
+ [0][1][2][1][RTW89_QATAR][5] = 36,
[0][1][2][1][RTW89_FCC][6] = 80,
[0][1][2][1][RTW89_ETSI][6] = 36,
[0][1][2][1][RTW89_MKK][6] = 68,
@@ -29714,6 +33170,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][6] = 36,
[0][1][2][1][RTW89_CN][6] = 34,
[0][1][2][1][RTW89_UK][6] = 36,
+ [0][1][2][1][RTW89_MEXICO][6] = 80,
+ [0][1][2][1][RTW89_UKRAINE][6] = 36,
+ [0][1][2][1][RTW89_CHILE][6] = 42,
+ [0][1][2][1][RTW89_QATAR][6] = 36,
[0][1][2][1][RTW89_FCC][7] = 74,
[0][1][2][1][RTW89_ETSI][7] = 36,
[0][1][2][1][RTW89_MKK][7] = 68,
@@ -29722,6 +33182,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][7] = 36,
[0][1][2][1][RTW89_CN][7] = 34,
[0][1][2][1][RTW89_UK][7] = 36,
+ [0][1][2][1][RTW89_MEXICO][7] = 74,
+ [0][1][2][1][RTW89_UKRAINE][7] = 36,
+ [0][1][2][1][RTW89_CHILE][7] = 42,
+ [0][1][2][1][RTW89_QATAR][7] = 36,
[0][1][2][1][RTW89_FCC][8] = 70,
[0][1][2][1][RTW89_ETSI][8] = 36,
[0][1][2][1][RTW89_MKK][8] = 68,
@@ -29730,6 +33194,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][8] = 36,
[0][1][2][1][RTW89_CN][8] = 34,
[0][1][2][1][RTW89_UK][8] = 36,
+ [0][1][2][1][RTW89_MEXICO][8] = 70,
+ [0][1][2][1][RTW89_UKRAINE][8] = 36,
+ [0][1][2][1][RTW89_CHILE][8] = 42,
+ [0][1][2][1][RTW89_QATAR][8] = 36,
[0][1][2][1][RTW89_FCC][9] = 66,
[0][1][2][1][RTW89_ETSI][9] = 36,
[0][1][2][1][RTW89_MKK][9] = 68,
@@ -29738,6 +33206,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][9] = 36,
[0][1][2][1][RTW89_CN][9] = 34,
[0][1][2][1][RTW89_UK][9] = 36,
+ [0][1][2][1][RTW89_MEXICO][9] = 66,
+ [0][1][2][1][RTW89_UKRAINE][9] = 36,
+ [0][1][2][1][RTW89_CHILE][9] = 66,
+ [0][1][2][1][RTW89_QATAR][9] = 36,
[0][1][2][1][RTW89_FCC][10] = 58,
[0][1][2][1][RTW89_ETSI][10] = 36,
[0][1][2][1][RTW89_MKK][10] = 68,
@@ -29746,6 +33218,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][10] = 36,
[0][1][2][1][RTW89_CN][10] = 34,
[0][1][2][1][RTW89_UK][10] = 36,
+ [0][1][2][1][RTW89_MEXICO][10] = 58,
+ [0][1][2][1][RTW89_UKRAINE][10] = 36,
+ [0][1][2][1][RTW89_CHILE][10] = 58,
+ [0][1][2][1][RTW89_QATAR][10] = 36,
[0][1][2][1][RTW89_FCC][11] = 58,
[0][1][2][1][RTW89_ETSI][11] = 36,
[0][1][2][1][RTW89_MKK][11] = 68,
@@ -29754,6 +33230,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][11] = 36,
[0][1][2][1][RTW89_CN][11] = 34,
[0][1][2][1][RTW89_UK][11] = 36,
+ [0][1][2][1][RTW89_MEXICO][11] = 58,
+ [0][1][2][1][RTW89_UKRAINE][11] = 36,
+ [0][1][2][1][RTW89_CHILE][11] = 58,
+ [0][1][2][1][RTW89_QATAR][11] = 36,
[0][1][2][1][RTW89_FCC][12] = 16,
[0][1][2][1][RTW89_ETSI][12] = 36,
[0][1][2][1][RTW89_MKK][12] = 68,
@@ -29762,6 +33242,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][12] = 36,
[0][1][2][1][RTW89_CN][12] = 34,
[0][1][2][1][RTW89_UK][12] = 36,
+ [0][1][2][1][RTW89_MEXICO][12] = 16,
+ [0][1][2][1][RTW89_UKRAINE][12] = 36,
+ [0][1][2][1][RTW89_CHILE][12] = 16,
+ [0][1][2][1][RTW89_QATAR][12] = 36,
[0][1][2][1][RTW89_FCC][13] = 127,
[0][1][2][1][RTW89_ETSI][13] = 127,
[0][1][2][1][RTW89_MKK][13] = 127,
@@ -29770,6 +33254,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][13] = 127,
[0][1][2][1][RTW89_CN][13] = 127,
[0][1][2][1][RTW89_UK][13] = 127,
+ [0][1][2][1][RTW89_MEXICO][13] = 127,
+ [0][1][2][1][RTW89_UKRAINE][13] = 127,
+ [0][1][2][1][RTW89_CHILE][13] = 127,
+ [0][1][2][1][RTW89_QATAR][13] = 127,
[1][0][2][0][RTW89_FCC][0] = 127,
[1][0][2][0][RTW89_ETSI][0] = 127,
[1][0][2][0][RTW89_MKK][0] = 127,
@@ -29778,6 +33266,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][0] = 127,
[1][0][2][0][RTW89_CN][0] = 127,
[1][0][2][0][RTW89_UK][0] = 127,
+ [1][0][2][0][RTW89_MEXICO][0] = 127,
+ [1][0][2][0][RTW89_UKRAINE][0] = 127,
+ [1][0][2][0][RTW89_CHILE][0] = 127,
+ [1][0][2][0][RTW89_QATAR][0] = 127,
[1][0][2][0][RTW89_FCC][1] = 127,
[1][0][2][0][RTW89_ETSI][1] = 127,
[1][0][2][0][RTW89_MKK][1] = 127,
@@ -29786,6 +33278,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][1] = 127,
[1][0][2][0][RTW89_CN][1] = 127,
[1][0][2][0][RTW89_UK][1] = 127,
+ [1][0][2][0][RTW89_MEXICO][1] = 127,
+ [1][0][2][0][RTW89_UKRAINE][1] = 127,
+ [1][0][2][0][RTW89_CHILE][1] = 127,
+ [1][0][2][0][RTW89_QATAR][1] = 127,
[1][0][2][0][RTW89_FCC][2] = 64,
[1][0][2][0][RTW89_ETSI][2] = 60,
[1][0][2][0][RTW89_MKK][2] = 74,
@@ -29794,6 +33290,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][2] = 60,
[1][0][2][0][RTW89_CN][2] = 58,
[1][0][2][0][RTW89_UK][2] = 60,
+ [1][0][2][0][RTW89_MEXICO][2] = 64,
+ [1][0][2][0][RTW89_UKRAINE][2] = 60,
+ [1][0][2][0][RTW89_CHILE][2] = 64,
+ [1][0][2][0][RTW89_QATAR][2] = 60,
[1][0][2][0][RTW89_FCC][3] = 64,
[1][0][2][0][RTW89_ETSI][3] = 60,
[1][0][2][0][RTW89_MKK][3] = 74,
@@ -29802,6 +33302,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][3] = 60,
[1][0][2][0][RTW89_CN][3] = 58,
[1][0][2][0][RTW89_UK][3] = 60,
+ [1][0][2][0][RTW89_MEXICO][3] = 64,
+ [1][0][2][0][RTW89_UKRAINE][3] = 60,
+ [1][0][2][0][RTW89_CHILE][3] = 64,
+ [1][0][2][0][RTW89_QATAR][3] = 60,
[1][0][2][0][RTW89_FCC][4] = 68,
[1][0][2][0][RTW89_ETSI][4] = 60,
[1][0][2][0][RTW89_MKK][4] = 74,
@@ -29810,6 +33314,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][4] = 60,
[1][0][2][0][RTW89_CN][4] = 58,
[1][0][2][0][RTW89_UK][4] = 60,
+ [1][0][2][0][RTW89_MEXICO][4] = 68,
+ [1][0][2][0][RTW89_UKRAINE][4] = 60,
+ [1][0][2][0][RTW89_CHILE][4] = 68,
+ [1][0][2][0][RTW89_QATAR][4] = 60,
[1][0][2][0][RTW89_FCC][5] = 68,
[1][0][2][0][RTW89_ETSI][5] = 60,
[1][0][2][0][RTW89_MKK][5] = 74,
@@ -29818,6 +33326,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][5] = 60,
[1][0][2][0][RTW89_CN][5] = 58,
[1][0][2][0][RTW89_UK][5] = 60,
+ [1][0][2][0][RTW89_MEXICO][5] = 68,
+ [1][0][2][0][RTW89_UKRAINE][5] = 60,
+ [1][0][2][0][RTW89_CHILE][5] = 68,
+ [1][0][2][0][RTW89_QATAR][5] = 60,
[1][0][2][0][RTW89_FCC][6] = 66,
[1][0][2][0][RTW89_ETSI][6] = 60,
[1][0][2][0][RTW89_MKK][6] = 74,
@@ -29826,6 +33338,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][6] = 60,
[1][0][2][0][RTW89_CN][6] = 58,
[1][0][2][0][RTW89_UK][6] = 60,
+ [1][0][2][0][RTW89_MEXICO][6] = 66,
+ [1][0][2][0][RTW89_UKRAINE][6] = 60,
+ [1][0][2][0][RTW89_CHILE][6] = 66,
+ [1][0][2][0][RTW89_QATAR][6] = 60,
[1][0][2][0][RTW89_FCC][7] = 62,
[1][0][2][0][RTW89_ETSI][7] = 60,
[1][0][2][0][RTW89_MKK][7] = 74,
@@ -29834,6 +33350,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][7] = 60,
[1][0][2][0][RTW89_CN][7] = 58,
[1][0][2][0][RTW89_UK][7] = 60,
+ [1][0][2][0][RTW89_MEXICO][7] = 62,
+ [1][0][2][0][RTW89_UKRAINE][7] = 60,
+ [1][0][2][0][RTW89_CHILE][7] = 62,
+ [1][0][2][0][RTW89_QATAR][7] = 60,
[1][0][2][0][RTW89_FCC][8] = 62,
[1][0][2][0][RTW89_ETSI][8] = 60,
[1][0][2][0][RTW89_MKK][8] = 74,
@@ -29842,6 +33362,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][8] = 60,
[1][0][2][0][RTW89_CN][8] = 58,
[1][0][2][0][RTW89_UK][8] = 60,
+ [1][0][2][0][RTW89_MEXICO][8] = 62,
+ [1][0][2][0][RTW89_UKRAINE][8] = 60,
+ [1][0][2][0][RTW89_CHILE][8] = 62,
+ [1][0][2][0][RTW89_QATAR][8] = 60,
[1][0][2][0][RTW89_FCC][9] = 60,
[1][0][2][0][RTW89_ETSI][9] = 60,
[1][0][2][0][RTW89_MKK][9] = 74,
@@ -29850,6 +33374,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 60,
[1][0][2][0][RTW89_CN][9] = 58,
[1][0][2][0][RTW89_UK][9] = 60,
+ [1][0][2][0][RTW89_MEXICO][9] = 60,
+ [1][0][2][0][RTW89_UKRAINE][9] = 60,
+ [1][0][2][0][RTW89_CHILE][9] = 60,
+ [1][0][2][0][RTW89_QATAR][9] = 60,
[1][0][2][0][RTW89_FCC][10] = 56,
[1][0][2][0][RTW89_ETSI][10] = 60,
[1][0][2][0][RTW89_MKK][10] = 74,
@@ -29858,6 +33386,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][10] = 60,
[1][0][2][0][RTW89_CN][10] = 58,
[1][0][2][0][RTW89_UK][10] = 60,
+ [1][0][2][0][RTW89_MEXICO][10] = 56,
+ [1][0][2][0][RTW89_UKRAINE][10] = 60,
+ [1][0][2][0][RTW89_CHILE][10] = 56,
+ [1][0][2][0][RTW89_QATAR][10] = 60,
[1][0][2][0][RTW89_FCC][11] = 127,
[1][0][2][0][RTW89_ETSI][11] = 127,
[1][0][2][0][RTW89_MKK][11] = 127,
@@ -29866,6 +33398,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][11] = 127,
[1][0][2][0][RTW89_CN][11] = 127,
[1][0][2][0][RTW89_UK][11] = 127,
+ [1][0][2][0][RTW89_MEXICO][11] = 127,
+ [1][0][2][0][RTW89_UKRAINE][11] = 127,
+ [1][0][2][0][RTW89_CHILE][11] = 127,
+ [1][0][2][0][RTW89_QATAR][11] = 127,
[1][0][2][0][RTW89_FCC][12] = 127,
[1][0][2][0][RTW89_ETSI][12] = 127,
[1][0][2][0][RTW89_MKK][12] = 127,
@@ -29874,6 +33410,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][12] = 127,
[1][0][2][0][RTW89_CN][12] = 127,
[1][0][2][0][RTW89_UK][12] = 127,
+ [1][0][2][0][RTW89_MEXICO][12] = 127,
+ [1][0][2][0][RTW89_UKRAINE][12] = 127,
+ [1][0][2][0][RTW89_CHILE][12] = 127,
+ [1][0][2][0][RTW89_QATAR][12] = 127,
[1][0][2][0][RTW89_FCC][13] = 127,
[1][0][2][0][RTW89_ETSI][13] = 127,
[1][0][2][0][RTW89_MKK][13] = 127,
@@ -29882,6 +33422,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][13] = 127,
[1][0][2][0][RTW89_CN][13] = 127,
[1][0][2][0][RTW89_UK][13] = 127,
+ [1][0][2][0][RTW89_MEXICO][13] = 127,
+ [1][0][2][0][RTW89_UKRAINE][13] = 127,
+ [1][0][2][0][RTW89_CHILE][13] = 127,
+ [1][0][2][0][RTW89_QATAR][13] = 127,
[1][1][2][0][RTW89_FCC][0] = 127,
[1][1][2][0][RTW89_ETSI][0] = 127,
[1][1][2][0][RTW89_MKK][0] = 127,
@@ -29890,6 +33434,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][0] = 127,
[1][1][2][0][RTW89_CN][0] = 127,
[1][1][2][0][RTW89_UK][0] = 127,
+ [1][1][2][0][RTW89_MEXICO][0] = 127,
+ [1][1][2][0][RTW89_UKRAINE][0] = 127,
+ [1][1][2][0][RTW89_CHILE][0] = 127,
+ [1][1][2][0][RTW89_QATAR][0] = 127,
[1][1][2][0][RTW89_FCC][1] = 127,
[1][1][2][0][RTW89_ETSI][1] = 127,
[1][1][2][0][RTW89_MKK][1] = 127,
@@ -29898,6 +33446,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][1] = 127,
[1][1][2][0][RTW89_CN][1] = 127,
[1][1][2][0][RTW89_UK][1] = 127,
+ [1][1][2][0][RTW89_MEXICO][1] = 127,
+ [1][1][2][0][RTW89_UKRAINE][1] = 127,
+ [1][1][2][0][RTW89_CHILE][1] = 127,
+ [1][1][2][0][RTW89_QATAR][1] = 127,
[1][1][2][0][RTW89_FCC][2] = 60,
[1][1][2][0][RTW89_ETSI][2] = 48,
[1][1][2][0][RTW89_MKK][2] = 68,
@@ -29906,6 +33458,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][2] = 48,
[1][1][2][0][RTW89_CN][2] = 34,
[1][1][2][0][RTW89_UK][2] = 48,
+ [1][1][2][0][RTW89_MEXICO][2] = 60,
+ [1][1][2][0][RTW89_UKRAINE][2] = 48,
+ [1][1][2][0][RTW89_CHILE][2] = 60,
+ [1][1][2][0][RTW89_QATAR][2] = 48,
[1][1][2][0][RTW89_FCC][3] = 60,
[1][1][2][0][RTW89_ETSI][3] = 48,
[1][1][2][0][RTW89_MKK][3] = 68,
@@ -29914,6 +33470,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][3] = 48,
[1][1][2][0][RTW89_CN][3] = 34,
[1][1][2][0][RTW89_UK][3] = 48,
+ [1][1][2][0][RTW89_MEXICO][3] = 60,
+ [1][1][2][0][RTW89_UKRAINE][3] = 48,
+ [1][1][2][0][RTW89_CHILE][3] = 56,
+ [1][1][2][0][RTW89_QATAR][3] = 48,
[1][1][2][0][RTW89_FCC][4] = 60,
[1][1][2][0][RTW89_ETSI][4] = 48,
[1][1][2][0][RTW89_MKK][4] = 68,
@@ -29922,6 +33482,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][4] = 48,
[1][1][2][0][RTW89_CN][4] = 34,
[1][1][2][0][RTW89_UK][4] = 48,
+ [1][1][2][0][RTW89_MEXICO][4] = 60,
+ [1][1][2][0][RTW89_UKRAINE][4] = 48,
+ [1][1][2][0][RTW89_CHILE][4] = 56,
+ [1][1][2][0][RTW89_QATAR][4] = 48,
[1][1][2][0][RTW89_FCC][5] = 60,
[1][1][2][0][RTW89_ETSI][5] = 48,
[1][1][2][0][RTW89_MKK][5] = 68,
@@ -29930,6 +33494,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][5] = 48,
[1][1][2][0][RTW89_CN][5] = 34,
[1][1][2][0][RTW89_UK][5] = 48,
+ [1][1][2][0][RTW89_MEXICO][5] = 60,
+ [1][1][2][0][RTW89_UKRAINE][5] = 48,
+ [1][1][2][0][RTW89_CHILE][5] = 60,
+ [1][1][2][0][RTW89_QATAR][5] = 48,
[1][1][2][0][RTW89_FCC][6] = 58,
[1][1][2][0][RTW89_ETSI][6] = 48,
[1][1][2][0][RTW89_MKK][6] = 68,
@@ -29938,6 +33506,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][6] = 48,
[1][1][2][0][RTW89_CN][6] = 34,
[1][1][2][0][RTW89_UK][6] = 48,
+ [1][1][2][0][RTW89_MEXICO][6] = 58,
+ [1][1][2][0][RTW89_UKRAINE][6] = 48,
+ [1][1][2][0][RTW89_CHILE][6] = 52,
+ [1][1][2][0][RTW89_QATAR][6] = 48,
[1][1][2][0][RTW89_FCC][7] = 54,
[1][1][2][0][RTW89_ETSI][7] = 48,
[1][1][2][0][RTW89_MKK][7] = 68,
@@ -29946,6 +33518,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][7] = 48,
[1][1][2][0][RTW89_CN][7] = 34,
[1][1][2][0][RTW89_UK][7] = 48,
+ [1][1][2][0][RTW89_MEXICO][7] = 54,
+ [1][1][2][0][RTW89_UKRAINE][7] = 48,
+ [1][1][2][0][RTW89_CHILE][7] = 52,
+ [1][1][2][0][RTW89_QATAR][7] = 48,
[1][1][2][0][RTW89_FCC][8] = 54,
[1][1][2][0][RTW89_ETSI][8] = 48,
[1][1][2][0][RTW89_MKK][8] = 68,
@@ -29954,6 +33530,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][8] = 48,
[1][1][2][0][RTW89_CN][8] = 34,
[1][1][2][0][RTW89_UK][8] = 48,
+ [1][1][2][0][RTW89_MEXICO][8] = 54,
+ [1][1][2][0][RTW89_UKRAINE][8] = 48,
+ [1][1][2][0][RTW89_CHILE][8] = 54,
+ [1][1][2][0][RTW89_QATAR][8] = 48,
[1][1][2][0][RTW89_FCC][9] = 54,
[1][1][2][0][RTW89_ETSI][9] = 48,
[1][1][2][0][RTW89_MKK][9] = 68,
@@ -29962,6 +33542,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][9] = 48,
[1][1][2][0][RTW89_CN][9] = 34,
[1][1][2][0][RTW89_UK][9] = 48,
+ [1][1][2][0][RTW89_MEXICO][9] = 54,
+ [1][1][2][0][RTW89_UKRAINE][9] = 48,
+ [1][1][2][0][RTW89_CHILE][9] = 54,
+ [1][1][2][0][RTW89_QATAR][9] = 48,
[1][1][2][0][RTW89_FCC][10] = 46,
[1][1][2][0][RTW89_ETSI][10] = 48,
[1][1][2][0][RTW89_MKK][10] = 68,
@@ -29970,6 +33554,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][10] = 48,
[1][1][2][0][RTW89_CN][10] = 34,
[1][1][2][0][RTW89_UK][10] = 48,
+ [1][1][2][0][RTW89_MEXICO][10] = 46,
+ [1][1][2][0][RTW89_UKRAINE][10] = 48,
+ [1][1][2][0][RTW89_CHILE][10] = 46,
+ [1][1][2][0][RTW89_QATAR][10] = 48,
[1][1][2][0][RTW89_FCC][11] = 127,
[1][1][2][0][RTW89_ETSI][11] = 127,
[1][1][2][0][RTW89_MKK][11] = 127,
@@ -29978,6 +33566,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][11] = 127,
[1][1][2][0][RTW89_CN][11] = 127,
[1][1][2][0][RTW89_UK][11] = 127,
+ [1][1][2][0][RTW89_MEXICO][11] = 127,
+ [1][1][2][0][RTW89_UKRAINE][11] = 127,
+ [1][1][2][0][RTW89_CHILE][11] = 127,
+ [1][1][2][0][RTW89_QATAR][11] = 127,
[1][1][2][0][RTW89_FCC][12] = 127,
[1][1][2][0][RTW89_ETSI][12] = 127,
[1][1][2][0][RTW89_MKK][12] = 127,
@@ -29986,6 +33578,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][12] = 127,
[1][1][2][0][RTW89_CN][12] = 127,
[1][1][2][0][RTW89_UK][12] = 127,
+ [1][1][2][0][RTW89_MEXICO][12] = 127,
+ [1][1][2][0][RTW89_UKRAINE][12] = 127,
+ [1][1][2][0][RTW89_CHILE][12] = 127,
+ [1][1][2][0][RTW89_QATAR][12] = 127,
[1][1][2][0][RTW89_FCC][13] = 127,
[1][1][2][0][RTW89_ETSI][13] = 127,
[1][1][2][0][RTW89_MKK][13] = 127,
@@ -29994,6 +33590,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][13] = 127,
[1][1][2][0][RTW89_CN][13] = 127,
[1][1][2][0][RTW89_UK][13] = 127,
+ [1][1][2][0][RTW89_MEXICO][13] = 127,
+ [1][1][2][0][RTW89_UKRAINE][13] = 127,
+ [1][1][2][0][RTW89_CHILE][13] = 127,
+ [1][1][2][0][RTW89_QATAR][13] = 127,
[1][1][2][1][RTW89_FCC][0] = 127,
[1][1][2][1][RTW89_ETSI][0] = 127,
[1][1][2][1][RTW89_MKK][0] = 127,
@@ -30002,6 +33602,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][0] = 127,
[1][1][2][1][RTW89_CN][0] = 127,
[1][1][2][1][RTW89_UK][0] = 127,
+ [1][1][2][1][RTW89_MEXICO][0] = 127,
+ [1][1][2][1][RTW89_UKRAINE][0] = 127,
+ [1][1][2][1][RTW89_CHILE][0] = 127,
+ [1][1][2][1][RTW89_QATAR][0] = 127,
[1][1][2][1][RTW89_FCC][1] = 127,
[1][1][2][1][RTW89_ETSI][1] = 127,
[1][1][2][1][RTW89_MKK][1] = 127,
@@ -30010,6 +33614,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][1] = 127,
[1][1][2][1][RTW89_CN][1] = 127,
[1][1][2][1][RTW89_UK][1] = 127,
+ [1][1][2][1][RTW89_MEXICO][1] = 127,
+ [1][1][2][1][RTW89_UKRAINE][1] = 127,
+ [1][1][2][1][RTW89_CHILE][1] = 127,
+ [1][1][2][1][RTW89_QATAR][1] = 127,
[1][1][2][1][RTW89_FCC][2] = 60,
[1][1][2][1][RTW89_ETSI][2] = 36,
[1][1][2][1][RTW89_MKK][2] = 68,
@@ -30018,6 +33626,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][2] = 36,
[1][1][2][1][RTW89_CN][2] = 34,
[1][1][2][1][RTW89_UK][2] = 36,
+ [1][1][2][1][RTW89_MEXICO][2] = 60,
+ [1][1][2][1][RTW89_UKRAINE][2] = 36,
+ [1][1][2][1][RTW89_CHILE][2] = 60,
+ [1][1][2][1][RTW89_QATAR][2] = 36,
[1][1][2][1][RTW89_FCC][3] = 60,
[1][1][2][1][RTW89_ETSI][3] = 36,
[1][1][2][1][RTW89_MKK][3] = 68,
@@ -30026,6 +33638,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][3] = 36,
[1][1][2][1][RTW89_CN][3] = 34,
[1][1][2][1][RTW89_UK][3] = 36,
+ [1][1][2][1][RTW89_MEXICO][3] = 60,
+ [1][1][2][1][RTW89_UKRAINE][3] = 36,
+ [1][1][2][1][RTW89_CHILE][3] = 44,
+ [1][1][2][1][RTW89_QATAR][3] = 36,
[1][1][2][1][RTW89_FCC][4] = 60,
[1][1][2][1][RTW89_ETSI][4] = 36,
[1][1][2][1][RTW89_MKK][4] = 68,
@@ -30034,6 +33650,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][4] = 36,
[1][1][2][1][RTW89_CN][4] = 34,
[1][1][2][1][RTW89_UK][4] = 36,
+ [1][1][2][1][RTW89_MEXICO][4] = 60,
+ [1][1][2][1][RTW89_UKRAINE][4] = 36,
+ [1][1][2][1][RTW89_CHILE][4] = 44,
+ [1][1][2][1][RTW89_QATAR][4] = 36,
[1][1][2][1][RTW89_FCC][5] = 60,
[1][1][2][1][RTW89_ETSI][5] = 36,
[1][1][2][1][RTW89_MKK][5] = 68,
@@ -30042,6 +33662,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][5] = 36,
[1][1][2][1][RTW89_CN][5] = 34,
[1][1][2][1][RTW89_UK][5] = 36,
+ [1][1][2][1][RTW89_MEXICO][5] = 60,
+ [1][1][2][1][RTW89_UKRAINE][5] = 36,
+ [1][1][2][1][RTW89_CHILE][5] = 60,
+ [1][1][2][1][RTW89_QATAR][5] = 36,
[1][1][2][1][RTW89_FCC][6] = 58,
[1][1][2][1][RTW89_ETSI][6] = 36,
[1][1][2][1][RTW89_MKK][6] = 68,
@@ -30050,6 +33674,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][6] = 36,
[1][1][2][1][RTW89_CN][6] = 34,
[1][1][2][1][RTW89_UK][6] = 36,
+ [1][1][2][1][RTW89_MEXICO][6] = 58,
+ [1][1][2][1][RTW89_UKRAINE][6] = 36,
+ [1][1][2][1][RTW89_CHILE][6] = 40,
+ [1][1][2][1][RTW89_QATAR][6] = 36,
[1][1][2][1][RTW89_FCC][7] = 54,
[1][1][2][1][RTW89_ETSI][7] = 36,
[1][1][2][1][RTW89_MKK][7] = 68,
@@ -30058,6 +33686,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][7] = 36,
[1][1][2][1][RTW89_CN][7] = 34,
[1][1][2][1][RTW89_UK][7] = 36,
+ [1][1][2][1][RTW89_MEXICO][7] = 54,
+ [1][1][2][1][RTW89_UKRAINE][7] = 36,
+ [1][1][2][1][RTW89_CHILE][7] = 40,
+ [1][1][2][1][RTW89_QATAR][7] = 36,
[1][1][2][1][RTW89_FCC][8] = 54,
[1][1][2][1][RTW89_ETSI][8] = 36,
[1][1][2][1][RTW89_MKK][8] = 68,
@@ -30066,6 +33698,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][8] = 36,
[1][1][2][1][RTW89_CN][8] = 34,
[1][1][2][1][RTW89_UK][8] = 36,
+ [1][1][2][1][RTW89_MEXICO][8] = 54,
+ [1][1][2][1][RTW89_UKRAINE][8] = 36,
+ [1][1][2][1][RTW89_CHILE][8] = 54,
+ [1][1][2][1][RTW89_QATAR][8] = 36,
[1][1][2][1][RTW89_FCC][9] = 54,
[1][1][2][1][RTW89_ETSI][9] = 36,
[1][1][2][1][RTW89_MKK][9] = 68,
@@ -30074,6 +33710,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][9] = 36,
[1][1][2][1][RTW89_CN][9] = 34,
[1][1][2][1][RTW89_UK][9] = 36,
+ [1][1][2][1][RTW89_MEXICO][9] = 54,
+ [1][1][2][1][RTW89_UKRAINE][9] = 36,
+ [1][1][2][1][RTW89_CHILE][9] = 54,
+ [1][1][2][1][RTW89_QATAR][9] = 36,
[1][1][2][1][RTW89_FCC][10] = 46,
[1][1][2][1][RTW89_ETSI][10] = 36,
[1][1][2][1][RTW89_MKK][10] = 68,
@@ -30082,6 +33722,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][10] = 36,
[1][1][2][1][RTW89_CN][10] = 36,
[1][1][2][1][RTW89_UK][10] = 36,
+ [1][1][2][1][RTW89_MEXICO][10] = 46,
+ [1][1][2][1][RTW89_UKRAINE][10] = 36,
+ [1][1][2][1][RTW89_CHILE][10] = 46,
+ [1][1][2][1][RTW89_QATAR][10] = 36,
[1][1][2][1][RTW89_FCC][11] = 127,
[1][1][2][1][RTW89_ETSI][11] = 127,
[1][1][2][1][RTW89_MKK][11] = 127,
@@ -30090,6 +33734,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][11] = 127,
[1][1][2][1][RTW89_CN][11] = 127,
[1][1][2][1][RTW89_UK][11] = 127,
+ [1][1][2][1][RTW89_MEXICO][11] = 127,
+ [1][1][2][1][RTW89_UKRAINE][11] = 127,
+ [1][1][2][1][RTW89_CHILE][11] = 127,
+ [1][1][2][1][RTW89_QATAR][11] = 127,
[1][1][2][1][RTW89_FCC][12] = 127,
[1][1][2][1][RTW89_ETSI][12] = 127,
[1][1][2][1][RTW89_MKK][12] = 127,
@@ -30098,6 +33746,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][12] = 127,
[1][1][2][1][RTW89_CN][12] = 127,
[1][1][2][1][RTW89_UK][12] = 127,
+ [1][1][2][1][RTW89_MEXICO][12] = 127,
+ [1][1][2][1][RTW89_UKRAINE][12] = 127,
+ [1][1][2][1][RTW89_CHILE][12] = 127,
+ [1][1][2][1][RTW89_QATAR][12] = 127,
[1][1][2][1][RTW89_FCC][13] = 127,
[1][1][2][1][RTW89_ETSI][13] = 127,
[1][1][2][1][RTW89_MKK][13] = 127,
@@ -30106,6 +33758,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][13] = 127,
[1][1][2][1][RTW89_CN][13] = 127,
[1][1][2][1][RTW89_UK][13] = 127,
+ [1][1][2][1][RTW89_MEXICO][13] = 127,
+ [1][1][2][1][RTW89_UKRAINE][13] = 127,
+ [1][1][2][1][RTW89_CHILE][13] = 127,
+ [1][1][2][1][RTW89_QATAR][13] = 127,
};
static
@@ -30120,17 +33776,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_WW][10] = 50,
[0][0][1][0][RTW89_WW][12] = 50,
[0][0][1][0][RTW89_WW][14] = 50,
- [0][0][1][0][RTW89_WW][15] = 66,
- [0][0][1][0][RTW89_WW][17] = 66,
- [0][0][1][0][RTW89_WW][19] = 66,
- [0][0][1][0][RTW89_WW][21] = 66,
- [0][0][1][0][RTW89_WW][23] = 66,
- [0][0][1][0][RTW89_WW][25] = 66,
- [0][0][1][0][RTW89_WW][27] = 66,
- [0][0][1][0][RTW89_WW][29] = 66,
- [0][0][1][0][RTW89_WW][31] = 66,
- [0][0][1][0][RTW89_WW][33] = 66,
- [0][0][1][0][RTW89_WW][35] = 60,
+ [0][0][1][0][RTW89_WW][15] = 54,
+ [0][0][1][0][RTW89_WW][17] = 54,
+ [0][0][1][0][RTW89_WW][19] = 54,
+ [0][0][1][0][RTW89_WW][21] = 54,
+ [0][0][1][0][RTW89_WW][23] = 54,
+ [0][0][1][0][RTW89_WW][25] = 54,
+ [0][0][1][0][RTW89_WW][27] = 54,
+ [0][0][1][0][RTW89_WW][29] = 54,
+ [0][0][1][0][RTW89_WW][31] = 54,
+ [0][0][1][0][RTW89_WW][33] = 54,
+ [0][0][1][0][RTW89_WW][35] = 54,
[0][0][1][0][RTW89_WW][37] = 64,
[0][0][1][0][RTW89_WW][38] = 30,
[0][0][1][0][RTW89_WW][40] = 30,
@@ -30144,21 +33800,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_WW][2] = 34,
[0][1][1][0][RTW89_WW][4] = 34,
[0][1][1][0][RTW89_WW][6] = 36,
- [0][1][1][0][RTW89_WW][8] = 46,
- [0][1][1][0][RTW89_WW][10] = 46,
- [0][1][1][0][RTW89_WW][12] = 46,
- [0][1][1][0][RTW89_WW][14] = 46,
- [0][1][1][0][RTW89_WW][15] = 54,
- [0][1][1][0][RTW89_WW][17] = 54,
- [0][1][1][0][RTW89_WW][19] = 54,
- [0][1][1][0][RTW89_WW][21] = 54,
- [0][1][1][0][RTW89_WW][23] = 54,
- [0][1][1][0][RTW89_WW][25] = 54,
- [0][1][1][0][RTW89_WW][27] = 54,
- [0][1][1][0][RTW89_WW][29] = 54,
- [0][1][1][0][RTW89_WW][31] = 54,
- [0][1][1][0][RTW89_WW][33] = 54,
- [0][1][1][0][RTW89_WW][35] = 52,
+ [0][1][1][0][RTW89_WW][8] = 42,
+ [0][1][1][0][RTW89_WW][10] = 42,
+ [0][1][1][0][RTW89_WW][12] = 42,
+ [0][1][1][0][RTW89_WW][14] = 42,
+ [0][1][1][0][RTW89_WW][15] = 42,
+ [0][1][1][0][RTW89_WW][17] = 42,
+ [0][1][1][0][RTW89_WW][19] = 42,
+ [0][1][1][0][RTW89_WW][21] = 42,
+ [0][1][1][0][RTW89_WW][23] = 42,
+ [0][1][1][0][RTW89_WW][25] = 42,
+ [0][1][1][0][RTW89_WW][27] = 42,
+ [0][1][1][0][RTW89_WW][29] = 42,
+ [0][1][1][0][RTW89_WW][31] = 42,
+ [0][1][1][0][RTW89_WW][33] = 42,
+ [0][1][1][0][RTW89_WW][35] = 42,
[0][1][1][0][RTW89_WW][37] = 52,
[0][1][1][0][RTW89_WW][38] = 18,
[0][1][1][0][RTW89_WW][40] = 18,
@@ -30176,17 +33832,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_WW][10] = 52,
[0][0][2][0][RTW89_WW][12] = 52,
[0][0][2][0][RTW89_WW][14] = 52,
- [0][0][2][0][RTW89_WW][15] = 66,
- [0][0][2][0][RTW89_WW][17] = 66,
- [0][0][2][0][RTW89_WW][19] = 66,
- [0][0][2][0][RTW89_WW][21] = 66,
- [0][0][2][0][RTW89_WW][23] = 66,
- [0][0][2][0][RTW89_WW][25] = 66,
- [0][0][2][0][RTW89_WW][27] = 66,
- [0][0][2][0][RTW89_WW][29] = 66,
- [0][0][2][0][RTW89_WW][31] = 66,
- [0][0][2][0][RTW89_WW][33] = 66,
- [0][0][2][0][RTW89_WW][35] = 56,
+ [0][0][2][0][RTW89_WW][15] = 54,
+ [0][0][2][0][RTW89_WW][17] = 54,
+ [0][0][2][0][RTW89_WW][19] = 54,
+ [0][0][2][0][RTW89_WW][21] = 54,
+ [0][0][2][0][RTW89_WW][23] = 54,
+ [0][0][2][0][RTW89_WW][25] = 54,
+ [0][0][2][0][RTW89_WW][27] = 54,
+ [0][0][2][0][RTW89_WW][29] = 54,
+ [0][0][2][0][RTW89_WW][31] = 54,
+ [0][0][2][0][RTW89_WW][33] = 54,
+ [0][0][2][0][RTW89_WW][35] = 54,
[0][0][2][0][RTW89_WW][37] = 64,
[0][0][2][0][RTW89_WW][38] = 30,
[0][0][2][0][RTW89_WW][40] = 30,
@@ -30204,17 +33860,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_WW][10] = 40,
[0][1][2][0][RTW89_WW][12] = 40,
[0][1][2][0][RTW89_WW][14] = 40,
- [0][1][2][0][RTW89_WW][15] = 54,
- [0][1][2][0][RTW89_WW][17] = 54,
- [0][1][2][0][RTW89_WW][19] = 54,
- [0][1][2][0][RTW89_WW][21] = 54,
- [0][1][2][0][RTW89_WW][23] = 54,
- [0][1][2][0][RTW89_WW][25] = 54,
- [0][1][2][0][RTW89_WW][27] = 54,
- [0][1][2][0][RTW89_WW][29] = 54,
- [0][1][2][0][RTW89_WW][31] = 54,
- [0][1][2][0][RTW89_WW][33] = 54,
- [0][1][2][0][RTW89_WW][35] = 46,
+ [0][1][2][0][RTW89_WW][15] = 42,
+ [0][1][2][0][RTW89_WW][17] = 42,
+ [0][1][2][0][RTW89_WW][19] = 42,
+ [0][1][2][0][RTW89_WW][21] = 42,
+ [0][1][2][0][RTW89_WW][23] = 42,
+ [0][1][2][0][RTW89_WW][25] = 42,
+ [0][1][2][0][RTW89_WW][27] = 42,
+ [0][1][2][0][RTW89_WW][29] = 42,
+ [0][1][2][0][RTW89_WW][31] = 42,
+ [0][1][2][0][RTW89_WW][33] = 42,
+ [0][1][2][0][RTW89_WW][35] = 42,
[0][1][2][0][RTW89_WW][37] = 52,
[0][1][2][0][RTW89_WW][38] = 18,
[0][1][2][0][RTW89_WW][40] = 18,
@@ -30224,25 +33880,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_WW][48] = 48,
[0][1][2][0][RTW89_WW][50] = 50,
[0][1][2][0][RTW89_WW][52] = 48,
- [0][1][2][1][RTW89_WW][0] = 36,
- [0][1][2][1][RTW89_WW][2] = 36,
- [0][1][2][1][RTW89_WW][4] = 36,
- [0][1][2][1][RTW89_WW][6] = 36,
- [0][1][2][1][RTW89_WW][8] = 36,
- [0][1][2][1][RTW89_WW][10] = 36,
- [0][1][2][1][RTW89_WW][12] = 36,
- [0][1][2][1][RTW89_WW][14] = 36,
- [0][1][2][1][RTW89_WW][15] = 40,
- [0][1][2][1][RTW89_WW][17] = 40,
- [0][1][2][1][RTW89_WW][19] = 40,
- [0][1][2][1][RTW89_WW][21] = 40,
- [0][1][2][1][RTW89_WW][23] = 40,
- [0][1][2][1][RTW89_WW][25] = 40,
- [0][1][2][1][RTW89_WW][27] = 40,
- [0][1][2][1][RTW89_WW][29] = 40,
- [0][1][2][1][RTW89_WW][31] = 40,
- [0][1][2][1][RTW89_WW][33] = 40,
- [0][1][2][1][RTW89_WW][35] = 40,
+ [0][1][2][1][RTW89_WW][0] = 30,
+ [0][1][2][1][RTW89_WW][2] = 30,
+ [0][1][2][1][RTW89_WW][4] = 30,
+ [0][1][2][1][RTW89_WW][6] = 30,
+ [0][1][2][1][RTW89_WW][8] = 30,
+ [0][1][2][1][RTW89_WW][10] = 30,
+ [0][1][2][1][RTW89_WW][12] = 30,
+ [0][1][2][1][RTW89_WW][14] = 30,
+ [0][1][2][1][RTW89_WW][15] = 30,
+ [0][1][2][1][RTW89_WW][17] = 30,
+ [0][1][2][1][RTW89_WW][19] = 30,
+ [0][1][2][1][RTW89_WW][21] = 30,
+ [0][1][2][1][RTW89_WW][23] = 30,
+ [0][1][2][1][RTW89_WW][25] = 30,
+ [0][1][2][1][RTW89_WW][27] = 30,
+ [0][1][2][1][RTW89_WW][29] = 30,
+ [0][1][2][1][RTW89_WW][31] = 30,
+ [0][1][2][1][RTW89_WW][33] = 30,
+ [0][1][2][1][RTW89_WW][35] = 30,
[0][1][2][1][RTW89_WW][37] = 40,
[0][1][2][1][RTW89_WW][38] = 6,
[0][1][2][1][RTW89_WW][40] = 6,
@@ -30256,11 +33912,11 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_WW][5] = 54,
[1][0][2][0][RTW89_WW][9] = 54,
[1][0][2][0][RTW89_WW][13] = 52,
- [1][0][2][0][RTW89_WW][16] = 56,
- [1][0][2][0][RTW89_WW][20] = 56,
- [1][0][2][0][RTW89_WW][24] = 56,
- [1][0][2][0][RTW89_WW][28] = 66,
- [1][0][2][0][RTW89_WW][32] = 62,
+ [1][0][2][0][RTW89_WW][16] = 54,
+ [1][0][2][0][RTW89_WW][20] = 54,
+ [1][0][2][0][RTW89_WW][24] = 54,
+ [1][0][2][0][RTW89_WW][28] = 54,
+ [1][0][2][0][RTW89_WW][32] = 54,
[1][0][2][0][RTW89_WW][36] = 64,
[1][0][2][0][RTW89_WW][39] = 30,
[1][0][2][0][RTW89_WW][43] = 30,
@@ -30270,25 +33926,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_WW][5] = 42,
[1][1][2][0][RTW89_WW][9] = 42,
[1][1][2][0][RTW89_WW][13] = 42,
- [1][1][2][0][RTW89_WW][16] = 54,
- [1][1][2][0][RTW89_WW][20] = 54,
- [1][1][2][0][RTW89_WW][24] = 54,
- [1][1][2][0][RTW89_WW][28] = 54,
- [1][1][2][0][RTW89_WW][32] = 54,
+ [1][1][2][0][RTW89_WW][16] = 42,
+ [1][1][2][0][RTW89_WW][20] = 42,
+ [1][1][2][0][RTW89_WW][24] = 42,
+ [1][1][2][0][RTW89_WW][28] = 42,
+ [1][1][2][0][RTW89_WW][32] = 42,
[1][1][2][0][RTW89_WW][36] = 52,
[1][1][2][0][RTW89_WW][39] = 18,
[1][1][2][0][RTW89_WW][43] = 18,
[1][1][2][0][RTW89_WW][47] = 62,
[1][1][2][0][RTW89_WW][51] = 60,
- [1][1][2][1][RTW89_WW][1] = 40,
- [1][1][2][1][RTW89_WW][5] = 40,
- [1][1][2][1][RTW89_WW][9] = 40,
- [1][1][2][1][RTW89_WW][13] = 40,
- [1][1][2][1][RTW89_WW][16] = 40,
- [1][1][2][1][RTW89_WW][20] = 40,
- [1][1][2][1][RTW89_WW][24] = 40,
- [1][1][2][1][RTW89_WW][28] = 40,
- [1][1][2][1][RTW89_WW][32] = 40,
+ [1][1][2][1][RTW89_WW][1] = 30,
+ [1][1][2][1][RTW89_WW][5] = 30,
+ [1][1][2][1][RTW89_WW][9] = 30,
+ [1][1][2][1][RTW89_WW][13] = 30,
+ [1][1][2][1][RTW89_WW][16] = 30,
+ [1][1][2][1][RTW89_WW][20] = 30,
+ [1][1][2][1][RTW89_WW][24] = 30,
+ [1][1][2][1][RTW89_WW][28] = 30,
+ [1][1][2][1][RTW89_WW][32] = 30,
[1][1][2][1][RTW89_WW][36] = 40,
[1][1][2][1][RTW89_WW][39] = 6,
[1][1][2][1][RTW89_WW][43] = 6,
@@ -30296,22 +33952,22 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_WW][51] = 60,
[2][0][2][0][RTW89_WW][3] = 54,
[2][0][2][0][RTW89_WW][11] = 50,
- [2][0][2][0][RTW89_WW][18] = 56,
- [2][0][2][0][RTW89_WW][26] = 60,
+ [2][0][2][0][RTW89_WW][18] = 54,
+ [2][0][2][0][RTW89_WW][26] = 54,
[2][0][2][0][RTW89_WW][34] = 60,
[2][0][2][0][RTW89_WW][41] = 30,
[2][0][2][0][RTW89_WW][49] = 62,
- [2][1][2][0][RTW89_WW][3] = 46,
+ [2][1][2][0][RTW89_WW][3] = 42,
[2][1][2][0][RTW89_WW][11] = 38,
- [2][1][2][0][RTW89_WW][18] = 50,
- [2][1][2][0][RTW89_WW][26] = 52,
+ [2][1][2][0][RTW89_WW][18] = 42,
+ [2][1][2][0][RTW89_WW][26] = 42,
[2][1][2][0][RTW89_WW][34] = 52,
[2][1][2][0][RTW89_WW][41] = 18,
[2][1][2][0][RTW89_WW][49] = 62,
- [2][1][2][1][RTW89_WW][3] = 40,
- [2][1][2][1][RTW89_WW][11] = 38,
- [2][1][2][1][RTW89_WW][18] = 40,
- [2][1][2][1][RTW89_WW][26] = 42,
+ [2][1][2][1][RTW89_WW][3] = 30,
+ [2][1][2][1][RTW89_WW][11] = 30,
+ [2][1][2][1][RTW89_WW][18] = 30,
+ [2][1][2][1][RTW89_WW][26] = 30,
[2][1][2][1][RTW89_WW][34] = 40,
[2][1][2][1][RTW89_WW][41] = 6,
[2][1][2][1][RTW89_WW][49] = 62,
@@ -30328,34 +33984,50 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ETSI][0] = 66,
[0][0][1][0][RTW89_MKK][0] = 66,
[0][0][1][0][RTW89_IC][0] = 60,
- [0][0][1][0][RTW89_KCC][0] = 52,
+ [0][0][1][0][RTW89_KCC][0] = 62,
[0][0][1][0][RTW89_ACMA][0] = 66,
[0][0][1][0][RTW89_CN][0] = 50,
[0][0][1][0][RTW89_UK][0] = 66,
+ [0][0][1][0][RTW89_MEXICO][0] = 62,
+ [0][0][1][0][RTW89_UKRAINE][0] = 54,
+ [0][0][1][0][RTW89_CHILE][0] = 70,
+ [0][0][1][0][RTW89_QATAR][0] = 66,
[0][0][1][0][RTW89_FCC][2] = 72,
[0][0][1][0][RTW89_ETSI][2] = 66,
[0][0][1][0][RTW89_MKK][2] = 66,
[0][0][1][0][RTW89_IC][2] = 60,
- [0][0][1][0][RTW89_KCC][2] = 52,
+ [0][0][1][0][RTW89_KCC][2] = 62,
[0][0][1][0][RTW89_ACMA][2] = 66,
[0][0][1][0][RTW89_CN][2] = 50,
[0][0][1][0][RTW89_UK][2] = 66,
+ [0][0][1][0][RTW89_MEXICO][2] = 62,
+ [0][0][1][0][RTW89_UKRAINE][2] = 54,
+ [0][0][1][0][RTW89_CHILE][2] = 70,
+ [0][0][1][0][RTW89_QATAR][2] = 66,
[0][0][1][0][RTW89_FCC][4] = 72,
[0][0][1][0][RTW89_ETSI][4] = 66,
[0][0][1][0][RTW89_MKK][4] = 66,
[0][0][1][0][RTW89_IC][4] = 60,
- [0][0][1][0][RTW89_KCC][4] = 52,
+ [0][0][1][0][RTW89_KCC][4] = 62,
[0][0][1][0][RTW89_ACMA][4] = 66,
[0][0][1][0][RTW89_CN][4] = 50,
[0][0][1][0][RTW89_UK][4] = 66,
+ [0][0][1][0][RTW89_MEXICO][4] = 62,
+ [0][0][1][0][RTW89_UKRAINE][4] = 54,
+ [0][0][1][0][RTW89_CHILE][4] = 70,
+ [0][0][1][0][RTW89_QATAR][4] = 66,
[0][0][1][0][RTW89_FCC][6] = 72,
[0][0][1][0][RTW89_ETSI][6] = 66,
[0][0][1][0][RTW89_MKK][6] = 66,
[0][0][1][0][RTW89_IC][6] = 58,
- [0][0][1][0][RTW89_KCC][6] = 62,
+ [0][0][1][0][RTW89_KCC][6] = 52,
[0][0][1][0][RTW89_ACMA][6] = 66,
[0][0][1][0][RTW89_CN][6] = 50,
[0][0][1][0][RTW89_UK][6] = 66,
+ [0][0][1][0][RTW89_MEXICO][6] = 62,
+ [0][0][1][0][RTW89_UKRAINE][6] = 54,
+ [0][0][1][0][RTW89_CHILE][6] = 70,
+ [0][0][1][0][RTW89_QATAR][6] = 66,
[0][0][1][0][RTW89_FCC][8] = 72,
[0][0][1][0][RTW89_ETSI][8] = 66,
[0][0][1][0][RTW89_MKK][8] = 66,
@@ -30364,6 +34036,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][8] = 66,
[0][0][1][0][RTW89_CN][8] = 50,
[0][0][1][0][RTW89_UK][8] = 66,
+ [0][0][1][0][RTW89_MEXICO][8] = 72,
+ [0][0][1][0][RTW89_UKRAINE][8] = 54,
+ [0][0][1][0][RTW89_CHILE][8] = 70,
+ [0][0][1][0][RTW89_QATAR][8] = 66,
[0][0][1][0][RTW89_FCC][10] = 72,
[0][0][1][0][RTW89_ETSI][10] = 66,
[0][0][1][0][RTW89_MKK][10] = 66,
@@ -30372,6 +34048,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][10] = 66,
[0][0][1][0][RTW89_CN][10] = 50,
[0][0][1][0][RTW89_UK][10] = 66,
+ [0][0][1][0][RTW89_MEXICO][10] = 72,
+ [0][0][1][0][RTW89_UKRAINE][10] = 54,
+ [0][0][1][0][RTW89_CHILE][10] = 70,
+ [0][0][1][0][RTW89_QATAR][10] = 66,
[0][0][1][0][RTW89_FCC][12] = 72,
[0][0][1][0][RTW89_ETSI][12] = 66,
[0][0][1][0][RTW89_MKK][12] = 66,
@@ -30380,6 +34060,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][12] = 66,
[0][0][1][0][RTW89_CN][12] = 50,
[0][0][1][0][RTW89_UK][12] = 66,
+ [0][0][1][0][RTW89_MEXICO][12] = 72,
+ [0][0][1][0][RTW89_UKRAINE][12] = 54,
+ [0][0][1][0][RTW89_CHILE][12] = 70,
+ [0][0][1][0][RTW89_QATAR][12] = 66,
[0][0][1][0][RTW89_FCC][14] = 70,
[0][0][1][0][RTW89_ETSI][14] = 66,
[0][0][1][0][RTW89_MKK][14] = 66,
@@ -30388,6 +34072,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][14] = 66,
[0][0][1][0][RTW89_CN][14] = 50,
[0][0][1][0][RTW89_UK][14] = 66,
+ [0][0][1][0][RTW89_MEXICO][14] = 70,
+ [0][0][1][0][RTW89_UKRAINE][14] = 54,
+ [0][0][1][0][RTW89_CHILE][14] = 68,
+ [0][0][1][0][RTW89_QATAR][14] = 66,
[0][0][1][0][RTW89_FCC][15] = 72,
[0][0][1][0][RTW89_ETSI][15] = 66,
[0][0][1][0][RTW89_MKK][15] = 70,
@@ -30396,6 +34084,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][15] = 66,
[0][0][1][0][RTW89_CN][15] = 127,
[0][0][1][0][RTW89_UK][15] = 66,
+ [0][0][1][0][RTW89_MEXICO][15] = 72,
+ [0][0][1][0][RTW89_UKRAINE][15] = 54,
+ [0][0][1][0][RTW89_CHILE][15] = 70,
+ [0][0][1][0][RTW89_QATAR][15] = 66,
[0][0][1][0][RTW89_FCC][17] = 72,
[0][0][1][0][RTW89_ETSI][17] = 66,
[0][0][1][0][RTW89_MKK][17] = 70,
@@ -30404,6 +34096,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][17] = 66,
[0][0][1][0][RTW89_CN][17] = 127,
[0][0][1][0][RTW89_UK][17] = 66,
+ [0][0][1][0][RTW89_MEXICO][17] = 72,
+ [0][0][1][0][RTW89_UKRAINE][17] = 54,
+ [0][0][1][0][RTW89_CHILE][17] = 70,
+ [0][0][1][0][RTW89_QATAR][17] = 66,
[0][0][1][0][RTW89_FCC][19] = 72,
[0][0][1][0][RTW89_ETSI][19] = 66,
[0][0][1][0][RTW89_MKK][19] = 70,
@@ -30412,6 +34108,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][19] = 66,
[0][0][1][0][RTW89_CN][19] = 127,
[0][0][1][0][RTW89_UK][19] = 66,
+ [0][0][1][0][RTW89_MEXICO][19] = 72,
+ [0][0][1][0][RTW89_UKRAINE][19] = 54,
+ [0][0][1][0][RTW89_CHILE][19] = 70,
+ [0][0][1][0][RTW89_QATAR][19] = 66,
[0][0][1][0][RTW89_FCC][21] = 72,
[0][0][1][0][RTW89_ETSI][21] = 66,
[0][0][1][0][RTW89_MKK][21] = 70,
@@ -30420,6 +34120,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][21] = 66,
[0][0][1][0][RTW89_CN][21] = 127,
[0][0][1][0][RTW89_UK][21] = 66,
+ [0][0][1][0][RTW89_MEXICO][21] = 72,
+ [0][0][1][0][RTW89_UKRAINE][21] = 54,
+ [0][0][1][0][RTW89_CHILE][21] = 70,
+ [0][0][1][0][RTW89_QATAR][21] = 66,
[0][0][1][0][RTW89_FCC][23] = 72,
[0][0][1][0][RTW89_ETSI][23] = 66,
[0][0][1][0][RTW89_MKK][23] = 70,
@@ -30428,6 +34132,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][23] = 66,
[0][0][1][0][RTW89_CN][23] = 127,
[0][0][1][0][RTW89_UK][23] = 66,
+ [0][0][1][0][RTW89_MEXICO][23] = 72,
+ [0][0][1][0][RTW89_UKRAINE][23] = 54,
+ [0][0][1][0][RTW89_CHILE][23] = 70,
+ [0][0][1][0][RTW89_QATAR][23] = 66,
[0][0][1][0][RTW89_FCC][25] = 72,
[0][0][1][0][RTW89_ETSI][25] = 66,
[0][0][1][0][RTW89_MKK][25] = 70,
@@ -30436,6 +34144,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][25] = 127,
[0][0][1][0][RTW89_CN][25] = 127,
[0][0][1][0][RTW89_UK][25] = 66,
+ [0][0][1][0][RTW89_MEXICO][25] = 72,
+ [0][0][1][0][RTW89_UKRAINE][25] = 54,
+ [0][0][1][0][RTW89_CHILE][25] = 70,
+ [0][0][1][0][RTW89_QATAR][25] = 66,
[0][0][1][0][RTW89_FCC][27] = 72,
[0][0][1][0][RTW89_ETSI][27] = 66,
[0][0][1][0][RTW89_MKK][27] = 70,
@@ -30444,6 +34156,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][27] = 127,
[0][0][1][0][RTW89_CN][27] = 127,
[0][0][1][0][RTW89_UK][27] = 66,
+ [0][0][1][0][RTW89_MEXICO][27] = 72,
+ [0][0][1][0][RTW89_UKRAINE][27] = 54,
+ [0][0][1][0][RTW89_CHILE][27] = 58,
+ [0][0][1][0][RTW89_QATAR][27] = 66,
[0][0][1][0][RTW89_FCC][29] = 72,
[0][0][1][0][RTW89_ETSI][29] = 66,
[0][0][1][0][RTW89_MKK][29] = 70,
@@ -30452,6 +34168,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][29] = 127,
[0][0][1][0][RTW89_CN][29] = 127,
[0][0][1][0][RTW89_UK][29] = 66,
+ [0][0][1][0][RTW89_MEXICO][29] = 72,
+ [0][0][1][0][RTW89_UKRAINE][29] = 54,
+ [0][0][1][0][RTW89_CHILE][29] = 58,
+ [0][0][1][0][RTW89_QATAR][29] = 66,
[0][0][1][0][RTW89_FCC][31] = 72,
[0][0][1][0][RTW89_ETSI][31] = 66,
[0][0][1][0][RTW89_MKK][31] = 70,
@@ -30460,6 +34180,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][31] = 66,
[0][0][1][0][RTW89_CN][31] = 127,
[0][0][1][0][RTW89_UK][31] = 66,
+ [0][0][1][0][RTW89_MEXICO][31] = 72,
+ [0][0][1][0][RTW89_UKRAINE][31] = 54,
+ [0][0][1][0][RTW89_CHILE][31] = 58,
+ [0][0][1][0][RTW89_QATAR][31] = 66,
[0][0][1][0][RTW89_FCC][33] = 72,
[0][0][1][0][RTW89_ETSI][33] = 66,
[0][0][1][0][RTW89_MKK][33] = 70,
@@ -30468,6 +34192,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][33] = 66,
[0][0][1][0][RTW89_CN][33] = 127,
[0][0][1][0][RTW89_UK][33] = 66,
+ [0][0][1][0][RTW89_MEXICO][33] = 72,
+ [0][0][1][0][RTW89_UKRAINE][33] = 54,
+ [0][0][1][0][RTW89_CHILE][33] = 58,
+ [0][0][1][0][RTW89_QATAR][33] = 66,
[0][0][1][0][RTW89_FCC][35] = 60,
[0][0][1][0][RTW89_ETSI][35] = 66,
[0][0][1][0][RTW89_MKK][35] = 70,
@@ -30476,6 +34204,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][35] = 66,
[0][0][1][0][RTW89_CN][35] = 127,
[0][0][1][0][RTW89_UK][35] = 66,
+ [0][0][1][0][RTW89_MEXICO][35] = 60,
+ [0][0][1][0][RTW89_UKRAINE][35] = 54,
+ [0][0][1][0][RTW89_CHILE][35] = 58,
+ [0][0][1][0][RTW89_QATAR][35] = 66,
[0][0][1][0][RTW89_FCC][37] = 72,
[0][0][1][0][RTW89_ETSI][37] = 127,
[0][0][1][0][RTW89_MKK][37] = 70,
@@ -30484,6 +34216,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][37] = 70,
[0][0][1][0][RTW89_CN][37] = 127,
[0][0][1][0][RTW89_UK][37] = 64,
+ [0][0][1][0][RTW89_MEXICO][37] = 72,
+ [0][0][1][0][RTW89_UKRAINE][37] = 127,
+ [0][0][1][0][RTW89_CHILE][37] = 70,
+ [0][0][1][0][RTW89_QATAR][37] = 127,
[0][0][1][0][RTW89_FCC][38] = 72,
[0][0][1][0][RTW89_ETSI][38] = 30,
[0][0][1][0][RTW89_MKK][38] = 127,
@@ -30492,6 +34228,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][38] = 70,
[0][0][1][0][RTW89_CN][38] = 68,
[0][0][1][0][RTW89_UK][38] = 64,
+ [0][0][1][0][RTW89_MEXICO][38] = 72,
+ [0][0][1][0][RTW89_UKRAINE][38] = 30,
+ [0][0][1][0][RTW89_CHILE][38] = 70,
+ [0][0][1][0][RTW89_QATAR][38] = 30,
[0][0][1][0][RTW89_FCC][40] = 72,
[0][0][1][0][RTW89_ETSI][40] = 30,
[0][0][1][0][RTW89_MKK][40] = 127,
@@ -30500,6 +34240,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][40] = 70,
[0][0][1][0][RTW89_CN][40] = 68,
[0][0][1][0][RTW89_UK][40] = 64,
+ [0][0][1][0][RTW89_MEXICO][40] = 72,
+ [0][0][1][0][RTW89_UKRAINE][40] = 30,
+ [0][0][1][0][RTW89_CHILE][40] = 70,
+ [0][0][1][0][RTW89_QATAR][40] = 30,
[0][0][1][0][RTW89_FCC][42] = 72,
[0][0][1][0][RTW89_ETSI][42] = 30,
[0][0][1][0][RTW89_MKK][42] = 127,
@@ -30508,6 +34252,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][42] = 70,
[0][0][1][0][RTW89_CN][42] = 68,
[0][0][1][0][RTW89_UK][42] = 64,
+ [0][0][1][0][RTW89_MEXICO][42] = 72,
+ [0][0][1][0][RTW89_UKRAINE][42] = 30,
+ [0][0][1][0][RTW89_CHILE][42] = 70,
+ [0][0][1][0][RTW89_QATAR][42] = 30,
[0][0][1][0][RTW89_FCC][44] = 72,
[0][0][1][0][RTW89_ETSI][44] = 30,
[0][0][1][0][RTW89_MKK][44] = 127,
@@ -30516,6 +34264,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][44] = 70,
[0][0][1][0][RTW89_CN][44] = 68,
[0][0][1][0][RTW89_UK][44] = 64,
+ [0][0][1][0][RTW89_MEXICO][44] = 72,
+ [0][0][1][0][RTW89_UKRAINE][44] = 30,
+ [0][0][1][0][RTW89_CHILE][44] = 70,
+ [0][0][1][0][RTW89_QATAR][44] = 30,
[0][0][1][0][RTW89_FCC][46] = 72,
[0][0][1][0][RTW89_ETSI][46] = 30,
[0][0][1][0][RTW89_MKK][46] = 127,
@@ -30524,6 +34276,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][46] = 70,
[0][0][1][0][RTW89_CN][46] = 68,
[0][0][1][0][RTW89_UK][46] = 64,
+ [0][0][1][0][RTW89_MEXICO][46] = 72,
+ [0][0][1][0][RTW89_UKRAINE][46] = 30,
+ [0][0][1][0][RTW89_CHILE][46] = 70,
+ [0][0][1][0][RTW89_QATAR][46] = 30,
[0][0][1][0][RTW89_FCC][48] = 72,
[0][0][1][0][RTW89_ETSI][48] = 127,
[0][0][1][0][RTW89_MKK][48] = 127,
@@ -30532,6 +34288,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][48] = 127,
[0][0][1][0][RTW89_CN][48] = 127,
[0][0][1][0][RTW89_UK][48] = 127,
+ [0][0][1][0][RTW89_MEXICO][48] = 127,
+ [0][0][1][0][RTW89_UKRAINE][48] = 127,
+ [0][0][1][0][RTW89_CHILE][48] = 127,
+ [0][0][1][0][RTW89_QATAR][48] = 127,
[0][0][1][0][RTW89_FCC][50] = 72,
[0][0][1][0][RTW89_ETSI][50] = 127,
[0][0][1][0][RTW89_MKK][50] = 127,
@@ -30540,6 +34300,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][50] = 127,
[0][0][1][0][RTW89_CN][50] = 127,
[0][0][1][0][RTW89_UK][50] = 127,
+ [0][0][1][0][RTW89_MEXICO][50] = 127,
+ [0][0][1][0][RTW89_UKRAINE][50] = 127,
+ [0][0][1][0][RTW89_CHILE][50] = 127,
+ [0][0][1][0][RTW89_QATAR][50] = 127,
[0][0][1][0][RTW89_FCC][52] = 72,
[0][0][1][0][RTW89_ETSI][52] = 127,
[0][0][1][0][RTW89_MKK][52] = 127,
@@ -30548,38 +34312,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][1][0][RTW89_ACMA][52] = 127,
[0][0][1][0][RTW89_CN][52] = 127,
[0][0][1][0][RTW89_UK][52] = 127,
+ [0][0][1][0][RTW89_MEXICO][52] = 127,
+ [0][0][1][0][RTW89_UKRAINE][52] = 127,
+ [0][0][1][0][RTW89_CHILE][52] = 127,
+ [0][0][1][0][RTW89_QATAR][52] = 127,
[0][1][1][0][RTW89_FCC][0] = 60,
[0][1][1][0][RTW89_ETSI][0] = 54,
[0][1][1][0][RTW89_MKK][0] = 54,
[0][1][1][0][RTW89_IC][0] = 34,
- [0][1][1][0][RTW89_KCC][0] = 40,
+ [0][1][1][0][RTW89_KCC][0] = 60,
[0][1][1][0][RTW89_ACMA][0] = 54,
[0][1][1][0][RTW89_CN][0] = 46,
[0][1][1][0][RTW89_UK][0] = 54,
+ [0][1][1][0][RTW89_MEXICO][0] = 50,
+ [0][1][1][0][RTW89_UKRAINE][0] = 42,
+ [0][1][1][0][RTW89_CHILE][0] = 60,
+ [0][1][1][0][RTW89_QATAR][0] = 54,
[0][1][1][0][RTW89_FCC][2] = 60,
[0][1][1][0][RTW89_ETSI][2] = 54,
[0][1][1][0][RTW89_MKK][2] = 54,
[0][1][1][0][RTW89_IC][2] = 34,
- [0][1][1][0][RTW89_KCC][2] = 40,
+ [0][1][1][0][RTW89_KCC][2] = 60,
[0][1][1][0][RTW89_ACMA][2] = 54,
[0][1][1][0][RTW89_CN][2] = 46,
[0][1][1][0][RTW89_UK][2] = 54,
+ [0][1][1][0][RTW89_MEXICO][2] = 50,
+ [0][1][1][0][RTW89_UKRAINE][2] = 42,
+ [0][1][1][0][RTW89_CHILE][2] = 60,
+ [0][1][1][0][RTW89_QATAR][2] = 54,
[0][1][1][0][RTW89_FCC][4] = 60,
[0][1][1][0][RTW89_ETSI][4] = 54,
[0][1][1][0][RTW89_MKK][4] = 54,
[0][1][1][0][RTW89_IC][4] = 34,
- [0][1][1][0][RTW89_KCC][4] = 40,
+ [0][1][1][0][RTW89_KCC][4] = 60,
[0][1][1][0][RTW89_ACMA][4] = 54,
[0][1][1][0][RTW89_CN][4] = 46,
[0][1][1][0][RTW89_UK][4] = 54,
+ [0][1][1][0][RTW89_MEXICO][4] = 50,
+ [0][1][1][0][RTW89_UKRAINE][4] = 42,
+ [0][1][1][0][RTW89_CHILE][4] = 60,
+ [0][1][1][0][RTW89_QATAR][4] = 54,
[0][1][1][0][RTW89_FCC][6] = 60,
[0][1][1][0][RTW89_ETSI][6] = 54,
[0][1][1][0][RTW89_MKK][6] = 54,
[0][1][1][0][RTW89_IC][6] = 36,
- [0][1][1][0][RTW89_KCC][6] = 60,
+ [0][1][1][0][RTW89_KCC][6] = 40,
[0][1][1][0][RTW89_ACMA][6] = 54,
[0][1][1][0][RTW89_CN][6] = 46,
[0][1][1][0][RTW89_UK][6] = 54,
+ [0][1][1][0][RTW89_MEXICO][6] = 50,
+ [0][1][1][0][RTW89_UKRAINE][6] = 42,
+ [0][1][1][0][RTW89_CHILE][6] = 60,
+ [0][1][1][0][RTW89_QATAR][6] = 54,
[0][1][1][0][RTW89_FCC][8] = 62,
[0][1][1][0][RTW89_ETSI][8] = 54,
[0][1][1][0][RTW89_MKK][8] = 52,
@@ -30588,6 +34372,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][8] = 54,
[0][1][1][0][RTW89_CN][8] = 46,
[0][1][1][0][RTW89_UK][8] = 54,
+ [0][1][1][0][RTW89_MEXICO][8] = 62,
+ [0][1][1][0][RTW89_UKRAINE][8] = 42,
+ [0][1][1][0][RTW89_CHILE][8] = 62,
+ [0][1][1][0][RTW89_QATAR][8] = 54,
[0][1][1][0][RTW89_FCC][10] = 62,
[0][1][1][0][RTW89_ETSI][10] = 54,
[0][1][1][0][RTW89_MKK][10] = 54,
@@ -30596,6 +34384,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][10] = 54,
[0][1][1][0][RTW89_CN][10] = 46,
[0][1][1][0][RTW89_UK][10] = 54,
+ [0][1][1][0][RTW89_MEXICO][10] = 62,
+ [0][1][1][0][RTW89_UKRAINE][10] = 42,
+ [0][1][1][0][RTW89_CHILE][10] = 62,
+ [0][1][1][0][RTW89_QATAR][10] = 54,
[0][1][1][0][RTW89_FCC][12] = 62,
[0][1][1][0][RTW89_ETSI][12] = 54,
[0][1][1][0][RTW89_MKK][12] = 54,
@@ -30604,6 +34396,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][12] = 54,
[0][1][1][0][RTW89_CN][12] = 46,
[0][1][1][0][RTW89_UK][12] = 54,
+ [0][1][1][0][RTW89_MEXICO][12] = 62,
+ [0][1][1][0][RTW89_UKRAINE][12] = 42,
+ [0][1][1][0][RTW89_CHILE][12] = 62,
+ [0][1][1][0][RTW89_QATAR][12] = 54,
[0][1][1][0][RTW89_FCC][14] = 60,
[0][1][1][0][RTW89_ETSI][14] = 54,
[0][1][1][0][RTW89_MKK][14] = 54,
@@ -30612,6 +34408,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][14] = 54,
[0][1][1][0][RTW89_CN][14] = 46,
[0][1][1][0][RTW89_UK][14] = 54,
+ [0][1][1][0][RTW89_MEXICO][14] = 60,
+ [0][1][1][0][RTW89_UKRAINE][14] = 42,
+ [0][1][1][0][RTW89_CHILE][14] = 60,
+ [0][1][1][0][RTW89_QATAR][14] = 54,
[0][1][1][0][RTW89_FCC][15] = 60,
[0][1][1][0][RTW89_ETSI][15] = 54,
[0][1][1][0][RTW89_MKK][15] = 70,
@@ -30620,6 +34420,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][15] = 54,
[0][1][1][0][RTW89_CN][15] = 127,
[0][1][1][0][RTW89_UK][15] = 54,
+ [0][1][1][0][RTW89_MEXICO][15] = 60,
+ [0][1][1][0][RTW89_UKRAINE][15] = 42,
+ [0][1][1][0][RTW89_CHILE][15] = 60,
+ [0][1][1][0][RTW89_QATAR][15] = 54,
[0][1][1][0][RTW89_FCC][17] = 60,
[0][1][1][0][RTW89_ETSI][17] = 54,
[0][1][1][0][RTW89_MKK][17] = 70,
@@ -30628,6 +34432,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][17] = 54,
[0][1][1][0][RTW89_CN][17] = 127,
[0][1][1][0][RTW89_UK][17] = 54,
+ [0][1][1][0][RTW89_MEXICO][17] = 60,
+ [0][1][1][0][RTW89_UKRAINE][17] = 42,
+ [0][1][1][0][RTW89_CHILE][17] = 60,
+ [0][1][1][0][RTW89_QATAR][17] = 54,
[0][1][1][0][RTW89_FCC][19] = 60,
[0][1][1][0][RTW89_ETSI][19] = 54,
[0][1][1][0][RTW89_MKK][19] = 70,
@@ -30636,6 +34444,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][19] = 54,
[0][1][1][0][RTW89_CN][19] = 127,
[0][1][1][0][RTW89_UK][19] = 54,
+ [0][1][1][0][RTW89_MEXICO][19] = 60,
+ [0][1][1][0][RTW89_UKRAINE][19] = 42,
+ [0][1][1][0][RTW89_CHILE][19] = 60,
+ [0][1][1][0][RTW89_QATAR][19] = 54,
[0][1][1][0][RTW89_FCC][21] = 60,
[0][1][1][0][RTW89_ETSI][21] = 54,
[0][1][1][0][RTW89_MKK][21] = 70,
@@ -30644,6 +34456,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][21] = 54,
[0][1][1][0][RTW89_CN][21] = 127,
[0][1][1][0][RTW89_UK][21] = 54,
+ [0][1][1][0][RTW89_MEXICO][21] = 60,
+ [0][1][1][0][RTW89_UKRAINE][21] = 42,
+ [0][1][1][0][RTW89_CHILE][21] = 60,
+ [0][1][1][0][RTW89_QATAR][21] = 54,
[0][1][1][0][RTW89_FCC][23] = 60,
[0][1][1][0][RTW89_ETSI][23] = 54,
[0][1][1][0][RTW89_MKK][23] = 70,
@@ -30652,6 +34468,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][23] = 54,
[0][1][1][0][RTW89_CN][23] = 127,
[0][1][1][0][RTW89_UK][23] = 54,
+ [0][1][1][0][RTW89_MEXICO][23] = 60,
+ [0][1][1][0][RTW89_UKRAINE][23] = 42,
+ [0][1][1][0][RTW89_CHILE][23] = 60,
+ [0][1][1][0][RTW89_QATAR][23] = 54,
[0][1][1][0][RTW89_FCC][25] = 60,
[0][1][1][0][RTW89_ETSI][25] = 54,
[0][1][1][0][RTW89_MKK][25] = 70,
@@ -30660,6 +34480,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][25] = 127,
[0][1][1][0][RTW89_CN][25] = 127,
[0][1][1][0][RTW89_UK][25] = 54,
+ [0][1][1][0][RTW89_MEXICO][25] = 60,
+ [0][1][1][0][RTW89_UKRAINE][25] = 42,
+ [0][1][1][0][RTW89_CHILE][25] = 60,
+ [0][1][1][0][RTW89_QATAR][25] = 54,
[0][1][1][0][RTW89_FCC][27] = 60,
[0][1][1][0][RTW89_ETSI][27] = 54,
[0][1][1][0][RTW89_MKK][27] = 70,
@@ -30668,6 +34492,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][27] = 127,
[0][1][1][0][RTW89_CN][27] = 127,
[0][1][1][0][RTW89_UK][27] = 54,
+ [0][1][1][0][RTW89_MEXICO][27] = 60,
+ [0][1][1][0][RTW89_UKRAINE][27] = 42,
+ [0][1][1][0][RTW89_CHILE][27] = 52,
+ [0][1][1][0][RTW89_QATAR][27] = 54,
[0][1][1][0][RTW89_FCC][29] = 60,
[0][1][1][0][RTW89_ETSI][29] = 54,
[0][1][1][0][RTW89_MKK][29] = 70,
@@ -30676,6 +34504,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][29] = 127,
[0][1][1][0][RTW89_CN][29] = 127,
[0][1][1][0][RTW89_UK][29] = 54,
+ [0][1][1][0][RTW89_MEXICO][29] = 60,
+ [0][1][1][0][RTW89_UKRAINE][29] = 42,
+ [0][1][1][0][RTW89_CHILE][29] = 52,
+ [0][1][1][0][RTW89_QATAR][29] = 54,
[0][1][1][0][RTW89_FCC][31] = 60,
[0][1][1][0][RTW89_ETSI][31] = 54,
[0][1][1][0][RTW89_MKK][31] = 70,
@@ -30684,6 +34516,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][31] = 54,
[0][1][1][0][RTW89_CN][31] = 127,
[0][1][1][0][RTW89_UK][31] = 54,
+ [0][1][1][0][RTW89_MEXICO][31] = 60,
+ [0][1][1][0][RTW89_UKRAINE][31] = 42,
+ [0][1][1][0][RTW89_CHILE][31] = 52,
+ [0][1][1][0][RTW89_QATAR][31] = 54,
[0][1][1][0][RTW89_FCC][33] = 60,
[0][1][1][0][RTW89_ETSI][33] = 54,
[0][1][1][0][RTW89_MKK][33] = 70,
@@ -30692,6 +34528,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][33] = 54,
[0][1][1][0][RTW89_CN][33] = 127,
[0][1][1][0][RTW89_UK][33] = 54,
+ [0][1][1][0][RTW89_MEXICO][33] = 60,
+ [0][1][1][0][RTW89_UKRAINE][33] = 42,
+ [0][1][1][0][RTW89_CHILE][33] = 52,
+ [0][1][1][0][RTW89_QATAR][33] = 54,
[0][1][1][0][RTW89_FCC][35] = 52,
[0][1][1][0][RTW89_ETSI][35] = 54,
[0][1][1][0][RTW89_MKK][35] = 70,
@@ -30700,6 +34540,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][35] = 54,
[0][1][1][0][RTW89_CN][35] = 127,
[0][1][1][0][RTW89_UK][35] = 54,
+ [0][1][1][0][RTW89_MEXICO][35] = 52,
+ [0][1][1][0][RTW89_UKRAINE][35] = 42,
+ [0][1][1][0][RTW89_CHILE][35] = 52,
+ [0][1][1][0][RTW89_QATAR][35] = 54,
[0][1][1][0][RTW89_FCC][37] = 62,
[0][1][1][0][RTW89_ETSI][37] = 127,
[0][1][1][0][RTW89_MKK][37] = 70,
@@ -30708,6 +34552,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][37] = 64,
[0][1][1][0][RTW89_CN][37] = 127,
[0][1][1][0][RTW89_UK][37] = 52,
+ [0][1][1][0][RTW89_MEXICO][37] = 62,
+ [0][1][1][0][RTW89_UKRAINE][37] = 127,
+ [0][1][1][0][RTW89_CHILE][37] = 62,
+ [0][1][1][0][RTW89_QATAR][37] = 127,
[0][1][1][0][RTW89_FCC][38] = 72,
[0][1][1][0][RTW89_ETSI][38] = 18,
[0][1][1][0][RTW89_MKK][38] = 127,
@@ -30716,6 +34564,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][38] = 70,
[0][1][1][0][RTW89_CN][38] = 64,
[0][1][1][0][RTW89_UK][38] = 52,
+ [0][1][1][0][RTW89_MEXICO][38] = 72,
+ [0][1][1][0][RTW89_UKRAINE][38] = 18,
+ [0][1][1][0][RTW89_CHILE][38] = 70,
+ [0][1][1][0][RTW89_QATAR][38] = 18,
[0][1][1][0][RTW89_FCC][40] = 72,
[0][1][1][0][RTW89_ETSI][40] = 18,
[0][1][1][0][RTW89_MKK][40] = 127,
@@ -30724,6 +34576,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][40] = 70,
[0][1][1][0][RTW89_CN][40] = 64,
[0][1][1][0][RTW89_UK][40] = 52,
+ [0][1][1][0][RTW89_MEXICO][40] = 72,
+ [0][1][1][0][RTW89_UKRAINE][40] = 18,
+ [0][1][1][0][RTW89_CHILE][40] = 70,
+ [0][1][1][0][RTW89_QATAR][40] = 18,
[0][1][1][0][RTW89_FCC][42] = 72,
[0][1][1][0][RTW89_ETSI][42] = 18,
[0][1][1][0][RTW89_MKK][42] = 127,
@@ -30732,6 +34588,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][42] = 70,
[0][1][1][0][RTW89_CN][42] = 64,
[0][1][1][0][RTW89_UK][42] = 52,
+ [0][1][1][0][RTW89_MEXICO][42] = 72,
+ [0][1][1][0][RTW89_UKRAINE][42] = 18,
+ [0][1][1][0][RTW89_CHILE][42] = 70,
+ [0][1][1][0][RTW89_QATAR][42] = 18,
[0][1][1][0][RTW89_FCC][44] = 72,
[0][1][1][0][RTW89_ETSI][44] = 18,
[0][1][1][0][RTW89_MKK][44] = 127,
@@ -30740,6 +34600,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][44] = 70,
[0][1][1][0][RTW89_CN][44] = 60,
[0][1][1][0][RTW89_UK][44] = 52,
+ [0][1][1][0][RTW89_MEXICO][44] = 72,
+ [0][1][1][0][RTW89_UKRAINE][44] = 18,
+ [0][1][1][0][RTW89_CHILE][44] = 70,
+ [0][1][1][0][RTW89_QATAR][44] = 18,
[0][1][1][0][RTW89_FCC][46] = 72,
[0][1][1][0][RTW89_ETSI][46] = 18,
[0][1][1][0][RTW89_MKK][46] = 127,
@@ -30748,6 +34612,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][46] = 70,
[0][1][1][0][RTW89_CN][46] = 60,
[0][1][1][0][RTW89_UK][46] = 52,
+ [0][1][1][0][RTW89_MEXICO][46] = 72,
+ [0][1][1][0][RTW89_UKRAINE][46] = 18,
+ [0][1][1][0][RTW89_CHILE][46] = 70,
+ [0][1][1][0][RTW89_QATAR][46] = 18,
[0][1][1][0][RTW89_FCC][48] = 48,
[0][1][1][0][RTW89_ETSI][48] = 127,
[0][1][1][0][RTW89_MKK][48] = 127,
@@ -30756,6 +34624,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][48] = 127,
[0][1][1][0][RTW89_CN][48] = 127,
[0][1][1][0][RTW89_UK][48] = 127,
+ [0][1][1][0][RTW89_MEXICO][48] = 127,
+ [0][1][1][0][RTW89_UKRAINE][48] = 127,
+ [0][1][1][0][RTW89_CHILE][48] = 127,
+ [0][1][1][0][RTW89_QATAR][48] = 127,
[0][1][1][0][RTW89_FCC][50] = 48,
[0][1][1][0][RTW89_ETSI][50] = 127,
[0][1][1][0][RTW89_MKK][50] = 127,
@@ -30764,6 +34636,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][50] = 127,
[0][1][1][0][RTW89_CN][50] = 127,
[0][1][1][0][RTW89_UK][50] = 127,
+ [0][1][1][0][RTW89_MEXICO][50] = 127,
+ [0][1][1][0][RTW89_UKRAINE][50] = 127,
+ [0][1][1][0][RTW89_CHILE][50] = 127,
+ [0][1][1][0][RTW89_QATAR][50] = 127,
[0][1][1][0][RTW89_FCC][52] = 48,
[0][1][1][0][RTW89_ETSI][52] = 127,
[0][1][1][0][RTW89_MKK][52] = 127,
@@ -30772,38 +34648,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][1][0][RTW89_ACMA][52] = 127,
[0][1][1][0][RTW89_CN][52] = 127,
[0][1][1][0][RTW89_UK][52] = 127,
+ [0][1][1][0][RTW89_MEXICO][52] = 127,
+ [0][1][1][0][RTW89_UKRAINE][52] = 127,
+ [0][1][1][0][RTW89_CHILE][52] = 127,
+ [0][1][1][0][RTW89_QATAR][52] = 127,
[0][0][2][0][RTW89_FCC][0] = 70,
[0][0][2][0][RTW89_ETSI][0] = 66,
[0][0][2][0][RTW89_MKK][0] = 68,
[0][0][2][0][RTW89_IC][0] = 60,
- [0][0][2][0][RTW89_KCC][0] = 54,
+ [0][0][2][0][RTW89_KCC][0] = 68,
[0][0][2][0][RTW89_ACMA][0] = 66,
[0][0][2][0][RTW89_CN][0] = 52,
[0][0][2][0][RTW89_UK][0] = 66,
+ [0][0][2][0][RTW89_MEXICO][0] = 62,
+ [0][0][2][0][RTW89_UKRAINE][0] = 54,
+ [0][0][2][0][RTW89_CHILE][0] = 68,
+ [0][0][2][0][RTW89_QATAR][0] = 66,
[0][0][2][0][RTW89_FCC][2] = 72,
[0][0][2][0][RTW89_ETSI][2] = 66,
[0][0][2][0][RTW89_MKK][2] = 68,
[0][0][2][0][RTW89_IC][2] = 60,
- [0][0][2][0][RTW89_KCC][2] = 54,
+ [0][0][2][0][RTW89_KCC][2] = 68,
[0][0][2][0][RTW89_ACMA][2] = 66,
[0][0][2][0][RTW89_CN][2] = 52,
[0][0][2][0][RTW89_UK][2] = 66,
+ [0][0][2][0][RTW89_MEXICO][2] = 62,
+ [0][0][2][0][RTW89_UKRAINE][2] = 54,
+ [0][0][2][0][RTW89_CHILE][2] = 70,
+ [0][0][2][0][RTW89_QATAR][2] = 66,
[0][0][2][0][RTW89_FCC][4] = 72,
[0][0][2][0][RTW89_ETSI][4] = 66,
[0][0][2][0][RTW89_MKK][4] = 68,
[0][0][2][0][RTW89_IC][4] = 60,
- [0][0][2][0][RTW89_KCC][4] = 54,
+ [0][0][2][0][RTW89_KCC][4] = 68,
[0][0][2][0][RTW89_ACMA][4] = 66,
[0][0][2][0][RTW89_CN][4] = 52,
[0][0][2][0][RTW89_UK][4] = 66,
+ [0][0][2][0][RTW89_MEXICO][4] = 62,
+ [0][0][2][0][RTW89_UKRAINE][4] = 54,
+ [0][0][2][0][RTW89_CHILE][4] = 70,
+ [0][0][2][0][RTW89_QATAR][4] = 66,
[0][0][2][0][RTW89_FCC][6] = 72,
[0][0][2][0][RTW89_ETSI][6] = 66,
[0][0][2][0][RTW89_MKK][6] = 60,
[0][0][2][0][RTW89_IC][6] = 60,
- [0][0][2][0][RTW89_KCC][6] = 68,
+ [0][0][2][0][RTW89_KCC][6] = 54,
[0][0][2][0][RTW89_ACMA][6] = 66,
[0][0][2][0][RTW89_CN][6] = 52,
[0][0][2][0][RTW89_UK][6] = 66,
+ [0][0][2][0][RTW89_MEXICO][6] = 62,
+ [0][0][2][0][RTW89_UKRAINE][6] = 54,
+ [0][0][2][0][RTW89_CHILE][6] = 70,
+ [0][0][2][0][RTW89_QATAR][6] = 66,
[0][0][2][0][RTW89_FCC][8] = 72,
[0][0][2][0][RTW89_ETSI][8] = 66,
[0][0][2][0][RTW89_MKK][8] = 58,
@@ -30812,6 +34708,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][8] = 66,
[0][0][2][0][RTW89_CN][8] = 52,
[0][0][2][0][RTW89_UK][8] = 66,
+ [0][0][2][0][RTW89_MEXICO][8] = 72,
+ [0][0][2][0][RTW89_UKRAINE][8] = 54,
+ [0][0][2][0][RTW89_CHILE][8] = 70,
+ [0][0][2][0][RTW89_QATAR][8] = 66,
[0][0][2][0][RTW89_FCC][10] = 72,
[0][0][2][0][RTW89_ETSI][10] = 66,
[0][0][2][0][RTW89_MKK][10] = 70,
@@ -30820,6 +34720,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][10] = 66,
[0][0][2][0][RTW89_CN][10] = 52,
[0][0][2][0][RTW89_UK][10] = 66,
+ [0][0][2][0][RTW89_MEXICO][10] = 72,
+ [0][0][2][0][RTW89_UKRAINE][10] = 54,
+ [0][0][2][0][RTW89_CHILE][10] = 70,
+ [0][0][2][0][RTW89_QATAR][10] = 66,
[0][0][2][0][RTW89_FCC][12] = 72,
[0][0][2][0][RTW89_ETSI][12] = 66,
[0][0][2][0][RTW89_MKK][12] = 70,
@@ -30828,6 +34732,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][12] = 66,
[0][0][2][0][RTW89_CN][12] = 52,
[0][0][2][0][RTW89_UK][12] = 66,
+ [0][0][2][0][RTW89_MEXICO][12] = 72,
+ [0][0][2][0][RTW89_UKRAINE][12] = 54,
+ [0][0][2][0][RTW89_CHILE][12] = 70,
+ [0][0][2][0][RTW89_QATAR][12] = 66,
[0][0][2][0][RTW89_FCC][14] = 68,
[0][0][2][0][RTW89_ETSI][14] = 66,
[0][0][2][0][RTW89_MKK][14] = 70,
@@ -30836,6 +34744,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][14] = 66,
[0][0][2][0][RTW89_CN][14] = 52,
[0][0][2][0][RTW89_UK][14] = 66,
+ [0][0][2][0][RTW89_MEXICO][14] = 68,
+ [0][0][2][0][RTW89_UKRAINE][14] = 54,
+ [0][0][2][0][RTW89_CHILE][14] = 66,
+ [0][0][2][0][RTW89_QATAR][14] = 66,
[0][0][2][0][RTW89_FCC][15] = 70,
[0][0][2][0][RTW89_ETSI][15] = 66,
[0][0][2][0][RTW89_MKK][15] = 70,
@@ -30844,6 +34756,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][15] = 66,
[0][0][2][0][RTW89_CN][15] = 127,
[0][0][2][0][RTW89_UK][15] = 66,
+ [0][0][2][0][RTW89_MEXICO][15] = 70,
+ [0][0][2][0][RTW89_UKRAINE][15] = 54,
+ [0][0][2][0][RTW89_CHILE][15] = 68,
+ [0][0][2][0][RTW89_QATAR][15] = 66,
[0][0][2][0][RTW89_FCC][17] = 72,
[0][0][2][0][RTW89_ETSI][17] = 66,
[0][0][2][0][RTW89_MKK][17] = 70,
@@ -30852,6 +34768,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][17] = 66,
[0][0][2][0][RTW89_CN][17] = 127,
[0][0][2][0][RTW89_UK][17] = 66,
+ [0][0][2][0][RTW89_MEXICO][17] = 72,
+ [0][0][2][0][RTW89_UKRAINE][17] = 54,
+ [0][0][2][0][RTW89_CHILE][17] = 68,
+ [0][0][2][0][RTW89_QATAR][17] = 66,
[0][0][2][0][RTW89_FCC][19] = 72,
[0][0][2][0][RTW89_ETSI][19] = 66,
[0][0][2][0][RTW89_MKK][19] = 70,
@@ -30860,6 +34780,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][19] = 66,
[0][0][2][0][RTW89_CN][19] = 127,
[0][0][2][0][RTW89_UK][19] = 66,
+ [0][0][2][0][RTW89_MEXICO][19] = 72,
+ [0][0][2][0][RTW89_UKRAINE][19] = 54,
+ [0][0][2][0][RTW89_CHILE][19] = 68,
+ [0][0][2][0][RTW89_QATAR][19] = 66,
[0][0][2][0][RTW89_FCC][21] = 72,
[0][0][2][0][RTW89_ETSI][21] = 66,
[0][0][2][0][RTW89_MKK][21] = 70,
@@ -30868,6 +34792,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][21] = 66,
[0][0][2][0][RTW89_CN][21] = 127,
[0][0][2][0][RTW89_UK][21] = 66,
+ [0][0][2][0][RTW89_MEXICO][21] = 72,
+ [0][0][2][0][RTW89_UKRAINE][21] = 54,
+ [0][0][2][0][RTW89_CHILE][21] = 70,
+ [0][0][2][0][RTW89_QATAR][21] = 66,
[0][0][2][0][RTW89_FCC][23] = 72,
[0][0][2][0][RTW89_ETSI][23] = 66,
[0][0][2][0][RTW89_MKK][23] = 70,
@@ -30876,6 +34804,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][23] = 66,
[0][0][2][0][RTW89_CN][23] = 127,
[0][0][2][0][RTW89_UK][23] = 66,
+ [0][0][2][0][RTW89_MEXICO][23] = 72,
+ [0][0][2][0][RTW89_UKRAINE][23] = 54,
+ [0][0][2][0][RTW89_CHILE][23] = 70,
+ [0][0][2][0][RTW89_QATAR][23] = 66,
[0][0][2][0][RTW89_FCC][25] = 72,
[0][0][2][0][RTW89_ETSI][25] = 66,
[0][0][2][0][RTW89_MKK][25] = 70,
@@ -30884,6 +34816,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][25] = 127,
[0][0][2][0][RTW89_CN][25] = 127,
[0][0][2][0][RTW89_UK][25] = 66,
+ [0][0][2][0][RTW89_MEXICO][25] = 72,
+ [0][0][2][0][RTW89_UKRAINE][25] = 54,
+ [0][0][2][0][RTW89_CHILE][25] = 70,
+ [0][0][2][0][RTW89_QATAR][25] = 66,
[0][0][2][0][RTW89_FCC][27] = 72,
[0][0][2][0][RTW89_ETSI][27] = 66,
[0][0][2][0][RTW89_MKK][27] = 70,
@@ -30892,6 +34828,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][27] = 127,
[0][0][2][0][RTW89_CN][27] = 127,
[0][0][2][0][RTW89_UK][27] = 66,
+ [0][0][2][0][RTW89_MEXICO][27] = 72,
+ [0][0][2][0][RTW89_UKRAINE][27] = 54,
+ [0][0][2][0][RTW89_CHILE][27] = 56,
+ [0][0][2][0][RTW89_QATAR][27] = 66,
[0][0][2][0][RTW89_FCC][29] = 72,
[0][0][2][0][RTW89_ETSI][29] = 66,
[0][0][2][0][RTW89_MKK][29] = 70,
@@ -30900,6 +34840,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][29] = 127,
[0][0][2][0][RTW89_CN][29] = 127,
[0][0][2][0][RTW89_UK][29] = 66,
+ [0][0][2][0][RTW89_MEXICO][29] = 72,
+ [0][0][2][0][RTW89_UKRAINE][29] = 54,
+ [0][0][2][0][RTW89_CHILE][29] = 56,
+ [0][0][2][0][RTW89_QATAR][29] = 66,
[0][0][2][0][RTW89_FCC][31] = 72,
[0][0][2][0][RTW89_ETSI][31] = 66,
[0][0][2][0][RTW89_MKK][31] = 70,
@@ -30908,6 +34852,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][31] = 66,
[0][0][2][0][RTW89_CN][31] = 127,
[0][0][2][0][RTW89_UK][31] = 66,
+ [0][0][2][0][RTW89_MEXICO][31] = 72,
+ [0][0][2][0][RTW89_UKRAINE][31] = 54,
+ [0][0][2][0][RTW89_CHILE][31] = 56,
+ [0][0][2][0][RTW89_QATAR][31] = 66,
[0][0][2][0][RTW89_FCC][33] = 72,
[0][0][2][0][RTW89_ETSI][33] = 66,
[0][0][2][0][RTW89_MKK][33] = 70,
@@ -30916,6 +34864,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][33] = 66,
[0][0][2][0][RTW89_CN][33] = 127,
[0][0][2][0][RTW89_UK][33] = 66,
+ [0][0][2][0][RTW89_MEXICO][33] = 72,
+ [0][0][2][0][RTW89_UKRAINE][33] = 54,
+ [0][0][2][0][RTW89_CHILE][33] = 56,
+ [0][0][2][0][RTW89_QATAR][33] = 66,
[0][0][2][0][RTW89_FCC][35] = 56,
[0][0][2][0][RTW89_ETSI][35] = 66,
[0][0][2][0][RTW89_MKK][35] = 70,
@@ -30924,6 +34876,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][35] = 66,
[0][0][2][0][RTW89_CN][35] = 127,
[0][0][2][0][RTW89_UK][35] = 66,
+ [0][0][2][0][RTW89_MEXICO][35] = 56,
+ [0][0][2][0][RTW89_UKRAINE][35] = 54,
+ [0][0][2][0][RTW89_CHILE][35] = 56,
+ [0][0][2][0][RTW89_QATAR][35] = 66,
[0][0][2][0][RTW89_FCC][37] = 72,
[0][0][2][0][RTW89_ETSI][37] = 127,
[0][0][2][0][RTW89_MKK][37] = 70,
@@ -30932,6 +34888,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][37] = 70,
[0][0][2][0][RTW89_CN][37] = 127,
[0][0][2][0][RTW89_UK][37] = 64,
+ [0][0][2][0][RTW89_MEXICO][37] = 72,
+ [0][0][2][0][RTW89_UKRAINE][37] = 127,
+ [0][0][2][0][RTW89_CHILE][37] = 70,
+ [0][0][2][0][RTW89_QATAR][37] = 127,
[0][0][2][0][RTW89_FCC][38] = 72,
[0][0][2][0][RTW89_ETSI][38] = 30,
[0][0][2][0][RTW89_MKK][38] = 127,
@@ -30940,6 +34900,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][38] = 70,
[0][0][2][0][RTW89_CN][38] = 68,
[0][0][2][0][RTW89_UK][38] = 64,
+ [0][0][2][0][RTW89_MEXICO][38] = 72,
+ [0][0][2][0][RTW89_UKRAINE][38] = 30,
+ [0][0][2][0][RTW89_CHILE][38] = 70,
+ [0][0][2][0][RTW89_QATAR][38] = 30,
[0][0][2][0][RTW89_FCC][40] = 72,
[0][0][2][0][RTW89_ETSI][40] = 30,
[0][0][2][0][RTW89_MKK][40] = 127,
@@ -30948,6 +34912,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][40] = 70,
[0][0][2][0][RTW89_CN][40] = 68,
[0][0][2][0][RTW89_UK][40] = 64,
+ [0][0][2][0][RTW89_MEXICO][40] = 72,
+ [0][0][2][0][RTW89_UKRAINE][40] = 30,
+ [0][0][2][0][RTW89_CHILE][40] = 70,
+ [0][0][2][0][RTW89_QATAR][40] = 30,
[0][0][2][0][RTW89_FCC][42] = 72,
[0][0][2][0][RTW89_ETSI][42] = 30,
[0][0][2][0][RTW89_MKK][42] = 127,
@@ -30956,6 +34924,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][42] = 70,
[0][0][2][0][RTW89_CN][42] = 68,
[0][0][2][0][RTW89_UK][42] = 64,
+ [0][0][2][0][RTW89_MEXICO][42] = 72,
+ [0][0][2][0][RTW89_UKRAINE][42] = 30,
+ [0][0][2][0][RTW89_CHILE][42] = 70,
+ [0][0][2][0][RTW89_QATAR][42] = 30,
[0][0][2][0][RTW89_FCC][44] = 72,
[0][0][2][0][RTW89_ETSI][44] = 30,
[0][0][2][0][RTW89_MKK][44] = 127,
@@ -30964,6 +34936,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][44] = 70,
[0][0][2][0][RTW89_CN][44] = 68,
[0][0][2][0][RTW89_UK][44] = 64,
+ [0][0][2][0][RTW89_MEXICO][44] = 72,
+ [0][0][2][0][RTW89_UKRAINE][44] = 30,
+ [0][0][2][0][RTW89_CHILE][44] = 70,
+ [0][0][2][0][RTW89_QATAR][44] = 30,
[0][0][2][0][RTW89_FCC][46] = 72,
[0][0][2][0][RTW89_ETSI][46] = 30,
[0][0][2][0][RTW89_MKK][46] = 127,
@@ -30972,6 +34948,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][46] = 70,
[0][0][2][0][RTW89_CN][46] = 68,
[0][0][2][0][RTW89_UK][46] = 64,
+ [0][0][2][0][RTW89_MEXICO][46] = 72,
+ [0][0][2][0][RTW89_UKRAINE][46] = 30,
+ [0][0][2][0][RTW89_CHILE][46] = 70,
+ [0][0][2][0][RTW89_QATAR][46] = 30,
[0][0][2][0][RTW89_FCC][48] = 72,
[0][0][2][0][RTW89_ETSI][48] = 127,
[0][0][2][0][RTW89_MKK][48] = 127,
@@ -30980,6 +34960,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][48] = 127,
[0][0][2][0][RTW89_CN][48] = 127,
[0][0][2][0][RTW89_UK][48] = 127,
+ [0][0][2][0][RTW89_MEXICO][48] = 127,
+ [0][0][2][0][RTW89_UKRAINE][48] = 127,
+ [0][0][2][0][RTW89_CHILE][48] = 127,
+ [0][0][2][0][RTW89_QATAR][48] = 127,
[0][0][2][0][RTW89_FCC][50] = 72,
[0][0][2][0][RTW89_ETSI][50] = 127,
[0][0][2][0][RTW89_MKK][50] = 127,
@@ -30988,6 +34972,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][50] = 127,
[0][0][2][0][RTW89_CN][50] = 127,
[0][0][2][0][RTW89_UK][50] = 127,
+ [0][0][2][0][RTW89_MEXICO][50] = 127,
+ [0][0][2][0][RTW89_UKRAINE][50] = 127,
+ [0][0][2][0][RTW89_CHILE][50] = 127,
+ [0][0][2][0][RTW89_QATAR][50] = 127,
[0][0][2][0][RTW89_FCC][52] = 72,
[0][0][2][0][RTW89_ETSI][52] = 127,
[0][0][2][0][RTW89_MKK][52] = 127,
@@ -30996,38 +34984,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][0][2][0][RTW89_ACMA][52] = 127,
[0][0][2][0][RTW89_CN][52] = 127,
[0][0][2][0][RTW89_UK][52] = 127,
+ [0][0][2][0][RTW89_MEXICO][52] = 127,
+ [0][0][2][0][RTW89_UKRAINE][52] = 127,
+ [0][0][2][0][RTW89_CHILE][52] = 127,
+ [0][0][2][0][RTW89_QATAR][52] = 127,
[0][1][2][0][RTW89_FCC][0] = 60,
[0][1][2][0][RTW89_ETSI][0] = 54,
[0][1][2][0][RTW89_MKK][0] = 54,
[0][1][2][0][RTW89_IC][0] = 36,
- [0][1][2][0][RTW89_KCC][0] = 40,
+ [0][1][2][0][RTW89_KCC][0] = 64,
[0][1][2][0][RTW89_ACMA][0] = 54,
[0][1][2][0][RTW89_CN][0] = 40,
[0][1][2][0][RTW89_UK][0] = 54,
+ [0][1][2][0][RTW89_MEXICO][0] = 50,
+ [0][1][2][0][RTW89_UKRAINE][0] = 42,
+ [0][1][2][0][RTW89_CHILE][0] = 60,
+ [0][1][2][0][RTW89_QATAR][0] = 54,
[0][1][2][0][RTW89_FCC][2] = 62,
[0][1][2][0][RTW89_ETSI][2] = 54,
[0][1][2][0][RTW89_MKK][2] = 54,
[0][1][2][0][RTW89_IC][2] = 36,
- [0][1][2][0][RTW89_KCC][2] = 40,
+ [0][1][2][0][RTW89_KCC][2] = 64,
[0][1][2][0][RTW89_ACMA][2] = 54,
[0][1][2][0][RTW89_CN][2] = 40,
[0][1][2][0][RTW89_UK][2] = 54,
+ [0][1][2][0][RTW89_MEXICO][2] = 50,
+ [0][1][2][0][RTW89_UKRAINE][2] = 42,
+ [0][1][2][0][RTW89_CHILE][2] = 62,
+ [0][1][2][0][RTW89_QATAR][2] = 54,
[0][1][2][0][RTW89_FCC][4] = 62,
[0][1][2][0][RTW89_ETSI][4] = 54,
[0][1][2][0][RTW89_MKK][4] = 54,
[0][1][2][0][RTW89_IC][4] = 36,
- [0][1][2][0][RTW89_KCC][4] = 40,
+ [0][1][2][0][RTW89_KCC][4] = 64,
[0][1][2][0][RTW89_ACMA][4] = 54,
[0][1][2][0][RTW89_CN][4] = 40,
[0][1][2][0][RTW89_UK][4] = 54,
+ [0][1][2][0][RTW89_MEXICO][4] = 50,
+ [0][1][2][0][RTW89_UKRAINE][4] = 42,
+ [0][1][2][0][RTW89_CHILE][4] = 62,
+ [0][1][2][0][RTW89_QATAR][4] = 54,
[0][1][2][0][RTW89_FCC][6] = 62,
[0][1][2][0][RTW89_ETSI][6] = 54,
[0][1][2][0][RTW89_MKK][6] = 50,
[0][1][2][0][RTW89_IC][6] = 38,
- [0][1][2][0][RTW89_KCC][6] = 64,
+ [0][1][2][0][RTW89_KCC][6] = 40,
[0][1][2][0][RTW89_ACMA][6] = 54,
[0][1][2][0][RTW89_CN][6] = 40,
[0][1][2][0][RTW89_UK][6] = 54,
+ [0][1][2][0][RTW89_MEXICO][6] = 50,
+ [0][1][2][0][RTW89_UKRAINE][6] = 42,
+ [0][1][2][0][RTW89_CHILE][6] = 62,
+ [0][1][2][0][RTW89_QATAR][6] = 54,
[0][1][2][0][RTW89_FCC][8] = 62,
[0][1][2][0][RTW89_ETSI][8] = 54,
[0][1][2][0][RTW89_MKK][8] = 42,
@@ -31036,6 +35044,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][8] = 54,
[0][1][2][0][RTW89_CN][8] = 40,
[0][1][2][0][RTW89_UK][8] = 54,
+ [0][1][2][0][RTW89_MEXICO][8] = 62,
+ [0][1][2][0][RTW89_UKRAINE][8] = 42,
+ [0][1][2][0][RTW89_CHILE][8] = 62,
+ [0][1][2][0][RTW89_QATAR][8] = 54,
[0][1][2][0][RTW89_FCC][10] = 62,
[0][1][2][0][RTW89_ETSI][10] = 54,
[0][1][2][0][RTW89_MKK][10] = 54,
@@ -31044,6 +35056,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][10] = 54,
[0][1][2][0][RTW89_CN][10] = 40,
[0][1][2][0][RTW89_UK][10] = 54,
+ [0][1][2][0][RTW89_MEXICO][10] = 62,
+ [0][1][2][0][RTW89_UKRAINE][10] = 42,
+ [0][1][2][0][RTW89_CHILE][10] = 62,
+ [0][1][2][0][RTW89_QATAR][10] = 54,
[0][1][2][0][RTW89_FCC][12] = 62,
[0][1][2][0][RTW89_ETSI][12] = 54,
[0][1][2][0][RTW89_MKK][12] = 54,
@@ -31052,6 +35068,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][12] = 54,
[0][1][2][0][RTW89_CN][12] = 40,
[0][1][2][0][RTW89_UK][12] = 54,
+ [0][1][2][0][RTW89_MEXICO][12] = 62,
+ [0][1][2][0][RTW89_UKRAINE][12] = 42,
+ [0][1][2][0][RTW89_CHILE][12] = 62,
+ [0][1][2][0][RTW89_QATAR][12] = 54,
[0][1][2][0][RTW89_FCC][14] = 62,
[0][1][2][0][RTW89_ETSI][14] = 54,
[0][1][2][0][RTW89_MKK][14] = 54,
@@ -31060,6 +35080,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][14] = 54,
[0][1][2][0][RTW89_CN][14] = 40,
[0][1][2][0][RTW89_UK][14] = 54,
+ [0][1][2][0][RTW89_MEXICO][14] = 62,
+ [0][1][2][0][RTW89_UKRAINE][14] = 42,
+ [0][1][2][0][RTW89_CHILE][14] = 62,
+ [0][1][2][0][RTW89_QATAR][14] = 54,
[0][1][2][0][RTW89_FCC][15] = 60,
[0][1][2][0][RTW89_ETSI][15] = 54,
[0][1][2][0][RTW89_MKK][15] = 68,
@@ -31068,6 +35092,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][15] = 54,
[0][1][2][0][RTW89_CN][15] = 127,
[0][1][2][0][RTW89_UK][15] = 54,
+ [0][1][2][0][RTW89_MEXICO][15] = 60,
+ [0][1][2][0][RTW89_UKRAINE][15] = 42,
+ [0][1][2][0][RTW89_CHILE][15] = 60,
+ [0][1][2][0][RTW89_QATAR][15] = 54,
[0][1][2][0][RTW89_FCC][17] = 62,
[0][1][2][0][RTW89_ETSI][17] = 54,
[0][1][2][0][RTW89_MKK][17] = 68,
@@ -31076,6 +35104,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][17] = 54,
[0][1][2][0][RTW89_CN][17] = 127,
[0][1][2][0][RTW89_UK][17] = 54,
+ [0][1][2][0][RTW89_MEXICO][17] = 62,
+ [0][1][2][0][RTW89_UKRAINE][17] = 42,
+ [0][1][2][0][RTW89_CHILE][17] = 60,
+ [0][1][2][0][RTW89_QATAR][17] = 54,
[0][1][2][0][RTW89_FCC][19] = 62,
[0][1][2][0][RTW89_ETSI][19] = 54,
[0][1][2][0][RTW89_MKK][19] = 68,
@@ -31084,6 +35116,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][19] = 54,
[0][1][2][0][RTW89_CN][19] = 127,
[0][1][2][0][RTW89_UK][19] = 54,
+ [0][1][2][0][RTW89_MEXICO][19] = 62,
+ [0][1][2][0][RTW89_UKRAINE][19] = 42,
+ [0][1][2][0][RTW89_CHILE][19] = 62,
+ [0][1][2][0][RTW89_QATAR][19] = 54,
[0][1][2][0][RTW89_FCC][21] = 62,
[0][1][2][0][RTW89_ETSI][21] = 54,
[0][1][2][0][RTW89_MKK][21] = 68,
@@ -31092,6 +35128,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][21] = 54,
[0][1][2][0][RTW89_CN][21] = 127,
[0][1][2][0][RTW89_UK][21] = 54,
+ [0][1][2][0][RTW89_MEXICO][21] = 62,
+ [0][1][2][0][RTW89_UKRAINE][21] = 42,
+ [0][1][2][0][RTW89_CHILE][21] = 62,
+ [0][1][2][0][RTW89_QATAR][21] = 54,
[0][1][2][0][RTW89_FCC][23] = 62,
[0][1][2][0][RTW89_ETSI][23] = 54,
[0][1][2][0][RTW89_MKK][23] = 68,
@@ -31100,6 +35140,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][23] = 54,
[0][1][2][0][RTW89_CN][23] = 127,
[0][1][2][0][RTW89_UK][23] = 54,
+ [0][1][2][0][RTW89_MEXICO][23] = 62,
+ [0][1][2][0][RTW89_UKRAINE][23] = 42,
+ [0][1][2][0][RTW89_CHILE][23] = 62,
+ [0][1][2][0][RTW89_QATAR][23] = 54,
[0][1][2][0][RTW89_FCC][25] = 62,
[0][1][2][0][RTW89_ETSI][25] = 54,
[0][1][2][0][RTW89_MKK][25] = 68,
@@ -31108,6 +35152,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][25] = 127,
[0][1][2][0][RTW89_CN][25] = 127,
[0][1][2][0][RTW89_UK][25] = 54,
+ [0][1][2][0][RTW89_MEXICO][25] = 62,
+ [0][1][2][0][RTW89_UKRAINE][25] = 42,
+ [0][1][2][0][RTW89_CHILE][25] = 62,
+ [0][1][2][0][RTW89_QATAR][25] = 54,
[0][1][2][0][RTW89_FCC][27] = 62,
[0][1][2][0][RTW89_ETSI][27] = 54,
[0][1][2][0][RTW89_MKK][27] = 68,
@@ -31116,6 +35164,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][27] = 127,
[0][1][2][0][RTW89_CN][27] = 127,
[0][1][2][0][RTW89_UK][27] = 54,
+ [0][1][2][0][RTW89_MEXICO][27] = 62,
+ [0][1][2][0][RTW89_UKRAINE][27] = 42,
+ [0][1][2][0][RTW89_CHILE][27] = 46,
+ [0][1][2][0][RTW89_QATAR][27] = 54,
[0][1][2][0][RTW89_FCC][29] = 62,
[0][1][2][0][RTW89_ETSI][29] = 54,
[0][1][2][0][RTW89_MKK][29] = 68,
@@ -31124,6 +35176,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][29] = 127,
[0][1][2][0][RTW89_CN][29] = 127,
[0][1][2][0][RTW89_UK][29] = 54,
+ [0][1][2][0][RTW89_MEXICO][29] = 62,
+ [0][1][2][0][RTW89_UKRAINE][29] = 42,
+ [0][1][2][0][RTW89_CHILE][29] = 46,
+ [0][1][2][0][RTW89_QATAR][29] = 54,
[0][1][2][0][RTW89_FCC][31] = 62,
[0][1][2][0][RTW89_ETSI][31] = 54,
[0][1][2][0][RTW89_MKK][31] = 68,
@@ -31132,6 +35188,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][31] = 54,
[0][1][2][0][RTW89_CN][31] = 127,
[0][1][2][0][RTW89_UK][31] = 54,
+ [0][1][2][0][RTW89_MEXICO][31] = 62,
+ [0][1][2][0][RTW89_UKRAINE][31] = 42,
+ [0][1][2][0][RTW89_CHILE][31] = 46,
+ [0][1][2][0][RTW89_QATAR][31] = 54,
[0][1][2][0][RTW89_FCC][33] = 62,
[0][1][2][0][RTW89_ETSI][33] = 54,
[0][1][2][0][RTW89_MKK][33] = 68,
@@ -31140,6 +35200,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][33] = 54,
[0][1][2][0][RTW89_CN][33] = 127,
[0][1][2][0][RTW89_UK][33] = 54,
+ [0][1][2][0][RTW89_MEXICO][33] = 62,
+ [0][1][2][0][RTW89_UKRAINE][33] = 42,
+ [0][1][2][0][RTW89_CHILE][33] = 46,
+ [0][1][2][0][RTW89_QATAR][33] = 54,
[0][1][2][0][RTW89_FCC][35] = 46,
[0][1][2][0][RTW89_ETSI][35] = 54,
[0][1][2][0][RTW89_MKK][35] = 68,
@@ -31148,6 +35212,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][35] = 54,
[0][1][2][0][RTW89_CN][35] = 127,
[0][1][2][0][RTW89_UK][35] = 54,
+ [0][1][2][0][RTW89_MEXICO][35] = 46,
+ [0][1][2][0][RTW89_UKRAINE][35] = 42,
+ [0][1][2][0][RTW89_CHILE][35] = 46,
+ [0][1][2][0][RTW89_QATAR][35] = 54,
[0][1][2][0][RTW89_FCC][37] = 64,
[0][1][2][0][RTW89_ETSI][37] = 127,
[0][1][2][0][RTW89_MKK][37] = 68,
@@ -31156,6 +35224,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][37] = 64,
[0][1][2][0][RTW89_CN][37] = 127,
[0][1][2][0][RTW89_UK][37] = 52,
+ [0][1][2][0][RTW89_MEXICO][37] = 64,
+ [0][1][2][0][RTW89_UKRAINE][37] = 127,
+ [0][1][2][0][RTW89_CHILE][37] = 64,
+ [0][1][2][0][RTW89_QATAR][37] = 127,
[0][1][2][0][RTW89_FCC][38] = 72,
[0][1][2][0][RTW89_ETSI][38] = 18,
[0][1][2][0][RTW89_MKK][38] = 127,
@@ -31164,6 +35236,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][38] = 70,
[0][1][2][0][RTW89_CN][38] = 68,
[0][1][2][0][RTW89_UK][38] = 52,
+ [0][1][2][0][RTW89_MEXICO][38] = 72,
+ [0][1][2][0][RTW89_UKRAINE][38] = 18,
+ [0][1][2][0][RTW89_CHILE][38] = 70,
+ [0][1][2][0][RTW89_QATAR][38] = 18,
[0][1][2][0][RTW89_FCC][40] = 72,
[0][1][2][0][RTW89_ETSI][40] = 18,
[0][1][2][0][RTW89_MKK][40] = 127,
@@ -31172,6 +35248,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][40] = 70,
[0][1][2][0][RTW89_CN][40] = 68,
[0][1][2][0][RTW89_UK][40] = 52,
+ [0][1][2][0][RTW89_MEXICO][40] = 72,
+ [0][1][2][0][RTW89_UKRAINE][40] = 18,
+ [0][1][2][0][RTW89_CHILE][40] = 70,
+ [0][1][2][0][RTW89_QATAR][40] = 18,
[0][1][2][0][RTW89_FCC][42] = 72,
[0][1][2][0][RTW89_ETSI][42] = 18,
[0][1][2][0][RTW89_MKK][42] = 127,
@@ -31180,6 +35260,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][42] = 70,
[0][1][2][0][RTW89_CN][42] = 68,
[0][1][2][0][RTW89_UK][42] = 52,
+ [0][1][2][0][RTW89_MEXICO][42] = 72,
+ [0][1][2][0][RTW89_UKRAINE][42] = 18,
+ [0][1][2][0][RTW89_CHILE][42] = 70,
+ [0][1][2][0][RTW89_QATAR][42] = 18,
[0][1][2][0][RTW89_FCC][44] = 72,
[0][1][2][0][RTW89_ETSI][44] = 18,
[0][1][2][0][RTW89_MKK][44] = 127,
@@ -31188,6 +35272,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][44] = 70,
[0][1][2][0][RTW89_CN][44] = 68,
[0][1][2][0][RTW89_UK][44] = 52,
+ [0][1][2][0][RTW89_MEXICO][44] = 72,
+ [0][1][2][0][RTW89_UKRAINE][44] = 18,
+ [0][1][2][0][RTW89_CHILE][44] = 70,
+ [0][1][2][0][RTW89_QATAR][44] = 18,
[0][1][2][0][RTW89_FCC][46] = 72,
[0][1][2][0][RTW89_ETSI][46] = 18,
[0][1][2][0][RTW89_MKK][46] = 127,
@@ -31196,6 +35284,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][46] = 70,
[0][1][2][0][RTW89_CN][46] = 68,
[0][1][2][0][RTW89_UK][46] = 52,
+ [0][1][2][0][RTW89_MEXICO][46] = 72,
+ [0][1][2][0][RTW89_UKRAINE][46] = 18,
+ [0][1][2][0][RTW89_CHILE][46] = 70,
+ [0][1][2][0][RTW89_QATAR][46] = 18,
[0][1][2][0][RTW89_FCC][48] = 48,
[0][1][2][0][RTW89_ETSI][48] = 127,
[0][1][2][0][RTW89_MKK][48] = 127,
@@ -31204,6 +35296,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][48] = 127,
[0][1][2][0][RTW89_CN][48] = 127,
[0][1][2][0][RTW89_UK][48] = 127,
+ [0][1][2][0][RTW89_MEXICO][48] = 127,
+ [0][1][2][0][RTW89_UKRAINE][48] = 127,
+ [0][1][2][0][RTW89_CHILE][48] = 127,
+ [0][1][2][0][RTW89_QATAR][48] = 127,
[0][1][2][0][RTW89_FCC][50] = 50,
[0][1][2][0][RTW89_ETSI][50] = 127,
[0][1][2][0][RTW89_MKK][50] = 127,
@@ -31212,6 +35308,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][50] = 127,
[0][1][2][0][RTW89_CN][50] = 127,
[0][1][2][0][RTW89_UK][50] = 127,
+ [0][1][2][0][RTW89_MEXICO][50] = 127,
+ [0][1][2][0][RTW89_UKRAINE][50] = 127,
+ [0][1][2][0][RTW89_CHILE][50] = 127,
+ [0][1][2][0][RTW89_QATAR][50] = 127,
[0][1][2][0][RTW89_FCC][52] = 48,
[0][1][2][0][RTW89_ETSI][52] = 127,
[0][1][2][0][RTW89_MKK][52] = 127,
@@ -31220,38 +35320,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][0][RTW89_ACMA][52] = 127,
[0][1][2][0][RTW89_CN][52] = 127,
[0][1][2][0][RTW89_UK][52] = 127,
+ [0][1][2][0][RTW89_MEXICO][52] = 127,
+ [0][1][2][0][RTW89_UKRAINE][52] = 127,
+ [0][1][2][0][RTW89_CHILE][52] = 127,
+ [0][1][2][0][RTW89_QATAR][52] = 127,
[0][1][2][1][RTW89_FCC][0] = 60,
[0][1][2][1][RTW89_ETSI][0] = 40,
[0][1][2][1][RTW89_MKK][0] = 54,
[0][1][2][1][RTW89_IC][0] = 40,
- [0][1][2][1][RTW89_KCC][0] = 40,
+ [0][1][2][1][RTW89_KCC][0] = 64,
[0][1][2][1][RTW89_ACMA][0] = 40,
[0][1][2][1][RTW89_CN][0] = 36,
[0][1][2][1][RTW89_UK][0] = 40,
+ [0][1][2][1][RTW89_MEXICO][0] = 50,
+ [0][1][2][1][RTW89_UKRAINE][0] = 30,
+ [0][1][2][1][RTW89_CHILE][0] = 60,
+ [0][1][2][1][RTW89_QATAR][0] = 40,
[0][1][2][1][RTW89_FCC][2] = 62,
[0][1][2][1][RTW89_ETSI][2] = 40,
[0][1][2][1][RTW89_MKK][2] = 54,
[0][1][2][1][RTW89_IC][2] = 40,
- [0][1][2][1][RTW89_KCC][2] = 40,
+ [0][1][2][1][RTW89_KCC][2] = 64,
[0][1][2][1][RTW89_ACMA][2] = 40,
[0][1][2][1][RTW89_CN][2] = 36,
[0][1][2][1][RTW89_UK][2] = 40,
+ [0][1][2][1][RTW89_MEXICO][2] = 50,
+ [0][1][2][1][RTW89_UKRAINE][2] = 30,
+ [0][1][2][1][RTW89_CHILE][2] = 60,
+ [0][1][2][1][RTW89_QATAR][2] = 40,
[0][1][2][1][RTW89_FCC][4] = 62,
[0][1][2][1][RTW89_ETSI][4] = 40,
[0][1][2][1][RTW89_MKK][4] = 54,
[0][1][2][1][RTW89_IC][4] = 40,
- [0][1][2][1][RTW89_KCC][4] = 40,
+ [0][1][2][1][RTW89_KCC][4] = 64,
[0][1][2][1][RTW89_ACMA][4] = 40,
[0][1][2][1][RTW89_CN][4] = 36,
[0][1][2][1][RTW89_UK][4] = 40,
+ [0][1][2][1][RTW89_MEXICO][4] = 50,
+ [0][1][2][1][RTW89_UKRAINE][4] = 30,
+ [0][1][2][1][RTW89_CHILE][4] = 60,
+ [0][1][2][1][RTW89_QATAR][4] = 40,
[0][1][2][1][RTW89_FCC][6] = 62,
[0][1][2][1][RTW89_ETSI][6] = 40,
[0][1][2][1][RTW89_MKK][6] = 50,
[0][1][2][1][RTW89_IC][6] = 40,
- [0][1][2][1][RTW89_KCC][6] = 64,
+ [0][1][2][1][RTW89_KCC][6] = 40,
[0][1][2][1][RTW89_ACMA][6] = 40,
[0][1][2][1][RTW89_CN][6] = 36,
[0][1][2][1][RTW89_UK][6] = 40,
+ [0][1][2][1][RTW89_MEXICO][6] = 50,
+ [0][1][2][1][RTW89_UKRAINE][6] = 30,
+ [0][1][2][1][RTW89_CHILE][6] = 60,
+ [0][1][2][1][RTW89_QATAR][6] = 40,
[0][1][2][1][RTW89_FCC][8] = 62,
[0][1][2][1][RTW89_ETSI][8] = 40,
[0][1][2][1][RTW89_MKK][8] = 42,
@@ -31260,6 +35380,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][8] = 40,
[0][1][2][1][RTW89_CN][8] = 36,
[0][1][2][1][RTW89_UK][8] = 40,
+ [0][1][2][1][RTW89_MEXICO][8] = 62,
+ [0][1][2][1][RTW89_UKRAINE][8] = 30,
+ [0][1][2][1][RTW89_CHILE][8] = 60,
+ [0][1][2][1][RTW89_QATAR][8] = 40,
[0][1][2][1][RTW89_FCC][10] = 62,
[0][1][2][1][RTW89_ETSI][10] = 40,
[0][1][2][1][RTW89_MKK][10] = 54,
@@ -31268,6 +35392,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][10] = 40,
[0][1][2][1][RTW89_CN][10] = 36,
[0][1][2][1][RTW89_UK][10] = 40,
+ [0][1][2][1][RTW89_MEXICO][10] = 62,
+ [0][1][2][1][RTW89_UKRAINE][10] = 30,
+ [0][1][2][1][RTW89_CHILE][10] = 60,
+ [0][1][2][1][RTW89_QATAR][10] = 40,
[0][1][2][1][RTW89_FCC][12] = 62,
[0][1][2][1][RTW89_ETSI][12] = 40,
[0][1][2][1][RTW89_MKK][12] = 54,
@@ -31276,6 +35404,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][12] = 40,
[0][1][2][1][RTW89_CN][12] = 36,
[0][1][2][1][RTW89_UK][12] = 40,
+ [0][1][2][1][RTW89_MEXICO][12] = 62,
+ [0][1][2][1][RTW89_UKRAINE][12] = 30,
+ [0][1][2][1][RTW89_CHILE][12] = 60,
+ [0][1][2][1][RTW89_QATAR][12] = 40,
[0][1][2][1][RTW89_FCC][14] = 62,
[0][1][2][1][RTW89_ETSI][14] = 40,
[0][1][2][1][RTW89_MKK][14] = 54,
@@ -31284,6 +35416,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][14] = 40,
[0][1][2][1][RTW89_CN][14] = 36,
[0][1][2][1][RTW89_UK][14] = 40,
+ [0][1][2][1][RTW89_MEXICO][14] = 62,
+ [0][1][2][1][RTW89_UKRAINE][14] = 30,
+ [0][1][2][1][RTW89_CHILE][14] = 60,
+ [0][1][2][1][RTW89_QATAR][14] = 40,
[0][1][2][1][RTW89_FCC][15] = 60,
[0][1][2][1][RTW89_ETSI][15] = 40,
[0][1][2][1][RTW89_MKK][15] = 68,
@@ -31292,6 +35428,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][15] = 40,
[0][1][2][1][RTW89_CN][15] = 127,
[0][1][2][1][RTW89_UK][15] = 40,
+ [0][1][2][1][RTW89_MEXICO][15] = 60,
+ [0][1][2][1][RTW89_UKRAINE][15] = 30,
+ [0][1][2][1][RTW89_CHILE][15] = 60,
+ [0][1][2][1][RTW89_QATAR][15] = 40,
[0][1][2][1][RTW89_FCC][17] = 62,
[0][1][2][1][RTW89_ETSI][17] = 40,
[0][1][2][1][RTW89_MKK][17] = 68,
@@ -31300,6 +35440,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][17] = 40,
[0][1][2][1][RTW89_CN][17] = 127,
[0][1][2][1][RTW89_UK][17] = 40,
+ [0][1][2][1][RTW89_MEXICO][17] = 62,
+ [0][1][2][1][RTW89_UKRAINE][17] = 30,
+ [0][1][2][1][RTW89_CHILE][17] = 60,
+ [0][1][2][1][RTW89_QATAR][17] = 40,
[0][1][2][1][RTW89_FCC][19] = 62,
[0][1][2][1][RTW89_ETSI][19] = 40,
[0][1][2][1][RTW89_MKK][19] = 68,
@@ -31308,6 +35452,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][19] = 40,
[0][1][2][1][RTW89_CN][19] = 127,
[0][1][2][1][RTW89_UK][19] = 40,
+ [0][1][2][1][RTW89_MEXICO][19] = 62,
+ [0][1][2][1][RTW89_UKRAINE][19] = 30,
+ [0][1][2][1][RTW89_CHILE][19] = 60,
+ [0][1][2][1][RTW89_QATAR][19] = 40,
[0][1][2][1][RTW89_FCC][21] = 62,
[0][1][2][1][RTW89_ETSI][21] = 40,
[0][1][2][1][RTW89_MKK][21] = 68,
@@ -31316,6 +35464,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][21] = 40,
[0][1][2][1][RTW89_CN][21] = 127,
[0][1][2][1][RTW89_UK][21] = 40,
+ [0][1][2][1][RTW89_MEXICO][21] = 62,
+ [0][1][2][1][RTW89_UKRAINE][21] = 30,
+ [0][1][2][1][RTW89_CHILE][21] = 60,
+ [0][1][2][1][RTW89_QATAR][21] = 40,
[0][1][2][1][RTW89_FCC][23] = 62,
[0][1][2][1][RTW89_ETSI][23] = 40,
[0][1][2][1][RTW89_MKK][23] = 68,
@@ -31324,6 +35476,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][23] = 40,
[0][1][2][1][RTW89_CN][23] = 127,
[0][1][2][1][RTW89_UK][23] = 40,
+ [0][1][2][1][RTW89_MEXICO][23] = 62,
+ [0][1][2][1][RTW89_UKRAINE][23] = 30,
+ [0][1][2][1][RTW89_CHILE][23] = 60,
+ [0][1][2][1][RTW89_QATAR][23] = 40,
[0][1][2][1][RTW89_FCC][25] = 46,
[0][1][2][1][RTW89_ETSI][25] = 40,
[0][1][2][1][RTW89_MKK][25] = 68,
@@ -31332,6 +35488,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][25] = 127,
[0][1][2][1][RTW89_CN][25] = 127,
[0][1][2][1][RTW89_UK][25] = 40,
+ [0][1][2][1][RTW89_MEXICO][25] = 46,
+ [0][1][2][1][RTW89_UKRAINE][25] = 30,
+ [0][1][2][1][RTW89_CHILE][25] = 60,
+ [0][1][2][1][RTW89_QATAR][25] = 40,
[0][1][2][1][RTW89_FCC][27] = 46,
[0][1][2][1][RTW89_ETSI][27] = 40,
[0][1][2][1][RTW89_MKK][27] = 68,
@@ -31340,6 +35500,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][27] = 127,
[0][1][2][1][RTW89_CN][27] = 127,
[0][1][2][1][RTW89_UK][27] = 40,
+ [0][1][2][1][RTW89_MEXICO][27] = 46,
+ [0][1][2][1][RTW89_UKRAINE][27] = 30,
+ [0][1][2][1][RTW89_CHILE][27] = 46,
+ [0][1][2][1][RTW89_QATAR][27] = 40,
[0][1][2][1][RTW89_FCC][29] = 46,
[0][1][2][1][RTW89_ETSI][29] = 40,
[0][1][2][1][RTW89_MKK][29] = 68,
@@ -31348,6 +35512,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][29] = 127,
[0][1][2][1][RTW89_CN][29] = 127,
[0][1][2][1][RTW89_UK][29] = 40,
+ [0][1][2][1][RTW89_MEXICO][29] = 46,
+ [0][1][2][1][RTW89_UKRAINE][29] = 30,
+ [0][1][2][1][RTW89_CHILE][29] = 46,
+ [0][1][2][1][RTW89_QATAR][29] = 40,
[0][1][2][1][RTW89_FCC][31] = 46,
[0][1][2][1][RTW89_ETSI][31] = 40,
[0][1][2][1][RTW89_MKK][31] = 68,
@@ -31356,6 +35524,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][31] = 40,
[0][1][2][1][RTW89_CN][31] = 127,
[0][1][2][1][RTW89_UK][31] = 40,
+ [0][1][2][1][RTW89_MEXICO][31] = 46,
+ [0][1][2][1][RTW89_UKRAINE][31] = 30,
+ [0][1][2][1][RTW89_CHILE][31] = 46,
+ [0][1][2][1][RTW89_QATAR][31] = 40,
[0][1][2][1][RTW89_FCC][33] = 46,
[0][1][2][1][RTW89_ETSI][33] = 40,
[0][1][2][1][RTW89_MKK][33] = 68,
@@ -31364,6 +35536,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][33] = 40,
[0][1][2][1][RTW89_CN][33] = 127,
[0][1][2][1][RTW89_UK][33] = 40,
+ [0][1][2][1][RTW89_MEXICO][33] = 46,
+ [0][1][2][1][RTW89_UKRAINE][33] = 30,
+ [0][1][2][1][RTW89_CHILE][33] = 46,
+ [0][1][2][1][RTW89_QATAR][33] = 40,
[0][1][2][1][RTW89_FCC][35] = 46,
[0][1][2][1][RTW89_ETSI][35] = 40,
[0][1][2][1][RTW89_MKK][35] = 68,
@@ -31372,6 +35548,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][35] = 40,
[0][1][2][1][RTW89_CN][35] = 127,
[0][1][2][1][RTW89_UK][35] = 40,
+ [0][1][2][1][RTW89_MEXICO][35] = 46,
+ [0][1][2][1][RTW89_UKRAINE][35] = 30,
+ [0][1][2][1][RTW89_CHILE][35] = 46,
+ [0][1][2][1][RTW89_QATAR][35] = 40,
[0][1][2][1][RTW89_FCC][37] = 64,
[0][1][2][1][RTW89_ETSI][37] = 127,
[0][1][2][1][RTW89_MKK][37] = 68,
@@ -31380,6 +35560,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][37] = 64,
[0][1][2][1][RTW89_CN][37] = 127,
[0][1][2][1][RTW89_UK][37] = 40,
+ [0][1][2][1][RTW89_MEXICO][37] = 64,
+ [0][1][2][1][RTW89_UKRAINE][37] = 127,
+ [0][1][2][1][RTW89_CHILE][37] = 64,
+ [0][1][2][1][RTW89_QATAR][37] = 127,
[0][1][2][1][RTW89_FCC][38] = 72,
[0][1][2][1][RTW89_ETSI][38] = 6,
[0][1][2][1][RTW89_MKK][38] = 127,
@@ -31388,6 +35572,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][38] = 70,
[0][1][2][1][RTW89_CN][38] = 60,
[0][1][2][1][RTW89_UK][38] = 40,
+ [0][1][2][1][RTW89_MEXICO][38] = 72,
+ [0][1][2][1][RTW89_UKRAINE][38] = 6,
+ [0][1][2][1][RTW89_CHILE][38] = 60,
+ [0][1][2][1][RTW89_QATAR][38] = 6,
[0][1][2][1][RTW89_FCC][40] = 72,
[0][1][2][1][RTW89_ETSI][40] = 6,
[0][1][2][1][RTW89_MKK][40] = 127,
@@ -31396,6 +35584,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][40] = 70,
[0][1][2][1][RTW89_CN][40] = 60,
[0][1][2][1][RTW89_UK][40] = 40,
+ [0][1][2][1][RTW89_MEXICO][40] = 72,
+ [0][1][2][1][RTW89_UKRAINE][40] = 6,
+ [0][1][2][1][RTW89_CHILE][40] = 60,
+ [0][1][2][1][RTW89_QATAR][40] = 6,
[0][1][2][1][RTW89_FCC][42] = 72,
[0][1][2][1][RTW89_ETSI][42] = 6,
[0][1][2][1][RTW89_MKK][42] = 127,
@@ -31404,6 +35596,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][42] = 70,
[0][1][2][1][RTW89_CN][42] = 60,
[0][1][2][1][RTW89_UK][42] = 40,
+ [0][1][2][1][RTW89_MEXICO][42] = 72,
+ [0][1][2][1][RTW89_UKRAINE][42] = 6,
+ [0][1][2][1][RTW89_CHILE][42] = 60,
+ [0][1][2][1][RTW89_QATAR][42] = 6,
[0][1][2][1][RTW89_FCC][44] = 72,
[0][1][2][1][RTW89_ETSI][44] = 6,
[0][1][2][1][RTW89_MKK][44] = 127,
@@ -31412,6 +35608,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][44] = 70,
[0][1][2][1][RTW89_CN][44] = 54,
[0][1][2][1][RTW89_UK][44] = 40,
+ [0][1][2][1][RTW89_MEXICO][44] = 72,
+ [0][1][2][1][RTW89_UKRAINE][44] = 6,
+ [0][1][2][1][RTW89_CHILE][44] = 60,
+ [0][1][2][1][RTW89_QATAR][44] = 6,
[0][1][2][1][RTW89_FCC][46] = 72,
[0][1][2][1][RTW89_ETSI][46] = 6,
[0][1][2][1][RTW89_MKK][46] = 127,
@@ -31420,6 +35620,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][46] = 70,
[0][1][2][1][RTW89_CN][46] = 54,
[0][1][2][1][RTW89_UK][46] = 40,
+ [0][1][2][1][RTW89_MEXICO][46] = 72,
+ [0][1][2][1][RTW89_UKRAINE][46] = 6,
+ [0][1][2][1][RTW89_CHILE][46] = 60,
+ [0][1][2][1][RTW89_QATAR][46] = 6,
[0][1][2][1][RTW89_FCC][48] = 48,
[0][1][2][1][RTW89_ETSI][48] = 127,
[0][1][2][1][RTW89_MKK][48] = 127,
@@ -31428,6 +35632,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][48] = 127,
[0][1][2][1][RTW89_CN][48] = 127,
[0][1][2][1][RTW89_UK][48] = 127,
+ [0][1][2][1][RTW89_MEXICO][48] = 127,
+ [0][1][2][1][RTW89_UKRAINE][48] = 127,
+ [0][1][2][1][RTW89_CHILE][48] = 127,
+ [0][1][2][1][RTW89_QATAR][48] = 127,
[0][1][2][1][RTW89_FCC][50] = 50,
[0][1][2][1][RTW89_ETSI][50] = 127,
[0][1][2][1][RTW89_MKK][50] = 127,
@@ -31436,6 +35644,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][50] = 127,
[0][1][2][1][RTW89_CN][50] = 127,
[0][1][2][1][RTW89_UK][50] = 127,
+ [0][1][2][1][RTW89_MEXICO][50] = 127,
+ [0][1][2][1][RTW89_UKRAINE][50] = 127,
+ [0][1][2][1][RTW89_CHILE][50] = 127,
+ [0][1][2][1][RTW89_QATAR][50] = 127,
[0][1][2][1][RTW89_FCC][52] = 48,
[0][1][2][1][RTW89_ETSI][52] = 127,
[0][1][2][1][RTW89_MKK][52] = 127,
@@ -31444,22 +35656,34 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[0][1][2][1][RTW89_ACMA][52] = 127,
[0][1][2][1][RTW89_CN][52] = 127,
[0][1][2][1][RTW89_UK][52] = 127,
+ [0][1][2][1][RTW89_MEXICO][52] = 127,
+ [0][1][2][1][RTW89_UKRAINE][52] = 127,
+ [0][1][2][1][RTW89_CHILE][52] = 127,
+ [0][1][2][1][RTW89_QATAR][52] = 127,
[1][0][2][0][RTW89_FCC][1] = 64,
[1][0][2][0][RTW89_ETSI][1] = 66,
[1][0][2][0][RTW89_MKK][1] = 66,
[1][0][2][0][RTW89_IC][1] = 62,
- [1][0][2][0][RTW89_KCC][1] = 66,
+ [1][0][2][0][RTW89_KCC][1] = 54,
[1][0][2][0][RTW89_ACMA][1] = 66,
[1][0][2][0][RTW89_CN][1] = 54,
[1][0][2][0][RTW89_UK][1] = 66,
+ [1][0][2][0][RTW89_MEXICO][1] = 62,
+ [1][0][2][0][RTW89_UKRAINE][1] = 54,
+ [1][0][2][0][RTW89_CHILE][1] = 62,
+ [1][0][2][0][RTW89_QATAR][1] = 66,
[1][0][2][0][RTW89_FCC][5] = 68,
[1][0][2][0][RTW89_ETSI][5] = 66,
[1][0][2][0][RTW89_MKK][5] = 66,
[1][0][2][0][RTW89_IC][5] = 64,
- [1][0][2][0][RTW89_KCC][5] = 54,
+ [1][0][2][0][RTW89_KCC][5] = 66,
[1][0][2][0][RTW89_ACMA][5] = 66,
[1][0][2][0][RTW89_CN][5] = 54,
[1][0][2][0][RTW89_UK][5] = 66,
+ [1][0][2][0][RTW89_MEXICO][5] = 62,
+ [1][0][2][0][RTW89_UKRAINE][5] = 54,
+ [1][0][2][0][RTW89_CHILE][5] = 66,
+ [1][0][2][0][RTW89_QATAR][5] = 66,
[1][0][2][0][RTW89_FCC][9] = 68,
[1][0][2][0][RTW89_ETSI][9] = 66,
[1][0][2][0][RTW89_MKK][9] = 66,
@@ -31468,6 +35692,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][9] = 66,
[1][0][2][0][RTW89_CN][9] = 54,
[1][0][2][0][RTW89_UK][9] = 66,
+ [1][0][2][0][RTW89_MEXICO][9] = 68,
+ [1][0][2][0][RTW89_UKRAINE][9] = 54,
+ [1][0][2][0][RTW89_CHILE][9] = 66,
+ [1][0][2][0][RTW89_QATAR][9] = 66,
[1][0][2][0][RTW89_FCC][13] = 60,
[1][0][2][0][RTW89_ETSI][13] = 66,
[1][0][2][0][RTW89_MKK][13] = 66,
@@ -31476,6 +35704,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][13] = 66,
[1][0][2][0][RTW89_CN][13] = 54,
[1][0][2][0][RTW89_UK][13] = 66,
+ [1][0][2][0][RTW89_MEXICO][13] = 60,
+ [1][0][2][0][RTW89_UKRAINE][13] = 54,
+ [1][0][2][0][RTW89_CHILE][13] = 60,
+ [1][0][2][0][RTW89_QATAR][13] = 66,
[1][0][2][0][RTW89_FCC][16] = 64,
[1][0][2][0][RTW89_ETSI][16] = 66,
[1][0][2][0][RTW89_MKK][16] = 66,
@@ -31484,6 +35716,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][16] = 66,
[1][0][2][0][RTW89_CN][16] = 127,
[1][0][2][0][RTW89_UK][16] = 66,
+ [1][0][2][0][RTW89_MEXICO][16] = 64,
+ [1][0][2][0][RTW89_UKRAINE][16] = 54,
+ [1][0][2][0][RTW89_CHILE][16] = 64,
+ [1][0][2][0][RTW89_QATAR][16] = 66,
[1][0][2][0][RTW89_FCC][20] = 68,
[1][0][2][0][RTW89_ETSI][20] = 66,
[1][0][2][0][RTW89_MKK][20] = 66,
@@ -31492,6 +35728,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][20] = 66,
[1][0][2][0][RTW89_CN][20] = 127,
[1][0][2][0][RTW89_UK][20] = 66,
+ [1][0][2][0][RTW89_MEXICO][20] = 68,
+ [1][0][2][0][RTW89_UKRAINE][20] = 54,
+ [1][0][2][0][RTW89_CHILE][20] = 66,
+ [1][0][2][0][RTW89_QATAR][20] = 66,
[1][0][2][0][RTW89_FCC][24] = 68,
[1][0][2][0][RTW89_ETSI][24] = 66,
[1][0][2][0][RTW89_MKK][24] = 66,
@@ -31500,6 +35740,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][24] = 127,
[1][0][2][0][RTW89_CN][24] = 127,
[1][0][2][0][RTW89_UK][24] = 66,
+ [1][0][2][0][RTW89_MEXICO][24] = 68,
+ [1][0][2][0][RTW89_UKRAINE][24] = 54,
+ [1][0][2][0][RTW89_CHILE][24] = 66,
+ [1][0][2][0][RTW89_QATAR][24] = 66,
[1][0][2][0][RTW89_FCC][28] = 68,
[1][0][2][0][RTW89_ETSI][28] = 66,
[1][0][2][0][RTW89_MKK][28] = 66,
@@ -31508,6 +35752,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][28] = 127,
[1][0][2][0][RTW89_CN][28] = 127,
[1][0][2][0][RTW89_UK][28] = 66,
+ [1][0][2][0][RTW89_MEXICO][28] = 68,
+ [1][0][2][0][RTW89_UKRAINE][28] = 54,
+ [1][0][2][0][RTW89_CHILE][28] = 62,
+ [1][0][2][0][RTW89_QATAR][28] = 66,
[1][0][2][0][RTW89_FCC][32] = 62,
[1][0][2][0][RTW89_ETSI][32] = 66,
[1][0][2][0][RTW89_MKK][32] = 66,
@@ -31516,6 +35764,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][32] = 66,
[1][0][2][0][RTW89_CN][32] = 127,
[1][0][2][0][RTW89_UK][32] = 66,
+ [1][0][2][0][RTW89_MEXICO][32] = 62,
+ [1][0][2][0][RTW89_UKRAINE][32] = 54,
+ [1][0][2][0][RTW89_CHILE][32] = 62,
+ [1][0][2][0][RTW89_QATAR][32] = 66,
[1][0][2][0][RTW89_FCC][36] = 68,
[1][0][2][0][RTW89_ETSI][36] = 127,
[1][0][2][0][RTW89_MKK][36] = 66,
@@ -31524,6 +35776,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][36] = 66,
[1][0][2][0][RTW89_CN][36] = 127,
[1][0][2][0][RTW89_UK][36] = 64,
+ [1][0][2][0][RTW89_MEXICO][36] = 68,
+ [1][0][2][0][RTW89_UKRAINE][36] = 127,
+ [1][0][2][0][RTW89_CHILE][36] = 66,
+ [1][0][2][0][RTW89_QATAR][36] = 127,
[1][0][2][0][RTW89_FCC][39] = 68,
[1][0][2][0][RTW89_ETSI][39] = 30,
[1][0][2][0][RTW89_MKK][39] = 127,
@@ -31532,6 +35788,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][39] = 66,
[1][0][2][0][RTW89_CN][39] = 62,
[1][0][2][0][RTW89_UK][39] = 64,
+ [1][0][2][0][RTW89_MEXICO][39] = 68,
+ [1][0][2][0][RTW89_UKRAINE][39] = 30,
+ [1][0][2][0][RTW89_CHILE][39] = 66,
+ [1][0][2][0][RTW89_QATAR][39] = 30,
[1][0][2][0][RTW89_FCC][43] = 68,
[1][0][2][0][RTW89_ETSI][43] = 30,
[1][0][2][0][RTW89_MKK][43] = 127,
@@ -31540,6 +35800,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][43] = 66,
[1][0][2][0][RTW89_CN][43] = 66,
[1][0][2][0][RTW89_UK][43] = 64,
+ [1][0][2][0][RTW89_MEXICO][43] = 68,
+ [1][0][2][0][RTW89_UKRAINE][43] = 30,
+ [1][0][2][0][RTW89_CHILE][43] = 66,
+ [1][0][2][0][RTW89_QATAR][43] = 30,
[1][0][2][0][RTW89_FCC][47] = 68,
[1][0][2][0][RTW89_ETSI][47] = 127,
[1][0][2][0][RTW89_MKK][47] = 127,
@@ -31548,6 +35812,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][47] = 127,
[1][0][2][0][RTW89_CN][47] = 127,
[1][0][2][0][RTW89_UK][47] = 127,
+ [1][0][2][0][RTW89_MEXICO][47] = 127,
+ [1][0][2][0][RTW89_UKRAINE][47] = 127,
+ [1][0][2][0][RTW89_CHILE][47] = 127,
+ [1][0][2][0][RTW89_QATAR][47] = 127,
[1][0][2][0][RTW89_FCC][51] = 68,
[1][0][2][0][RTW89_ETSI][51] = 127,
[1][0][2][0][RTW89_MKK][51] = 127,
@@ -31556,6 +35824,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][0][2][0][RTW89_ACMA][51] = 127,
[1][0][2][0][RTW89_CN][51] = 127,
[1][0][2][0][RTW89_UK][51] = 127,
+ [1][0][2][0][RTW89_MEXICO][51] = 127,
+ [1][0][2][0][RTW89_UKRAINE][51] = 127,
+ [1][0][2][0][RTW89_CHILE][51] = 127,
+ [1][0][2][0][RTW89_QATAR][51] = 127,
[1][1][2][0][RTW89_FCC][1] = 54,
[1][1][2][0][RTW89_ETSI][1] = 54,
[1][1][2][0][RTW89_MKK][1] = 48,
@@ -31564,6 +35836,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][1] = 54,
[1][1][2][0][RTW89_CN][1] = 42,
[1][1][2][0][RTW89_UK][1] = 54,
+ [1][1][2][0][RTW89_MEXICO][1] = 50,
+ [1][1][2][0][RTW89_UKRAINE][1] = 42,
+ [1][1][2][0][RTW89_CHILE][1] = 54,
+ [1][1][2][0][RTW89_QATAR][1] = 54,
[1][1][2][0][RTW89_FCC][5] = 68,
[1][1][2][0][RTW89_ETSI][5] = 54,
[1][1][2][0][RTW89_MKK][5] = 52,
@@ -31572,6 +35848,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][5] = 54,
[1][1][2][0][RTW89_CN][5] = 42,
[1][1][2][0][RTW89_UK][5] = 54,
+ [1][1][2][0][RTW89_MEXICO][5] = 50,
+ [1][1][2][0][RTW89_UKRAINE][5] = 42,
+ [1][1][2][0][RTW89_CHILE][5] = 66,
+ [1][1][2][0][RTW89_QATAR][5] = 54,
[1][1][2][0][RTW89_FCC][9] = 68,
[1][1][2][0][RTW89_ETSI][9] = 54,
[1][1][2][0][RTW89_MKK][9] = 52,
@@ -31580,6 +35860,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][9] = 54,
[1][1][2][0][RTW89_CN][9] = 42,
[1][1][2][0][RTW89_UK][9] = 54,
+ [1][1][2][0][RTW89_MEXICO][9] = 68,
+ [1][1][2][0][RTW89_UKRAINE][9] = 42,
+ [1][1][2][0][RTW89_CHILE][9] = 66,
+ [1][1][2][0][RTW89_QATAR][9] = 54,
[1][1][2][0][RTW89_FCC][13] = 54,
[1][1][2][0][RTW89_ETSI][13] = 54,
[1][1][2][0][RTW89_MKK][13] = 52,
@@ -31588,6 +35872,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][13] = 54,
[1][1][2][0][RTW89_CN][13] = 42,
[1][1][2][0][RTW89_UK][13] = 54,
+ [1][1][2][0][RTW89_MEXICO][13] = 54,
+ [1][1][2][0][RTW89_UKRAINE][13] = 42,
+ [1][1][2][0][RTW89_CHILE][13] = 54,
+ [1][1][2][0][RTW89_QATAR][13] = 54,
[1][1][2][0][RTW89_FCC][16] = 56,
[1][1][2][0][RTW89_ETSI][16] = 54,
[1][1][2][0][RTW89_MKK][16] = 66,
@@ -31596,6 +35884,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][16] = 54,
[1][1][2][0][RTW89_CN][16] = 127,
[1][1][2][0][RTW89_UK][16] = 54,
+ [1][1][2][0][RTW89_MEXICO][16] = 56,
+ [1][1][2][0][RTW89_UKRAINE][16] = 42,
+ [1][1][2][0][RTW89_CHILE][16] = 54,
+ [1][1][2][0][RTW89_QATAR][16] = 54,
[1][1][2][0][RTW89_FCC][20] = 68,
[1][1][2][0][RTW89_ETSI][20] = 54,
[1][1][2][0][RTW89_MKK][20] = 66,
@@ -31604,6 +35896,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][20] = 54,
[1][1][2][0][RTW89_CN][20] = 127,
[1][1][2][0][RTW89_UK][20] = 54,
+ [1][1][2][0][RTW89_MEXICO][20] = 68,
+ [1][1][2][0][RTW89_UKRAINE][20] = 42,
+ [1][1][2][0][RTW89_CHILE][20] = 66,
+ [1][1][2][0][RTW89_QATAR][20] = 54,
[1][1][2][0][RTW89_FCC][24] = 68,
[1][1][2][0][RTW89_ETSI][24] = 54,
[1][1][2][0][RTW89_MKK][24] = 66,
@@ -31612,6 +35908,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][24] = 127,
[1][1][2][0][RTW89_CN][24] = 127,
[1][1][2][0][RTW89_UK][24] = 54,
+ [1][1][2][0][RTW89_MEXICO][24] = 68,
+ [1][1][2][0][RTW89_UKRAINE][24] = 42,
+ [1][1][2][0][RTW89_CHILE][24] = 66,
+ [1][1][2][0][RTW89_QATAR][24] = 54,
[1][1][2][0][RTW89_FCC][28] = 68,
[1][1][2][0][RTW89_ETSI][28] = 54,
[1][1][2][0][RTW89_MKK][28] = 66,
@@ -31620,6 +35920,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][28] = 127,
[1][1][2][0][RTW89_CN][28] = 127,
[1][1][2][0][RTW89_UK][28] = 54,
+ [1][1][2][0][RTW89_MEXICO][28] = 68,
+ [1][1][2][0][RTW89_UKRAINE][28] = 42,
+ [1][1][2][0][RTW89_CHILE][28] = 54,
+ [1][1][2][0][RTW89_QATAR][28] = 54,
[1][1][2][0][RTW89_FCC][32] = 56,
[1][1][2][0][RTW89_ETSI][32] = 54,
[1][1][2][0][RTW89_MKK][32] = 66,
@@ -31628,6 +35932,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][32] = 54,
[1][1][2][0][RTW89_CN][32] = 127,
[1][1][2][0][RTW89_UK][32] = 54,
+ [1][1][2][0][RTW89_MEXICO][32] = 56,
+ [1][1][2][0][RTW89_UKRAINE][32] = 42,
+ [1][1][2][0][RTW89_CHILE][32] = 54,
+ [1][1][2][0][RTW89_QATAR][32] = 54,
[1][1][2][0][RTW89_FCC][36] = 68,
[1][1][2][0][RTW89_ETSI][36] = 127,
[1][1][2][0][RTW89_MKK][36] = 66,
@@ -31636,6 +35944,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][36] = 66,
[1][1][2][0][RTW89_CN][36] = 127,
[1][1][2][0][RTW89_UK][36] = 52,
+ [1][1][2][0][RTW89_MEXICO][36] = 68,
+ [1][1][2][0][RTW89_UKRAINE][36] = 127,
+ [1][1][2][0][RTW89_CHILE][36] = 66,
+ [1][1][2][0][RTW89_QATAR][36] = 127,
[1][1][2][0][RTW89_FCC][39] = 68,
[1][1][2][0][RTW89_ETSI][39] = 18,
[1][1][2][0][RTW89_MKK][39] = 127,
@@ -31644,6 +35956,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][39] = 66,
[1][1][2][0][RTW89_CN][39] = 62,
[1][1][2][0][RTW89_UK][39] = 52,
+ [1][1][2][0][RTW89_MEXICO][39] = 68,
+ [1][1][2][0][RTW89_UKRAINE][39] = 18,
+ [1][1][2][0][RTW89_CHILE][39] = 66,
+ [1][1][2][0][RTW89_QATAR][39] = 18,
[1][1][2][0][RTW89_FCC][43] = 68,
[1][1][2][0][RTW89_ETSI][43] = 18,
[1][1][2][0][RTW89_MKK][43] = 127,
@@ -31652,6 +35968,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][43] = 66,
[1][1][2][0][RTW89_CN][43] = 66,
[1][1][2][0][RTW89_UK][43] = 52,
+ [1][1][2][0][RTW89_MEXICO][43] = 68,
+ [1][1][2][0][RTW89_UKRAINE][43] = 18,
+ [1][1][2][0][RTW89_CHILE][43] = 66,
+ [1][1][2][0][RTW89_QATAR][43] = 18,
[1][1][2][0][RTW89_FCC][47] = 62,
[1][1][2][0][RTW89_ETSI][47] = 127,
[1][1][2][0][RTW89_MKK][47] = 127,
@@ -31660,6 +35980,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][47] = 127,
[1][1][2][0][RTW89_CN][47] = 127,
[1][1][2][0][RTW89_UK][47] = 127,
+ [1][1][2][0][RTW89_MEXICO][47] = 127,
+ [1][1][2][0][RTW89_UKRAINE][47] = 127,
+ [1][1][2][0][RTW89_CHILE][47] = 127,
+ [1][1][2][0][RTW89_QATAR][47] = 127,
[1][1][2][0][RTW89_FCC][51] = 60,
[1][1][2][0][RTW89_ETSI][51] = 127,
[1][1][2][0][RTW89_MKK][51] = 127,
@@ -31668,6 +35992,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][0][RTW89_ACMA][51] = 127,
[1][1][2][0][RTW89_CN][51] = 127,
[1][1][2][0][RTW89_UK][51] = 127,
+ [1][1][2][0][RTW89_MEXICO][51] = 127,
+ [1][1][2][0][RTW89_UKRAINE][51] = 127,
+ [1][1][2][0][RTW89_CHILE][51] = 127,
+ [1][1][2][0][RTW89_QATAR][51] = 127,
[1][1][2][1][RTW89_FCC][1] = 54,
[1][1][2][1][RTW89_ETSI][1] = 40,
[1][1][2][1][RTW89_MKK][1] = 48,
@@ -31676,6 +36004,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][1] = 40,
[1][1][2][1][RTW89_CN][1] = 42,
[1][1][2][1][RTW89_UK][1] = 40,
+ [1][1][2][1][RTW89_MEXICO][1] = 50,
+ [1][1][2][1][RTW89_UKRAINE][1] = 30,
+ [1][1][2][1][RTW89_CHILE][1] = 54,
+ [1][1][2][1][RTW89_QATAR][1] = 40,
[1][1][2][1][RTW89_FCC][5] = 68,
[1][1][2][1][RTW89_ETSI][5] = 40,
[1][1][2][1][RTW89_MKK][5] = 52,
@@ -31684,6 +36016,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][5] = 40,
[1][1][2][1][RTW89_CN][5] = 42,
[1][1][2][1][RTW89_UK][5] = 40,
+ [1][1][2][1][RTW89_MEXICO][5] = 50,
+ [1][1][2][1][RTW89_UKRAINE][5] = 30,
+ [1][1][2][1][RTW89_CHILE][5] = 60,
+ [1][1][2][1][RTW89_QATAR][5] = 40,
[1][1][2][1][RTW89_FCC][9] = 68,
[1][1][2][1][RTW89_ETSI][9] = 40,
[1][1][2][1][RTW89_MKK][9] = 52,
@@ -31692,6 +36028,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][9] = 40,
[1][1][2][1][RTW89_CN][9] = 42,
[1][1][2][1][RTW89_UK][9] = 40,
+ [1][1][2][1][RTW89_MEXICO][9] = 68,
+ [1][1][2][1][RTW89_UKRAINE][9] = 30,
+ [1][1][2][1][RTW89_CHILE][9] = 60,
+ [1][1][2][1][RTW89_QATAR][9] = 40,
[1][1][2][1][RTW89_FCC][13] = 54,
[1][1][2][1][RTW89_ETSI][13] = 40,
[1][1][2][1][RTW89_MKK][13] = 52,
@@ -31700,6 +36040,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][13] = 40,
[1][1][2][1][RTW89_CN][13] = 42,
[1][1][2][1][RTW89_UK][13] = 40,
+ [1][1][2][1][RTW89_MEXICO][13] = 54,
+ [1][1][2][1][RTW89_UKRAINE][13] = 30,
+ [1][1][2][1][RTW89_CHILE][13] = 54,
+ [1][1][2][1][RTW89_QATAR][13] = 40,
[1][1][2][1][RTW89_FCC][16] = 56,
[1][1][2][1][RTW89_ETSI][16] = 40,
[1][1][2][1][RTW89_MKK][16] = 66,
@@ -31708,6 +36052,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][16] = 40,
[1][1][2][1][RTW89_CN][16] = 127,
[1][1][2][1][RTW89_UK][16] = 40,
+ [1][1][2][1][RTW89_MEXICO][16] = 56,
+ [1][1][2][1][RTW89_UKRAINE][16] = 30,
+ [1][1][2][1][RTW89_CHILE][16] = 54,
+ [1][1][2][1][RTW89_QATAR][16] = 40,
[1][1][2][1][RTW89_FCC][20] = 68,
[1][1][2][1][RTW89_ETSI][20] = 40,
[1][1][2][1][RTW89_MKK][20] = 66,
@@ -31716,6 +36064,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][20] = 40,
[1][1][2][1][RTW89_CN][20] = 127,
[1][1][2][1][RTW89_UK][20] = 40,
+ [1][1][2][1][RTW89_MEXICO][20] = 68,
+ [1][1][2][1][RTW89_UKRAINE][20] = 30,
+ [1][1][2][1][RTW89_CHILE][20] = 60,
+ [1][1][2][1][RTW89_QATAR][20] = 40,
[1][1][2][1][RTW89_FCC][24] = 68,
[1][1][2][1][RTW89_ETSI][24] = 40,
[1][1][2][1][RTW89_MKK][24] = 66,
@@ -31724,6 +36076,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][24] = 127,
[1][1][2][1][RTW89_CN][24] = 127,
[1][1][2][1][RTW89_UK][24] = 40,
+ [1][1][2][1][RTW89_MEXICO][24] = 68,
+ [1][1][2][1][RTW89_UKRAINE][24] = 30,
+ [1][1][2][1][RTW89_CHILE][24] = 60,
+ [1][1][2][1][RTW89_QATAR][24] = 40,
[1][1][2][1][RTW89_FCC][28] = 68,
[1][1][2][1][RTW89_ETSI][28] = 40,
[1][1][2][1][RTW89_MKK][28] = 66,
@@ -31732,6 +36088,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][28] = 127,
[1][1][2][1][RTW89_CN][28] = 127,
[1][1][2][1][RTW89_UK][28] = 40,
+ [1][1][2][1][RTW89_MEXICO][28] = 68,
+ [1][1][2][1][RTW89_UKRAINE][28] = 30,
+ [1][1][2][1][RTW89_CHILE][28] = 54,
+ [1][1][2][1][RTW89_QATAR][28] = 40,
[1][1][2][1][RTW89_FCC][32] = 56,
[1][1][2][1][RTW89_ETSI][32] = 40,
[1][1][2][1][RTW89_MKK][32] = 66,
@@ -31740,6 +36100,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][32] = 40,
[1][1][2][1][RTW89_CN][32] = 127,
[1][1][2][1][RTW89_UK][32] = 40,
+ [1][1][2][1][RTW89_MEXICO][32] = 56,
+ [1][1][2][1][RTW89_UKRAINE][32] = 30,
+ [1][1][2][1][RTW89_CHILE][32] = 54,
+ [1][1][2][1][RTW89_QATAR][32] = 40,
[1][1][2][1][RTW89_FCC][36] = 68,
[1][1][2][1][RTW89_ETSI][36] = 127,
[1][1][2][1][RTW89_MKK][36] = 66,
@@ -31748,6 +36112,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][36] = 66,
[1][1][2][1][RTW89_CN][36] = 127,
[1][1][2][1][RTW89_UK][36] = 40,
+ [1][1][2][1][RTW89_MEXICO][36] = 68,
+ [1][1][2][1][RTW89_UKRAINE][36] = 127,
+ [1][1][2][1][RTW89_CHILE][36] = 66,
+ [1][1][2][1][RTW89_QATAR][36] = 127,
[1][1][2][1][RTW89_FCC][39] = 68,
[1][1][2][1][RTW89_ETSI][39] = 6,
[1][1][2][1][RTW89_MKK][39] = 127,
@@ -31756,6 +36124,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][39] = 66,
[1][1][2][1][RTW89_CN][39] = 60,
[1][1][2][1][RTW89_UK][39] = 40,
+ [1][1][2][1][RTW89_MEXICO][39] = 68,
+ [1][1][2][1][RTW89_UKRAINE][39] = 6,
+ [1][1][2][1][RTW89_CHILE][39] = 60,
+ [1][1][2][1][RTW89_QATAR][39] = 6,
[1][1][2][1][RTW89_FCC][43] = 68,
[1][1][2][1][RTW89_ETSI][43] = 6,
[1][1][2][1][RTW89_MKK][43] = 127,
@@ -31764,6 +36136,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][43] = 66,
[1][1][2][1][RTW89_CN][43] = 52,
[1][1][2][1][RTW89_UK][43] = 40,
+ [1][1][2][1][RTW89_MEXICO][43] = 68,
+ [1][1][2][1][RTW89_UKRAINE][43] = 6,
+ [1][1][2][1][RTW89_CHILE][43] = 60,
+ [1][1][2][1][RTW89_QATAR][43] = 6,
[1][1][2][1][RTW89_FCC][47] = 62,
[1][1][2][1][RTW89_ETSI][47] = 127,
[1][1][2][1][RTW89_MKK][47] = 127,
@@ -31772,6 +36148,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][47] = 127,
[1][1][2][1][RTW89_CN][47] = 127,
[1][1][2][1][RTW89_UK][47] = 127,
+ [1][1][2][1][RTW89_MEXICO][47] = 127,
+ [1][1][2][1][RTW89_UKRAINE][47] = 127,
+ [1][1][2][1][RTW89_CHILE][47] = 127,
+ [1][1][2][1][RTW89_QATAR][47] = 127,
[1][1][2][1][RTW89_FCC][51] = 60,
[1][1][2][1][RTW89_ETSI][51] = 127,
[1][1][2][1][RTW89_MKK][51] = 127,
@@ -31780,6 +36160,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[1][1][2][1][RTW89_ACMA][51] = 127,
[1][1][2][1][RTW89_CN][51] = 127,
[1][1][2][1][RTW89_UK][51] = 127,
+ [1][1][2][1][RTW89_MEXICO][51] = 127,
+ [1][1][2][1][RTW89_UKRAINE][51] = 127,
+ [1][1][2][1][RTW89_CHILE][51] = 127,
+ [1][1][2][1][RTW89_QATAR][51] = 127,
[2][0][2][0][RTW89_FCC][3] = 58,
[2][0][2][0][RTW89_ETSI][3] = 60,
[2][0][2][0][RTW89_MKK][3] = 60,
@@ -31788,6 +36172,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][3] = 60,
[2][0][2][0][RTW89_CN][3] = 54,
[2][0][2][0][RTW89_UK][3] = 60,
+ [2][0][2][0][RTW89_MEXICO][3] = 58,
+ [2][0][2][0][RTW89_UKRAINE][3] = 54,
+ [2][0][2][0][RTW89_CHILE][3] = 58,
+ [2][0][2][0][RTW89_QATAR][3] = 60,
[2][0][2][0][RTW89_FCC][11] = 50,
[2][0][2][0][RTW89_ETSI][11] = 60,
[2][0][2][0][RTW89_MKK][11] = 60,
@@ -31796,6 +36184,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][11] = 60,
[2][0][2][0][RTW89_CN][11] = 54,
[2][0][2][0][RTW89_UK][11] = 60,
+ [2][0][2][0][RTW89_MEXICO][11] = 50,
+ [2][0][2][0][RTW89_UKRAINE][11] = 54,
+ [2][0][2][0][RTW89_CHILE][11] = 50,
+ [2][0][2][0][RTW89_QATAR][11] = 60,
[2][0][2][0][RTW89_FCC][18] = 60,
[2][0][2][0][RTW89_ETSI][18] = 60,
[2][0][2][0][RTW89_MKK][18] = 60,
@@ -31804,6 +36196,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][18] = 60,
[2][0][2][0][RTW89_CN][18] = 127,
[2][0][2][0][RTW89_UK][18] = 60,
+ [2][0][2][0][RTW89_MEXICO][18] = 60,
+ [2][0][2][0][RTW89_UKRAINE][18] = 54,
+ [2][0][2][0][RTW89_CHILE][18] = 60,
+ [2][0][2][0][RTW89_QATAR][18] = 60,
[2][0][2][0][RTW89_FCC][26] = 62,
[2][0][2][0][RTW89_ETSI][26] = 60,
[2][0][2][0][RTW89_MKK][26] = 60,
@@ -31812,6 +36208,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][26] = 127,
[2][0][2][0][RTW89_CN][26] = 127,
[2][0][2][0][RTW89_UK][26] = 60,
+ [2][0][2][0][RTW89_MEXICO][26] = 62,
+ [2][0][2][0][RTW89_UKRAINE][26] = 54,
+ [2][0][2][0][RTW89_CHILE][26] = 60,
+ [2][0][2][0][RTW89_QATAR][26] = 60,
[2][0][2][0][RTW89_FCC][34] = 62,
[2][0][2][0][RTW89_ETSI][34] = 127,
[2][0][2][0][RTW89_MKK][34] = 60,
@@ -31820,6 +36220,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][34] = 60,
[2][0][2][0][RTW89_CN][34] = 127,
[2][0][2][0][RTW89_UK][34] = 60,
+ [2][0][2][0][RTW89_MEXICO][34] = 62,
+ [2][0][2][0][RTW89_UKRAINE][34] = 127,
+ [2][0][2][0][RTW89_CHILE][34] = 60,
+ [2][0][2][0][RTW89_QATAR][34] = 127,
[2][0][2][0][RTW89_FCC][41] = 62,
[2][0][2][0][RTW89_ETSI][41] = 30,
[2][0][2][0][RTW89_MKK][41] = 127,
@@ -31828,6 +36232,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][41] = 60,
[2][0][2][0][RTW89_CN][41] = 62,
[2][0][2][0][RTW89_UK][41] = 60,
+ [2][0][2][0][RTW89_MEXICO][41] = 62,
+ [2][0][2][0][RTW89_UKRAINE][41] = 30,
+ [2][0][2][0][RTW89_CHILE][41] = 60,
+ [2][0][2][0][RTW89_QATAR][41] = 30,
[2][0][2][0][RTW89_FCC][49] = 62,
[2][0][2][0][RTW89_ETSI][49] = 127,
[2][0][2][0][RTW89_MKK][49] = 127,
@@ -31836,6 +36244,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][0][2][0][RTW89_ACMA][49] = 127,
[2][0][2][0][RTW89_CN][49] = 127,
[2][0][2][0][RTW89_UK][49] = 127,
+ [2][0][2][0][RTW89_MEXICO][49] = 127,
+ [2][0][2][0][RTW89_UKRAINE][49] = 127,
+ [2][0][2][0][RTW89_CHILE][49] = 127,
+ [2][0][2][0][RTW89_QATAR][49] = 127,
[2][1][2][0][RTW89_FCC][3] = 48,
[2][1][2][0][RTW89_ETSI][3] = 54,
[2][1][2][0][RTW89_MKK][3] = 56,
@@ -31844,6 +36256,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][3] = 54,
[2][1][2][0][RTW89_CN][3] = 52,
[2][1][2][0][RTW89_UK][3] = 54,
+ [2][1][2][0][RTW89_MEXICO][3] = 48,
+ [2][1][2][0][RTW89_UKRAINE][3] = 42,
+ [2][1][2][0][RTW89_CHILE][3] = 46,
+ [2][1][2][0][RTW89_QATAR][3] = 54,
[2][1][2][0][RTW89_FCC][11] = 38,
[2][1][2][0][RTW89_ETSI][11] = 54,
[2][1][2][0][RTW89_MKK][11] = 54,
@@ -31852,6 +36268,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][11] = 54,
[2][1][2][0][RTW89_CN][11] = 52,
[2][1][2][0][RTW89_UK][11] = 54,
+ [2][1][2][0][RTW89_MEXICO][11] = 38,
+ [2][1][2][0][RTW89_UKRAINE][11] = 42,
+ [2][1][2][0][RTW89_CHILE][11] = 38,
+ [2][1][2][0][RTW89_QATAR][11] = 54,
[2][1][2][0][RTW89_FCC][18] = 50,
[2][1][2][0][RTW89_ETSI][18] = 54,
[2][1][2][0][RTW89_MKK][18] = 60,
@@ -31860,6 +36280,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][18] = 54,
[2][1][2][0][RTW89_CN][18] = 127,
[2][1][2][0][RTW89_UK][18] = 54,
+ [2][1][2][0][RTW89_MEXICO][18] = 50,
+ [2][1][2][0][RTW89_UKRAINE][18] = 42,
+ [2][1][2][0][RTW89_CHILE][18] = 50,
+ [2][1][2][0][RTW89_QATAR][18] = 54,
[2][1][2][0][RTW89_FCC][26] = 52,
[2][1][2][0][RTW89_ETSI][26] = 54,
[2][1][2][0][RTW89_MKK][26] = 56,
@@ -31868,6 +36292,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][26] = 127,
[2][1][2][0][RTW89_CN][26] = 127,
[2][1][2][0][RTW89_UK][26] = 54,
+ [2][1][2][0][RTW89_MEXICO][26] = 52,
+ [2][1][2][0][RTW89_UKRAINE][26] = 42,
+ [2][1][2][0][RTW89_CHILE][26] = 52,
+ [2][1][2][0][RTW89_QATAR][26] = 54,
[2][1][2][0][RTW89_FCC][34] = 62,
[2][1][2][0][RTW89_ETSI][34] = 127,
[2][1][2][0][RTW89_MKK][34] = 60,
@@ -31876,6 +36304,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][34] = 60,
[2][1][2][0][RTW89_CN][34] = 127,
[2][1][2][0][RTW89_UK][34] = 52,
+ [2][1][2][0][RTW89_MEXICO][34] = 62,
+ [2][1][2][0][RTW89_UKRAINE][34] = 127,
+ [2][1][2][0][RTW89_CHILE][34] = 60,
+ [2][1][2][0][RTW89_QATAR][34] = 127,
[2][1][2][0][RTW89_FCC][41] = 60,
[2][1][2][0][RTW89_ETSI][41] = 18,
[2][1][2][0][RTW89_MKK][41] = 127,
@@ -31884,6 +36316,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][41] = 58,
[2][1][2][0][RTW89_CN][41] = 62,
[2][1][2][0][RTW89_UK][41] = 52,
+ [2][1][2][0][RTW89_MEXICO][41] = 60,
+ [2][1][2][0][RTW89_UKRAINE][41] = 18,
+ [2][1][2][0][RTW89_CHILE][41] = 58,
+ [2][1][2][0][RTW89_QATAR][41] = 18,
[2][1][2][0][RTW89_FCC][49] = 62,
[2][1][2][0][RTW89_ETSI][49] = 127,
[2][1][2][0][RTW89_MKK][49] = 127,
@@ -31892,6 +36328,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][0][RTW89_ACMA][49] = 127,
[2][1][2][0][RTW89_CN][49] = 127,
[2][1][2][0][RTW89_UK][49] = 127,
+ [2][1][2][0][RTW89_MEXICO][49] = 127,
+ [2][1][2][0][RTW89_UKRAINE][49] = 127,
+ [2][1][2][0][RTW89_CHILE][49] = 127,
+ [2][1][2][0][RTW89_QATAR][49] = 127,
[2][1][2][1][RTW89_FCC][3] = 48,
[2][1][2][1][RTW89_ETSI][3] = 40,
[2][1][2][1][RTW89_MKK][3] = 56,
@@ -31900,6 +36340,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][3] = 40,
[2][1][2][1][RTW89_CN][3] = 42,
[2][1][2][1][RTW89_UK][3] = 40,
+ [2][1][2][1][RTW89_MEXICO][3] = 48,
+ [2][1][2][1][RTW89_UKRAINE][3] = 30,
+ [2][1][2][1][RTW89_CHILE][3] = 46,
+ [2][1][2][1][RTW89_QATAR][3] = 40,
[2][1][2][1][RTW89_FCC][11] = 38,
[2][1][2][1][RTW89_ETSI][11] = 40,
[2][1][2][1][RTW89_MKK][11] = 54,
@@ -31908,6 +36352,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][11] = 40,
[2][1][2][1][RTW89_CN][11] = 42,
[2][1][2][1][RTW89_UK][11] = 40,
+ [2][1][2][1][RTW89_MEXICO][11] = 38,
+ [2][1][2][1][RTW89_UKRAINE][11] = 30,
+ [2][1][2][1][RTW89_CHILE][11] = 38,
+ [2][1][2][1][RTW89_QATAR][11] = 40,
[2][1][2][1][RTW89_FCC][18] = 50,
[2][1][2][1][RTW89_ETSI][18] = 40,
[2][1][2][1][RTW89_MKK][18] = 60,
@@ -31916,6 +36364,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][18] = 40,
[2][1][2][1][RTW89_CN][18] = 127,
[2][1][2][1][RTW89_UK][18] = 40,
+ [2][1][2][1][RTW89_MEXICO][18] = 50,
+ [2][1][2][1][RTW89_UKRAINE][18] = 30,
+ [2][1][2][1][RTW89_CHILE][18] = 50,
+ [2][1][2][1][RTW89_QATAR][18] = 40,
[2][1][2][1][RTW89_FCC][26] = 52,
[2][1][2][1][RTW89_ETSI][26] = 42,
[2][1][2][1][RTW89_MKK][26] = 56,
@@ -31924,6 +36376,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][26] = 127,
[2][1][2][1][RTW89_CN][26] = 127,
[2][1][2][1][RTW89_UK][26] = 42,
+ [2][1][2][1][RTW89_MEXICO][26] = 52,
+ [2][1][2][1][RTW89_UKRAINE][26] = 30,
+ [2][1][2][1][RTW89_CHILE][26] = 52,
+ [2][1][2][1][RTW89_QATAR][26] = 42,
[2][1][2][1][RTW89_FCC][34] = 62,
[2][1][2][1][RTW89_ETSI][34] = 127,
[2][1][2][1][RTW89_MKK][34] = 60,
@@ -31932,6 +36388,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][34] = 60,
[2][1][2][1][RTW89_CN][34] = 127,
[2][1][2][1][RTW89_UK][34] = 40,
+ [2][1][2][1][RTW89_MEXICO][34] = 62,
+ [2][1][2][1][RTW89_UKRAINE][34] = 127,
+ [2][1][2][1][RTW89_CHILE][34] = 60,
+ [2][1][2][1][RTW89_QATAR][34] = 127,
[2][1][2][1][RTW89_FCC][41] = 60,
[2][1][2][1][RTW89_ETSI][41] = 6,
[2][1][2][1][RTW89_MKK][41] = 127,
@@ -31940,6 +36400,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][41] = 58,
[2][1][2][1][RTW89_CN][41] = 40,
[2][1][2][1][RTW89_UK][41] = 40,
+ [2][1][2][1][RTW89_MEXICO][41] = 60,
+ [2][1][2][1][RTW89_UKRAINE][41] = 6,
+ [2][1][2][1][RTW89_CHILE][41] = 58,
+ [2][1][2][1][RTW89_QATAR][41] = 6,
[2][1][2][1][RTW89_FCC][49] = 62,
[2][1][2][1][RTW89_ETSI][49] = 127,
[2][1][2][1][RTW89_MKK][49] = 127,
@@ -31948,6 +36412,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[2][1][2][1][RTW89_ACMA][49] = 127,
[2][1][2][1][RTW89_CN][49] = 127,
[2][1][2][1][RTW89_UK][49] = 127,
+ [2][1][2][1][RTW89_MEXICO][49] = 127,
+ [2][1][2][1][RTW89_UKRAINE][49] = 127,
+ [2][1][2][1][RTW89_CHILE][49] = 127,
+ [2][1][2][1][RTW89_QATAR][49] = 127,
[3][0][2][0][RTW89_FCC][7] = 40,
[3][0][2][0][RTW89_ETSI][7] = 50,
[3][0][2][0][RTW89_MKK][7] = 50,
@@ -31956,6 +36424,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][7] = 127,
[3][0][2][0][RTW89_CN][7] = 66,
[3][0][2][0][RTW89_UK][7] = 127,
+ [3][0][2][0][RTW89_MEXICO][7] = 127,
+ [3][0][2][0][RTW89_UKRAINE][7] = 50,
+ [3][0][2][0][RTW89_CHILE][7] = 40,
+ [3][0][2][0][RTW89_QATAR][7] = 50,
[3][0][2][0][RTW89_FCC][22] = 42,
[3][0][2][0][RTW89_ETSI][22] = 50,
[3][0][2][0][RTW89_MKK][22] = 50,
@@ -31964,6 +36436,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][22] = 127,
[3][0][2][0][RTW89_CN][22] = 66,
[3][0][2][0][RTW89_UK][22] = 127,
+ [3][0][2][0][RTW89_MEXICO][22] = 127,
+ [3][0][2][0][RTW89_UKRAINE][22] = 50,
+ [3][0][2][0][RTW89_CHILE][22] = 42,
+ [3][0][2][0][RTW89_QATAR][22] = 50,
[3][0][2][0][RTW89_FCC][45] = 52,
[3][0][2][0][RTW89_ETSI][45] = 127,
[3][0][2][0][RTW89_MKK][45] = 127,
@@ -31972,6 +36448,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][0][2][0][RTW89_ACMA][45] = 127,
[3][0][2][0][RTW89_CN][45] = 127,
[3][0][2][0][RTW89_UK][45] = 127,
+ [3][0][2][0][RTW89_MEXICO][45] = 127,
+ [3][0][2][0][RTW89_UKRAINE][45] = 127,
+ [3][0][2][0][RTW89_CHILE][45] = 127,
+ [3][0][2][0][RTW89_QATAR][45] = 127,
[3][1][2][0][RTW89_FCC][7] = 32,
[3][1][2][0][RTW89_ETSI][7] = 50,
[3][1][2][0][RTW89_MKK][7] = 36,
@@ -31980,6 +36460,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][7] = 127,
[3][1][2][0][RTW89_CN][7] = 54,
[3][1][2][0][RTW89_UK][7] = 127,
+ [3][1][2][0][RTW89_MEXICO][7] = 127,
+ [3][1][2][0][RTW89_UKRAINE][7] = 50,
+ [3][1][2][0][RTW89_CHILE][7] = 32,
+ [3][1][2][0][RTW89_QATAR][7] = 50,
[3][1][2][0][RTW89_FCC][22] = 36,
[3][1][2][0][RTW89_ETSI][22] = 50,
[3][1][2][0][RTW89_MKK][22] = 48,
@@ -31988,6 +36472,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][22] = 127,
[3][1][2][0][RTW89_CN][22] = 54,
[3][1][2][0][RTW89_UK][22] = 127,
+ [3][1][2][0][RTW89_MEXICO][22] = 127,
+ [3][1][2][0][RTW89_UKRAINE][22] = 50,
+ [3][1][2][0][RTW89_CHILE][22] = 36,
+ [3][1][2][0][RTW89_QATAR][22] = 50,
[3][1][2][0][RTW89_FCC][45] = 46,
[3][1][2][0][RTW89_ETSI][45] = 127,
[3][1][2][0][RTW89_MKK][45] = 127,
@@ -31996,6 +36484,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][0][RTW89_ACMA][45] = 127,
[3][1][2][0][RTW89_CN][45] = 127,
[3][1][2][0][RTW89_UK][45] = 127,
+ [3][1][2][0][RTW89_MEXICO][45] = 127,
+ [3][1][2][0][RTW89_UKRAINE][45] = 127,
+ [3][1][2][0][RTW89_CHILE][45] = 127,
+ [3][1][2][0][RTW89_QATAR][45] = 127,
[3][1][2][1][RTW89_FCC][7] = 32,
[3][1][2][1][RTW89_ETSI][7] = 42,
[3][1][2][1][RTW89_MKK][7] = 36,
@@ -32004,6 +36496,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][7] = 127,
[3][1][2][1][RTW89_CN][7] = 42,
[3][1][2][1][RTW89_UK][7] = 127,
+ [3][1][2][1][RTW89_MEXICO][7] = 127,
+ [3][1][2][1][RTW89_UKRAINE][7] = 42,
+ [3][1][2][1][RTW89_CHILE][7] = 32,
+ [3][1][2][1][RTW89_QATAR][7] = 42,
[3][1][2][1][RTW89_FCC][22] = 36,
[3][1][2][1][RTW89_ETSI][22] = 42,
[3][1][2][1][RTW89_MKK][22] = 48,
@@ -32012,6 +36508,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][22] = 127,
[3][1][2][1][RTW89_CN][22] = 42,
[3][1][2][1][RTW89_UK][22] = 127,
+ [3][1][2][1][RTW89_MEXICO][22] = 127,
+ [3][1][2][1][RTW89_UKRAINE][22] = 42,
+ [3][1][2][1][RTW89_CHILE][22] = 36,
+ [3][1][2][1][RTW89_QATAR][22] = 42,
[3][1][2][1][RTW89_FCC][45] = 46,
[3][1][2][1][RTW89_ETSI][45] = 127,
[3][1][2][1][RTW89_MKK][45] = 127,
@@ -32020,1964 +36520,9289 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[3][1][2][1][RTW89_ACMA][45] = 127,
[3][1][2][1][RTW89_CN][45] = 127,
[3][1][2][1][RTW89_UK][45] = 127,
+ [3][1][2][1][RTW89_MEXICO][45] = 127,
+ [3][1][2][1][RTW89_UKRAINE][45] = 127,
+ [3][1][2][1][RTW89_CHILE][45] = 127,
+ [3][1][2][1][RTW89_QATAR][45] = 127,
};
static
const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
- [0][0][1][0][RTW89_WW][0] = 24,
- [0][0][1][0][RTW89_WW][2] = 22,
- [0][0][1][0][RTW89_WW][4] = 22,
- [0][0][1][0][RTW89_WW][6] = 22,
- [0][0][1][0][RTW89_WW][8] = 22,
- [0][0][1][0][RTW89_WW][10] = 22,
- [0][0][1][0][RTW89_WW][12] = 22,
- [0][0][1][0][RTW89_WW][14] = 22,
- [0][0][1][0][RTW89_WW][15] = 22,
- [0][0][1][0][RTW89_WW][17] = 22,
- [0][0][1][0][RTW89_WW][19] = 22,
- [0][0][1][0][RTW89_WW][21] = 22,
- [0][0][1][0][RTW89_WW][23] = 22,
- [0][0][1][0][RTW89_WW][25] = 22,
- [0][0][1][0][RTW89_WW][27] = 22,
- [0][0][1][0][RTW89_WW][29] = 22,
- [0][0][1][0][RTW89_WW][30] = 22,
- [0][0][1][0][RTW89_WW][32] = 22,
- [0][0][1][0][RTW89_WW][34] = 22,
- [0][0][1][0][RTW89_WW][36] = 22,
- [0][0][1][0][RTW89_WW][38] = 22,
- [0][0][1][0][RTW89_WW][40] = 22,
- [0][0][1][0][RTW89_WW][42] = 22,
- [0][0][1][0][RTW89_WW][44] = 22,
- [0][0][1][0][RTW89_WW][45] = 22,
- [0][0][1][0][RTW89_WW][47] = 22,
- [0][0][1][0][RTW89_WW][49] = 24,
- [0][0][1][0][RTW89_WW][51] = 22,
- [0][0][1][0][RTW89_WW][53] = 22,
- [0][0][1][0][RTW89_WW][55] = 22,
- [0][0][1][0][RTW89_WW][57] = 22,
- [0][0][1][0][RTW89_WW][59] = 22,
- [0][0][1][0][RTW89_WW][60] = 22,
- [0][0][1][0][RTW89_WW][62] = 22,
- [0][0][1][0][RTW89_WW][64] = 22,
- [0][0][1][0][RTW89_WW][66] = 22,
- [0][0][1][0][RTW89_WW][68] = 22,
- [0][0][1][0][RTW89_WW][70] = 24,
- [0][0][1][0][RTW89_WW][72] = 22,
- [0][0][1][0][RTW89_WW][74] = 22,
- [0][0][1][0][RTW89_WW][75] = 22,
- [0][0][1][0][RTW89_WW][77] = 22,
- [0][0][1][0][RTW89_WW][79] = 22,
- [0][0][1][0][RTW89_WW][81] = 22,
- [0][0][1][0][RTW89_WW][83] = 22,
- [0][0][1][0][RTW89_WW][85] = 22,
- [0][0][1][0][RTW89_WW][87] = 22,
- [0][0][1][0][RTW89_WW][89] = 22,
- [0][0][1][0][RTW89_WW][90] = 22,
- [0][0][1][0][RTW89_WW][92] = 22,
- [0][0][1][0][RTW89_WW][94] = 22,
- [0][0][1][0][RTW89_WW][96] = 22,
- [0][0][1][0][RTW89_WW][98] = 22,
- [0][0][1][0][RTW89_WW][100] = 22,
- [0][0][1][0][RTW89_WW][102] = 22,
- [0][0][1][0][RTW89_WW][104] = 22,
- [0][0][1][0][RTW89_WW][105] = 22,
- [0][0][1][0][RTW89_WW][107] = 24,
- [0][0][1][0][RTW89_WW][109] = 24,
- [0][0][1][0][RTW89_WW][111] = 0,
- [0][0][1][0][RTW89_WW][113] = 0,
- [0][0][1][0][RTW89_WW][115] = 0,
- [0][0][1][0][RTW89_WW][117] = 0,
- [0][0][1][0][RTW89_WW][119] = 0,
- [0][1][1][0][RTW89_WW][0] = -2,
- [0][1][1][0][RTW89_WW][2] = -4,
- [0][1][1][0][RTW89_WW][4] = -4,
- [0][1][1][0][RTW89_WW][6] = -4,
- [0][1][1][0][RTW89_WW][8] = -4,
- [0][1][1][0][RTW89_WW][10] = -4,
- [0][1][1][0][RTW89_WW][12] = -4,
- [0][1][1][0][RTW89_WW][14] = -4,
- [0][1][1][0][RTW89_WW][15] = -4,
- [0][1][1][0][RTW89_WW][17] = -4,
- [0][1][1][0][RTW89_WW][19] = -4,
- [0][1][1][0][RTW89_WW][21] = -4,
- [0][1][1][0][RTW89_WW][23] = -4,
- [0][1][1][0][RTW89_WW][25] = -4,
- [0][1][1][0][RTW89_WW][27] = -4,
- [0][1][1][0][RTW89_WW][29] = -4,
- [0][1][1][0][RTW89_WW][30] = -4,
- [0][1][1][0][RTW89_WW][32] = -4,
- [0][1][1][0][RTW89_WW][34] = -4,
- [0][1][1][0][RTW89_WW][36] = -4,
- [0][1][1][0][RTW89_WW][38] = -4,
- [0][1][1][0][RTW89_WW][40] = -4,
- [0][1][1][0][RTW89_WW][42] = -4,
- [0][1][1][0][RTW89_WW][44] = -2,
- [0][1][1][0][RTW89_WW][45] = -2,
- [0][1][1][0][RTW89_WW][47] = -2,
- [0][1][1][0][RTW89_WW][49] = -2,
- [0][1][1][0][RTW89_WW][51] = -2,
- [0][1][1][0][RTW89_WW][53] = -2,
- [0][1][1][0][RTW89_WW][55] = -2,
- [0][1][1][0][RTW89_WW][57] = -2,
- [0][1][1][0][RTW89_WW][59] = -2,
- [0][1][1][0][RTW89_WW][60] = -2,
- [0][1][1][0][RTW89_WW][62] = -2,
- [0][1][1][0][RTW89_WW][64] = -2,
- [0][1][1][0][RTW89_WW][66] = -2,
- [0][1][1][0][RTW89_WW][68] = -2,
- [0][1][1][0][RTW89_WW][70] = -2,
- [0][1][1][0][RTW89_WW][72] = -2,
- [0][1][1][0][RTW89_WW][74] = -2,
- [0][1][1][0][RTW89_WW][75] = -2,
- [0][1][1][0][RTW89_WW][77] = -2,
- [0][1][1][0][RTW89_WW][79] = -2,
- [0][1][1][0][RTW89_WW][81] = -2,
- [0][1][1][0][RTW89_WW][83] = -2,
- [0][1][1][0][RTW89_WW][85] = -2,
- [0][1][1][0][RTW89_WW][87] = -2,
- [0][1][1][0][RTW89_WW][89] = -2,
- [0][1][1][0][RTW89_WW][90] = -2,
- [0][1][1][0][RTW89_WW][92] = -2,
- [0][1][1][0][RTW89_WW][94] = -2,
- [0][1][1][0][RTW89_WW][96] = -2,
- [0][1][1][0][RTW89_WW][98] = -2,
- [0][1][1][0][RTW89_WW][100] = -2,
- [0][1][1][0][RTW89_WW][102] = -2,
- [0][1][1][0][RTW89_WW][104] = -2,
- [0][1][1][0][RTW89_WW][105] = -2,
- [0][1][1][0][RTW89_WW][107] = 1,
- [0][1][1][0][RTW89_WW][109] = 1,
- [0][1][1][0][RTW89_WW][111] = 0,
- [0][1][1][0][RTW89_WW][113] = 0,
- [0][1][1][0][RTW89_WW][115] = 0,
- [0][1][1][0][RTW89_WW][117] = 0,
- [0][1][1][0][RTW89_WW][119] = 0,
- [0][0][2][0][RTW89_WW][0] = 24,
- [0][0][2][0][RTW89_WW][2] = 22,
- [0][0][2][0][RTW89_WW][4] = 22,
- [0][0][2][0][RTW89_WW][6] = 22,
- [0][0][2][0][RTW89_WW][8] = 22,
- [0][0][2][0][RTW89_WW][10] = 22,
- [0][0][2][0][RTW89_WW][12] = 22,
- [0][0][2][0][RTW89_WW][14] = 22,
- [0][0][2][0][RTW89_WW][15] = 22,
- [0][0][2][0][RTW89_WW][17] = 22,
- [0][0][2][0][RTW89_WW][19] = 22,
- [0][0][2][0][RTW89_WW][21] = 22,
- [0][0][2][0][RTW89_WW][23] = 22,
- [0][0][2][0][RTW89_WW][25] = 22,
- [0][0][2][0][RTW89_WW][27] = 22,
- [0][0][2][0][RTW89_WW][29] = 22,
- [0][0][2][0][RTW89_WW][30] = 22,
- [0][0][2][0][RTW89_WW][32] = 22,
- [0][0][2][0][RTW89_WW][34] = 22,
- [0][0][2][0][RTW89_WW][36] = 22,
- [0][0][2][0][RTW89_WW][38] = 22,
- [0][0][2][0][RTW89_WW][40] = 22,
- [0][0][2][0][RTW89_WW][42] = 22,
- [0][0][2][0][RTW89_WW][44] = 22,
- [0][0][2][0][RTW89_WW][45] = 22,
- [0][0][2][0][RTW89_WW][47] = 22,
- [0][0][2][0][RTW89_WW][49] = 24,
- [0][0][2][0][RTW89_WW][51] = 22,
- [0][0][2][0][RTW89_WW][53] = 22,
- [0][0][2][0][RTW89_WW][55] = 22,
- [0][0][2][0][RTW89_WW][57] = 22,
- [0][0][2][0][RTW89_WW][59] = 22,
- [0][0][2][0][RTW89_WW][60] = 22,
- [0][0][2][0][RTW89_WW][62] = 22,
- [0][0][2][0][RTW89_WW][64] = 22,
- [0][0][2][0][RTW89_WW][66] = 22,
- [0][0][2][0][RTW89_WW][68] = 22,
- [0][0][2][0][RTW89_WW][70] = 24,
- [0][0][2][0][RTW89_WW][72] = 22,
- [0][0][2][0][RTW89_WW][74] = 22,
- [0][0][2][0][RTW89_WW][75] = 22,
- [0][0][2][0][RTW89_WW][77] = 22,
- [0][0][2][0][RTW89_WW][79] = 22,
- [0][0][2][0][RTW89_WW][81] = 22,
- [0][0][2][0][RTW89_WW][83] = 22,
- [0][0][2][0][RTW89_WW][85] = 22,
- [0][0][2][0][RTW89_WW][87] = 22,
- [0][0][2][0][RTW89_WW][89] = 22,
- [0][0][2][0][RTW89_WW][90] = 22,
- [0][0][2][0][RTW89_WW][92] = 22,
- [0][0][2][0][RTW89_WW][94] = 22,
- [0][0][2][0][RTW89_WW][96] = 22,
- [0][0][2][0][RTW89_WW][98] = 22,
- [0][0][2][0][RTW89_WW][100] = 22,
- [0][0][2][0][RTW89_WW][102] = 22,
- [0][0][2][0][RTW89_WW][104] = 22,
- [0][0][2][0][RTW89_WW][105] = 22,
- [0][0][2][0][RTW89_WW][107] = 24,
- [0][0][2][0][RTW89_WW][109] = 24,
- [0][0][2][0][RTW89_WW][111] = 0,
- [0][0][2][0][RTW89_WW][113] = 0,
- [0][0][2][0][RTW89_WW][115] = 0,
- [0][0][2][0][RTW89_WW][117] = 0,
- [0][0][2][0][RTW89_WW][119] = 0,
- [0][1][2][0][RTW89_WW][0] = -2,
- [0][1][2][0][RTW89_WW][2] = -4,
- [0][1][2][0][RTW89_WW][4] = -4,
- [0][1][2][0][RTW89_WW][6] = -4,
- [0][1][2][0][RTW89_WW][8] = -4,
- [0][1][2][0][RTW89_WW][10] = -4,
- [0][1][2][0][RTW89_WW][12] = -4,
- [0][1][2][0][RTW89_WW][14] = -4,
- [0][1][2][0][RTW89_WW][15] = -4,
- [0][1][2][0][RTW89_WW][17] = -4,
- [0][1][2][0][RTW89_WW][19] = -4,
- [0][1][2][0][RTW89_WW][21] = -4,
- [0][1][2][0][RTW89_WW][23] = -4,
- [0][1][2][0][RTW89_WW][25] = -4,
- [0][1][2][0][RTW89_WW][27] = -4,
- [0][1][2][0][RTW89_WW][29] = -4,
- [0][1][2][0][RTW89_WW][30] = -4,
- [0][1][2][0][RTW89_WW][32] = -4,
- [0][1][2][0][RTW89_WW][34] = -4,
- [0][1][2][0][RTW89_WW][36] = -4,
- [0][1][2][0][RTW89_WW][38] = -4,
- [0][1][2][0][RTW89_WW][40] = -4,
- [0][1][2][0][RTW89_WW][42] = -4,
- [0][1][2][0][RTW89_WW][44] = -2,
- [0][1][2][0][RTW89_WW][45] = -2,
- [0][1][2][0][RTW89_WW][47] = -2,
- [0][1][2][0][RTW89_WW][49] = -2,
- [0][1][2][0][RTW89_WW][51] = -2,
- [0][1][2][0][RTW89_WW][53] = -2,
- [0][1][2][0][RTW89_WW][55] = -2,
- [0][1][2][0][RTW89_WW][57] = -2,
- [0][1][2][0][RTW89_WW][59] = -2,
- [0][1][2][0][RTW89_WW][60] = -2,
- [0][1][2][0][RTW89_WW][62] = -2,
- [0][1][2][0][RTW89_WW][64] = -2,
- [0][1][2][0][RTW89_WW][66] = -2,
- [0][1][2][0][RTW89_WW][68] = -2,
- [0][1][2][0][RTW89_WW][70] = -2,
- [0][1][2][0][RTW89_WW][72] = -2,
- [0][1][2][0][RTW89_WW][74] = -2,
- [0][1][2][0][RTW89_WW][75] = -2,
- [0][1][2][0][RTW89_WW][77] = -2,
- [0][1][2][0][RTW89_WW][79] = -2,
- [0][1][2][0][RTW89_WW][81] = -2,
- [0][1][2][0][RTW89_WW][83] = -2,
- [0][1][2][0][RTW89_WW][85] = -2,
- [0][1][2][0][RTW89_WW][87] = -2,
- [0][1][2][0][RTW89_WW][89] = -2,
- [0][1][2][0][RTW89_WW][90] = -2,
- [0][1][2][0][RTW89_WW][92] = -2,
- [0][1][2][0][RTW89_WW][94] = -2,
- [0][1][2][0][RTW89_WW][96] = -2,
- [0][1][2][0][RTW89_WW][98] = -2,
- [0][1][2][0][RTW89_WW][100] = -2,
- [0][1][2][0][RTW89_WW][102] = -2,
- [0][1][2][0][RTW89_WW][104] = -2,
- [0][1][2][0][RTW89_WW][105] = -2,
- [0][1][2][0][RTW89_WW][107] = 1,
- [0][1][2][0][RTW89_WW][109] = 1,
- [0][1][2][0][RTW89_WW][111] = 0,
- [0][1][2][0][RTW89_WW][113] = 0,
- [0][1][2][0][RTW89_WW][115] = 0,
- [0][1][2][0][RTW89_WW][117] = 0,
- [0][1][2][0][RTW89_WW][119] = 0,
- [0][1][2][1][RTW89_WW][0] = -2,
- [0][1][2][1][RTW89_WW][2] = -4,
- [0][1][2][1][RTW89_WW][4] = -4,
- [0][1][2][1][RTW89_WW][6] = -4,
- [0][1][2][1][RTW89_WW][8] = -4,
- [0][1][2][1][RTW89_WW][10] = -4,
- [0][1][2][1][RTW89_WW][12] = -4,
- [0][1][2][1][RTW89_WW][14] = -4,
- [0][1][2][1][RTW89_WW][15] = -4,
- [0][1][2][1][RTW89_WW][17] = -4,
- [0][1][2][1][RTW89_WW][19] = -4,
- [0][1][2][1][RTW89_WW][21] = -4,
- [0][1][2][1][RTW89_WW][23] = -4,
- [0][1][2][1][RTW89_WW][25] = -4,
- [0][1][2][1][RTW89_WW][27] = -4,
- [0][1][2][1][RTW89_WW][29] = -4,
- [0][1][2][1][RTW89_WW][30] = -4,
- [0][1][2][1][RTW89_WW][32] = -4,
- [0][1][2][1][RTW89_WW][34] = -4,
- [0][1][2][1][RTW89_WW][36] = -4,
- [0][1][2][1][RTW89_WW][38] = -4,
- [0][1][2][1][RTW89_WW][40] = -4,
- [0][1][2][1][RTW89_WW][42] = -4,
- [0][1][2][1][RTW89_WW][44] = -2,
- [0][1][2][1][RTW89_WW][45] = -2,
- [0][1][2][1][RTW89_WW][47] = -2,
- [0][1][2][1][RTW89_WW][49] = -2,
- [0][1][2][1][RTW89_WW][51] = -2,
- [0][1][2][1][RTW89_WW][53] = -2,
- [0][1][2][1][RTW89_WW][55] = -2,
- [0][1][2][1][RTW89_WW][57] = -2,
- [0][1][2][1][RTW89_WW][59] = -2,
- [0][1][2][1][RTW89_WW][60] = -2,
- [0][1][2][1][RTW89_WW][62] = -2,
- [0][1][2][1][RTW89_WW][64] = -2,
- [0][1][2][1][RTW89_WW][66] = -2,
- [0][1][2][1][RTW89_WW][68] = -2,
- [0][1][2][1][RTW89_WW][70] = -2,
- [0][1][2][1][RTW89_WW][72] = -2,
- [0][1][2][1][RTW89_WW][74] = -2,
- [0][1][2][1][RTW89_WW][75] = -2,
- [0][1][2][1][RTW89_WW][77] = -2,
- [0][1][2][1][RTW89_WW][79] = -2,
- [0][1][2][1][RTW89_WW][81] = -2,
- [0][1][2][1][RTW89_WW][83] = -2,
- [0][1][2][1][RTW89_WW][85] = -2,
- [0][1][2][1][RTW89_WW][87] = -2,
- [0][1][2][1][RTW89_WW][89] = -2,
- [0][1][2][1][RTW89_WW][90] = -2,
- [0][1][2][1][RTW89_WW][92] = -2,
- [0][1][2][1][RTW89_WW][94] = -2,
- [0][1][2][1][RTW89_WW][96] = -2,
- [0][1][2][1][RTW89_WW][98] = -2,
- [0][1][2][1][RTW89_WW][100] = -2,
- [0][1][2][1][RTW89_WW][102] = -2,
- [0][1][2][1][RTW89_WW][104] = -2,
- [0][1][2][1][RTW89_WW][105] = -2,
- [0][1][2][1][RTW89_WW][107] = 1,
- [0][1][2][1][RTW89_WW][109] = 1,
- [0][1][2][1][RTW89_WW][111] = 0,
- [0][1][2][1][RTW89_WW][113] = 0,
- [0][1][2][1][RTW89_WW][115] = 0,
- [0][1][2][1][RTW89_WW][117] = 0,
- [0][1][2][1][RTW89_WW][119] = 0,
- [1][0][2][0][RTW89_WW][1] = 34,
- [1][0][2][0][RTW89_WW][5] = 34,
- [1][0][2][0][RTW89_WW][9] = 34,
- [1][0][2][0][RTW89_WW][13] = 34,
- [1][0][2][0][RTW89_WW][16] = 34,
- [1][0][2][0][RTW89_WW][20] = 34,
- [1][0][2][0][RTW89_WW][24] = 36,
- [1][0][2][0][RTW89_WW][28] = 34,
- [1][0][2][0][RTW89_WW][31] = 34,
- [1][0][2][0][RTW89_WW][35] = 34,
- [1][0][2][0][RTW89_WW][39] = 34,
- [1][0][2][0][RTW89_WW][43] = 34,
- [1][0][2][0][RTW89_WW][46] = 34,
- [1][0][2][0][RTW89_WW][50] = 34,
- [1][0][2][0][RTW89_WW][54] = 36,
- [1][0][2][0][RTW89_WW][58] = 36,
- [1][0][2][0][RTW89_WW][61] = 34,
- [1][0][2][0][RTW89_WW][65] = 34,
- [1][0][2][0][RTW89_WW][69] = 34,
- [1][0][2][0][RTW89_WW][73] = 34,
- [1][0][2][0][RTW89_WW][76] = 34,
- [1][0][2][0][RTW89_WW][80] = 34,
- [1][0][2][0][RTW89_WW][84] = 34,
- [1][0][2][0][RTW89_WW][88] = 34,
- [1][0][2][0][RTW89_WW][91] = 36,
- [1][0][2][0][RTW89_WW][95] = 34,
- [1][0][2][0][RTW89_WW][99] = 34,
- [1][0][2][0][RTW89_WW][103] = 34,
- [1][0][2][0][RTW89_WW][106] = 36,
- [1][0][2][0][RTW89_WW][110] = 0,
- [1][0][2][0][RTW89_WW][114] = 0,
- [1][0][2][0][RTW89_WW][118] = 0,
- [1][1][2][0][RTW89_WW][1] = 10,
- [1][1][2][0][RTW89_WW][5] = 10,
- [1][1][2][0][RTW89_WW][9] = 10,
- [1][1][2][0][RTW89_WW][13] = 10,
- [1][1][2][0][RTW89_WW][16] = 10,
- [1][1][2][0][RTW89_WW][20] = 10,
- [1][1][2][0][RTW89_WW][24] = 10,
- [1][1][2][0][RTW89_WW][28] = 10,
- [1][1][2][0][RTW89_WW][31] = 10,
- [1][1][2][0][RTW89_WW][35] = 10,
- [1][1][2][0][RTW89_WW][39] = 10,
- [1][1][2][0][RTW89_WW][43] = 10,
- [1][1][2][0][RTW89_WW][46] = 12,
- [1][1][2][0][RTW89_WW][50] = 12,
- [1][1][2][0][RTW89_WW][54] = 10,
- [1][1][2][0][RTW89_WW][58] = 10,
- [1][1][2][0][RTW89_WW][61] = 10,
- [1][1][2][0][RTW89_WW][65] = 10,
- [1][1][2][0][RTW89_WW][69] = 10,
- [1][1][2][0][RTW89_WW][73] = 10,
- [1][1][2][0][RTW89_WW][76] = 10,
- [1][1][2][0][RTW89_WW][80] = 10,
- [1][1][2][0][RTW89_WW][84] = 10,
- [1][1][2][0][RTW89_WW][88] = 10,
- [1][1][2][0][RTW89_WW][91] = 12,
- [1][1][2][0][RTW89_WW][95] = 10,
- [1][1][2][0][RTW89_WW][99] = 10,
- [1][1][2][0][RTW89_WW][103] = 10,
- [1][1][2][0][RTW89_WW][106] = 12,
- [1][1][2][0][RTW89_WW][110] = 0,
- [1][1][2][0][RTW89_WW][114] = 0,
- [1][1][2][0][RTW89_WW][118] = 0,
- [1][1][2][1][RTW89_WW][1] = 10,
- [1][1][2][1][RTW89_WW][5] = 10,
- [1][1][2][1][RTW89_WW][9] = 10,
- [1][1][2][1][RTW89_WW][13] = 10,
- [1][1][2][1][RTW89_WW][16] = 10,
- [1][1][2][1][RTW89_WW][20] = 10,
- [1][1][2][1][RTW89_WW][24] = 10,
- [1][1][2][1][RTW89_WW][28] = 10,
- [1][1][2][1][RTW89_WW][31] = 10,
- [1][1][2][1][RTW89_WW][35] = 10,
- [1][1][2][1][RTW89_WW][39] = 10,
- [1][1][2][1][RTW89_WW][43] = 10,
- [1][1][2][1][RTW89_WW][46] = 12,
- [1][1][2][1][RTW89_WW][50] = 12,
- [1][1][2][1][RTW89_WW][54] = 10,
- [1][1][2][1][RTW89_WW][58] = 10,
- [1][1][2][1][RTW89_WW][61] = 10,
- [1][1][2][1][RTW89_WW][65] = 10,
- [1][1][2][1][RTW89_WW][69] = 10,
- [1][1][2][1][RTW89_WW][73] = 10,
- [1][1][2][1][RTW89_WW][76] = 10,
- [1][1][2][1][RTW89_WW][80] = 10,
- [1][1][2][1][RTW89_WW][84] = 10,
- [1][1][2][1][RTW89_WW][88] = 10,
- [1][1][2][1][RTW89_WW][91] = 12,
- [1][1][2][1][RTW89_WW][95] = 10,
- [1][1][2][1][RTW89_WW][99] = 10,
- [1][1][2][1][RTW89_WW][103] = 10,
- [1][1][2][1][RTW89_WW][106] = 12,
- [1][1][2][1][RTW89_WW][110] = 0,
- [1][1][2][1][RTW89_WW][114] = 0,
- [1][1][2][1][RTW89_WW][118] = 0,
- [2][0][2][0][RTW89_WW][3] = 46,
- [2][0][2][0][RTW89_WW][11] = 46,
- [2][0][2][0][RTW89_WW][18] = 46,
- [2][0][2][0][RTW89_WW][26] = 46,
- [2][0][2][0][RTW89_WW][33] = 46,
- [2][0][2][0][RTW89_WW][41] = 46,
- [2][0][2][0][RTW89_WW][48] = 46,
- [2][0][2][0][RTW89_WW][56] = 46,
- [2][0][2][0][RTW89_WW][63] = 46,
- [2][0][2][0][RTW89_WW][71] = 46,
- [2][0][2][0][RTW89_WW][78] = 46,
- [2][0][2][0][RTW89_WW][86] = 46,
- [2][0][2][0][RTW89_WW][93] = 46,
- [2][0][2][0][RTW89_WW][101] = 44,
- [2][0][2][0][RTW89_WW][108] = 0,
- [2][0][2][0][RTW89_WW][116] = 0,
- [2][1][2][0][RTW89_WW][3] = 22,
- [2][1][2][0][RTW89_WW][11] = 20,
- [2][1][2][0][RTW89_WW][18] = 20,
- [2][1][2][0][RTW89_WW][26] = 20,
- [2][1][2][0][RTW89_WW][33] = 20,
- [2][1][2][0][RTW89_WW][41] = 22,
- [2][1][2][0][RTW89_WW][48] = 22,
- [2][1][2][0][RTW89_WW][56] = 20,
- [2][1][2][0][RTW89_WW][63] = 22,
- [2][1][2][0][RTW89_WW][71] = 20,
- [2][1][2][0][RTW89_WW][78] = 20,
- [2][1][2][0][RTW89_WW][86] = 20,
- [2][1][2][0][RTW89_WW][93] = 22,
- [2][1][2][0][RTW89_WW][101] = 22,
- [2][1][2][0][RTW89_WW][108] = 0,
- [2][1][2][0][RTW89_WW][116] = 0,
- [2][1][2][1][RTW89_WW][3] = 22,
- [2][1][2][1][RTW89_WW][11] = 20,
- [2][1][2][1][RTW89_WW][18] = 20,
- [2][1][2][1][RTW89_WW][26] = 20,
- [2][1][2][1][RTW89_WW][33] = 20,
- [2][1][2][1][RTW89_WW][41] = 22,
- [2][1][2][1][RTW89_WW][48] = 22,
- [2][1][2][1][RTW89_WW][56] = 20,
- [2][1][2][1][RTW89_WW][63] = 22,
- [2][1][2][1][RTW89_WW][71] = 20,
- [2][1][2][1][RTW89_WW][78] = 20,
- [2][1][2][1][RTW89_WW][86] = 20,
- [2][1][2][1][RTW89_WW][93] = 22,
- [2][1][2][1][RTW89_WW][101] = 22,
- [2][1][2][1][RTW89_WW][108] = 0,
- [2][1][2][1][RTW89_WW][116] = 0,
- [3][0][2][0][RTW89_WW][7] = 38,
- [3][0][2][0][RTW89_WW][22] = 38,
- [3][0][2][0][RTW89_WW][37] = 38,
- [3][0][2][0][RTW89_WW][52] = 54,
- [3][0][2][0][RTW89_WW][67] = 54,
- [3][0][2][0][RTW89_WW][82] = 26,
- [3][0][2][0][RTW89_WW][97] = 26,
- [3][0][2][0][RTW89_WW][112] = 0,
- [3][1][2][0][RTW89_WW][7] = 32,
- [3][1][2][0][RTW89_WW][22] = 30,
- [3][1][2][0][RTW89_WW][37] = 30,
- [3][1][2][0][RTW89_WW][52] = 30,
- [3][1][2][0][RTW89_WW][67] = 32,
- [3][1][2][0][RTW89_WW][82] = 24,
- [3][1][2][0][RTW89_WW][97] = 14,
- [3][1][2][0][RTW89_WW][112] = 0,
- [3][1][2][1][RTW89_WW][7] = 32,
- [3][1][2][1][RTW89_WW][22] = 30,
- [3][1][2][1][RTW89_WW][37] = 30,
- [3][1][2][1][RTW89_WW][52] = 30,
- [3][1][2][1][RTW89_WW][67] = 32,
- [3][1][2][1][RTW89_WW][82] = 24,
- [3][1][2][1][RTW89_WW][97] = 14,
- [3][1][2][1][RTW89_WW][112] = 0,
- [0][0][1][0][RTW89_FCC][0] = 24,
- [0][0][1][0][RTW89_ETSI][0] = 66,
- [0][0][1][0][RTW89_KCC][0] = 24,
- [0][0][1][0][RTW89_FCC][2] = 22,
- [0][0][1][0][RTW89_ETSI][2] = 66,
- [0][0][1][0][RTW89_KCC][2] = 24,
- [0][0][1][0][RTW89_FCC][4] = 22,
- [0][0][1][0][RTW89_ETSI][4] = 66,
- [0][0][1][0][RTW89_KCC][4] = 24,
- [0][0][1][0][RTW89_FCC][6] = 22,
- [0][0][1][0][RTW89_ETSI][6] = 66,
- [0][0][1][0][RTW89_KCC][6] = 24,
- [0][0][1][0][RTW89_FCC][8] = 22,
- [0][0][1][0][RTW89_ETSI][8] = 66,
- [0][0][1][0][RTW89_KCC][8] = 24,
- [0][0][1][0][RTW89_FCC][10] = 22,
- [0][0][1][0][RTW89_ETSI][10] = 66,
- [0][0][1][0][RTW89_KCC][10] = 24,
- [0][0][1][0][RTW89_FCC][12] = 22,
- [0][0][1][0][RTW89_ETSI][12] = 66,
- [0][0][1][0][RTW89_KCC][12] = 24,
- [0][0][1][0][RTW89_FCC][14] = 22,
- [0][0][1][0][RTW89_ETSI][14] = 66,
- [0][0][1][0][RTW89_KCC][14] = 24,
- [0][0][1][0][RTW89_FCC][15] = 22,
- [0][0][1][0][RTW89_ETSI][15] = 66,
- [0][0][1][0][RTW89_KCC][15] = 24,
- [0][0][1][0][RTW89_FCC][17] = 22,
- [0][0][1][0][RTW89_ETSI][17] = 66,
- [0][0][1][0][RTW89_KCC][17] = 24,
- [0][0][1][0][RTW89_FCC][19] = 22,
- [0][0][1][0][RTW89_ETSI][19] = 66,
- [0][0][1][0][RTW89_KCC][19] = 24,
- [0][0][1][0][RTW89_FCC][21] = 22,
- [0][0][1][0][RTW89_ETSI][21] = 66,
- [0][0][1][0][RTW89_KCC][21] = 24,
- [0][0][1][0][RTW89_FCC][23] = 22,
- [0][0][1][0][RTW89_ETSI][23] = 66,
- [0][0][1][0][RTW89_KCC][23] = 24,
- [0][0][1][0][RTW89_FCC][25] = 22,
- [0][0][1][0][RTW89_ETSI][25] = 66,
- [0][0][1][0][RTW89_KCC][25] = 24,
- [0][0][1][0][RTW89_FCC][27] = 22,
- [0][0][1][0][RTW89_ETSI][27] = 66,
- [0][0][1][0][RTW89_KCC][27] = 24,
- [0][0][1][0][RTW89_FCC][29] = 22,
- [0][0][1][0][RTW89_ETSI][29] = 66,
- [0][0][1][0][RTW89_KCC][29] = 24,
- [0][0][1][0][RTW89_FCC][30] = 22,
- [0][0][1][0][RTW89_ETSI][30] = 66,
- [0][0][1][0][RTW89_KCC][30] = 24,
- [0][0][1][0][RTW89_FCC][32] = 22,
- [0][0][1][0][RTW89_ETSI][32] = 66,
- [0][0][1][0][RTW89_KCC][32] = 24,
- [0][0][1][0][RTW89_FCC][34] = 22,
- [0][0][1][0][RTW89_ETSI][34] = 66,
- [0][0][1][0][RTW89_KCC][34] = 24,
- [0][0][1][0][RTW89_FCC][36] = 22,
- [0][0][1][0][RTW89_ETSI][36] = 66,
- [0][0][1][0][RTW89_KCC][36] = 24,
- [0][0][1][0][RTW89_FCC][38] = 22,
- [0][0][1][0][RTW89_ETSI][38] = 66,
- [0][0][1][0][RTW89_KCC][38] = 24,
- [0][0][1][0][RTW89_FCC][40] = 22,
- [0][0][1][0][RTW89_ETSI][40] = 66,
- [0][0][1][0][RTW89_KCC][40] = 24,
- [0][0][1][0][RTW89_FCC][42] = 22,
- [0][0][1][0][RTW89_ETSI][42] = 66,
- [0][0][1][0][RTW89_KCC][42] = 24,
- [0][0][1][0][RTW89_FCC][44] = 22,
- [0][0][1][0][RTW89_ETSI][44] = 66,
- [0][0][1][0][RTW89_KCC][44] = 24,
- [0][0][1][0][RTW89_FCC][45] = 22,
- [0][0][1][0][RTW89_ETSI][45] = 127,
- [0][0][1][0][RTW89_KCC][45] = 24,
- [0][0][1][0][RTW89_FCC][47] = 22,
- [0][0][1][0][RTW89_ETSI][47] = 127,
- [0][0][1][0][RTW89_KCC][47] = 24,
- [0][0][1][0][RTW89_FCC][49] = 24,
- [0][0][1][0][RTW89_ETSI][49] = 127,
- [0][0][1][0][RTW89_KCC][49] = 24,
- [0][0][1][0][RTW89_FCC][51] = 22,
- [0][0][1][0][RTW89_ETSI][51] = 127,
- [0][0][1][0][RTW89_KCC][51] = 24,
- [0][0][1][0][RTW89_FCC][53] = 22,
- [0][0][1][0][RTW89_ETSI][53] = 127,
- [0][0][1][0][RTW89_KCC][53] = 24,
- [0][0][1][0][RTW89_FCC][55] = 22,
- [0][0][1][0][RTW89_ETSI][55] = 127,
- [0][0][1][0][RTW89_KCC][55] = 26,
- [0][0][1][0][RTW89_FCC][57] = 22,
- [0][0][1][0][RTW89_ETSI][57] = 127,
- [0][0][1][0][RTW89_KCC][57] = 26,
- [0][0][1][0][RTW89_FCC][59] = 22,
- [0][0][1][0][RTW89_ETSI][59] = 127,
- [0][0][1][0][RTW89_KCC][59] = 26,
- [0][0][1][0][RTW89_FCC][60] = 22,
- [0][0][1][0][RTW89_ETSI][60] = 127,
- [0][0][1][0][RTW89_KCC][60] = 26,
- [0][0][1][0][RTW89_FCC][62] = 22,
- [0][0][1][0][RTW89_ETSI][62] = 127,
- [0][0][1][0][RTW89_KCC][62] = 26,
- [0][0][1][0][RTW89_FCC][64] = 22,
- [0][0][1][0][RTW89_ETSI][64] = 127,
- [0][0][1][0][RTW89_KCC][64] = 26,
- [0][0][1][0][RTW89_FCC][66] = 22,
- [0][0][1][0][RTW89_ETSI][66] = 127,
- [0][0][1][0][RTW89_KCC][66] = 26,
- [0][0][1][0][RTW89_FCC][68] = 22,
- [0][0][1][0][RTW89_ETSI][68] = 127,
- [0][0][1][0][RTW89_KCC][68] = 26,
- [0][0][1][0][RTW89_FCC][70] = 24,
- [0][0][1][0][RTW89_ETSI][70] = 127,
- [0][0][1][0][RTW89_KCC][70] = 26,
- [0][0][1][0][RTW89_FCC][72] = 22,
- [0][0][1][0][RTW89_ETSI][72] = 127,
- [0][0][1][0][RTW89_KCC][72] = 26,
- [0][0][1][0][RTW89_FCC][74] = 22,
- [0][0][1][0][RTW89_ETSI][74] = 127,
- [0][0][1][0][RTW89_KCC][74] = 26,
- [0][0][1][0][RTW89_FCC][75] = 22,
- [0][0][1][0][RTW89_ETSI][75] = 127,
- [0][0][1][0][RTW89_KCC][75] = 26,
- [0][0][1][0][RTW89_FCC][77] = 22,
- [0][0][1][0][RTW89_ETSI][77] = 127,
- [0][0][1][0][RTW89_KCC][77] = 26,
- [0][0][1][0][RTW89_FCC][79] = 22,
- [0][0][1][0][RTW89_ETSI][79] = 127,
- [0][0][1][0][RTW89_KCC][79] = 26,
- [0][0][1][0][RTW89_FCC][81] = 22,
- [0][0][1][0][RTW89_ETSI][81] = 127,
- [0][0][1][0][RTW89_KCC][81] = 26,
- [0][0][1][0][RTW89_FCC][83] = 22,
- [0][0][1][0][RTW89_ETSI][83] = 127,
- [0][0][1][0][RTW89_KCC][83] = 32,
- [0][0][1][0][RTW89_FCC][85] = 22,
- [0][0][1][0][RTW89_ETSI][85] = 127,
- [0][0][1][0][RTW89_KCC][85] = 32,
- [0][0][1][0][RTW89_FCC][87] = 22,
- [0][0][1][0][RTW89_ETSI][87] = 127,
- [0][0][1][0][RTW89_KCC][87] = 32,
- [0][0][1][0][RTW89_FCC][89] = 22,
- [0][0][1][0][RTW89_ETSI][89] = 127,
- [0][0][1][0][RTW89_KCC][89] = 32,
- [0][0][1][0][RTW89_FCC][90] = 22,
- [0][0][1][0][RTW89_ETSI][90] = 127,
- [0][0][1][0][RTW89_KCC][90] = 32,
- [0][0][1][0][RTW89_FCC][92] = 22,
- [0][0][1][0][RTW89_ETSI][92] = 127,
- [0][0][1][0][RTW89_KCC][92] = 32,
- [0][0][1][0][RTW89_FCC][94] = 22,
- [0][0][1][0][RTW89_ETSI][94] = 127,
- [0][0][1][0][RTW89_KCC][94] = 32,
- [0][0][1][0][RTW89_FCC][96] = 22,
- [0][0][1][0][RTW89_ETSI][96] = 127,
- [0][0][1][0][RTW89_KCC][96] = 32,
- [0][0][1][0][RTW89_FCC][98] = 22,
- [0][0][1][0][RTW89_ETSI][98] = 127,
- [0][0][1][0][RTW89_KCC][98] = 32,
- [0][0][1][0][RTW89_FCC][100] = 22,
- [0][0][1][0][RTW89_ETSI][100] = 127,
- [0][0][1][0][RTW89_KCC][100] = 32,
- [0][0][1][0][RTW89_FCC][102] = 22,
- [0][0][1][0][RTW89_ETSI][102] = 127,
- [0][0][1][0][RTW89_KCC][102] = 32,
- [0][0][1][0][RTW89_FCC][104] = 22,
- [0][0][1][0][RTW89_ETSI][104] = 127,
- [0][0][1][0][RTW89_KCC][104] = 32,
- [0][0][1][0][RTW89_FCC][105] = 22,
- [0][0][1][0][RTW89_ETSI][105] = 127,
- [0][0][1][0][RTW89_KCC][105] = 32,
- [0][0][1][0][RTW89_FCC][107] = 24,
- [0][0][1][0][RTW89_ETSI][107] = 127,
- [0][0][1][0][RTW89_KCC][107] = 32,
- [0][0][1][0][RTW89_FCC][109] = 24,
- [0][0][1][0][RTW89_ETSI][109] = 127,
- [0][0][1][0][RTW89_KCC][109] = 32,
- [0][0][1][0][RTW89_FCC][111] = 127,
- [0][0][1][0][RTW89_ETSI][111] = 127,
- [0][0][1][0][RTW89_KCC][111] = 127,
- [0][0][1][0][RTW89_FCC][113] = 127,
- [0][0][1][0][RTW89_ETSI][113] = 127,
- [0][0][1][0][RTW89_KCC][113] = 127,
- [0][0][1][0][RTW89_FCC][115] = 127,
- [0][0][1][0][RTW89_ETSI][115] = 127,
- [0][0][1][0][RTW89_KCC][115] = 127,
- [0][0][1][0][RTW89_FCC][117] = 127,
- [0][0][1][0][RTW89_ETSI][117] = 127,
- [0][0][1][0][RTW89_KCC][117] = 127,
- [0][0][1][0][RTW89_FCC][119] = 127,
- [0][0][1][0][RTW89_ETSI][119] = 127,
- [0][0][1][0][RTW89_KCC][119] = 127,
- [0][1][1][0][RTW89_FCC][0] = -2,
- [0][1][1][0][RTW89_ETSI][0] = 54,
- [0][1][1][0][RTW89_KCC][0] = 12,
- [0][1][1][0][RTW89_FCC][2] = -4,
- [0][1][1][0][RTW89_ETSI][2] = 54,
- [0][1][1][0][RTW89_KCC][2] = 12,
- [0][1][1][0][RTW89_FCC][4] = -4,
- [0][1][1][0][RTW89_ETSI][4] = 54,
- [0][1][1][0][RTW89_KCC][4] = 12,
- [0][1][1][0][RTW89_FCC][6] = -4,
- [0][1][1][0][RTW89_ETSI][6] = 54,
- [0][1][1][0][RTW89_KCC][6] = 12,
- [0][1][1][0][RTW89_FCC][8] = -4,
- [0][1][1][0][RTW89_ETSI][8] = 54,
- [0][1][1][0][RTW89_KCC][8] = 12,
- [0][1][1][0][RTW89_FCC][10] = -4,
- [0][1][1][0][RTW89_ETSI][10] = 54,
- [0][1][1][0][RTW89_KCC][10] = 12,
- [0][1][1][0][RTW89_FCC][12] = -4,
- [0][1][1][0][RTW89_ETSI][12] = 54,
- [0][1][1][0][RTW89_KCC][12] = 12,
- [0][1][1][0][RTW89_FCC][14] = -4,
- [0][1][1][0][RTW89_ETSI][14] = 54,
- [0][1][1][0][RTW89_KCC][14] = 12,
- [0][1][1][0][RTW89_FCC][15] = -4,
- [0][1][1][0][RTW89_ETSI][15] = 54,
- [0][1][1][0][RTW89_KCC][15] = 12,
- [0][1][1][0][RTW89_FCC][17] = -4,
- [0][1][1][0][RTW89_ETSI][17] = 54,
- [0][1][1][0][RTW89_KCC][17] = 12,
- [0][1][1][0][RTW89_FCC][19] = -4,
- [0][1][1][0][RTW89_ETSI][19] = 54,
- [0][1][1][0][RTW89_KCC][19] = 12,
- [0][1][1][0][RTW89_FCC][21] = -4,
- [0][1][1][0][RTW89_ETSI][21] = 54,
- [0][1][1][0][RTW89_KCC][21] = 12,
- [0][1][1][0][RTW89_FCC][23] = -4,
- [0][1][1][0][RTW89_ETSI][23] = 54,
- [0][1][1][0][RTW89_KCC][23] = 12,
- [0][1][1][0][RTW89_FCC][25] = -4,
- [0][1][1][0][RTW89_ETSI][25] = 54,
- [0][1][1][0][RTW89_KCC][25] = 12,
- [0][1][1][0][RTW89_FCC][27] = -4,
- [0][1][1][0][RTW89_ETSI][27] = 54,
- [0][1][1][0][RTW89_KCC][27] = 12,
- [0][1][1][0][RTW89_FCC][29] = -4,
- [0][1][1][0][RTW89_ETSI][29] = 54,
- [0][1][1][0][RTW89_KCC][29] = 12,
- [0][1][1][0][RTW89_FCC][30] = -4,
- [0][1][1][0][RTW89_ETSI][30] = 54,
- [0][1][1][0][RTW89_KCC][30] = 12,
- [0][1][1][0][RTW89_FCC][32] = -4,
- [0][1][1][0][RTW89_ETSI][32] = 54,
- [0][1][1][0][RTW89_KCC][32] = 12,
- [0][1][1][0][RTW89_FCC][34] = -4,
- [0][1][1][0][RTW89_ETSI][34] = 54,
- [0][1][1][0][RTW89_KCC][34] = 12,
- [0][1][1][0][RTW89_FCC][36] = -4,
- [0][1][1][0][RTW89_ETSI][36] = 54,
- [0][1][1][0][RTW89_KCC][36] = 12,
- [0][1][1][0][RTW89_FCC][38] = -4,
- [0][1][1][0][RTW89_ETSI][38] = 54,
- [0][1][1][0][RTW89_KCC][38] = 12,
- [0][1][1][0][RTW89_FCC][40] = -4,
- [0][1][1][0][RTW89_ETSI][40] = 54,
- [0][1][1][0][RTW89_KCC][40] = 12,
- [0][1][1][0][RTW89_FCC][42] = -4,
- [0][1][1][0][RTW89_ETSI][42] = 54,
- [0][1][1][0][RTW89_KCC][42] = 12,
- [0][1][1][0][RTW89_FCC][44] = -2,
- [0][1][1][0][RTW89_ETSI][44] = 54,
- [0][1][1][0][RTW89_KCC][44] = 12,
- [0][1][1][0][RTW89_FCC][45] = -2,
- [0][1][1][0][RTW89_ETSI][45] = 127,
- [0][1][1][0][RTW89_KCC][45] = 12,
- [0][1][1][0][RTW89_FCC][47] = -2,
- [0][1][1][0][RTW89_ETSI][47] = 127,
- [0][1][1][0][RTW89_KCC][47] = 12,
- [0][1][1][0][RTW89_FCC][49] = -2,
- [0][1][1][0][RTW89_ETSI][49] = 127,
- [0][1][1][0][RTW89_KCC][49] = 12,
- [0][1][1][0][RTW89_FCC][51] = -2,
- [0][1][1][0][RTW89_ETSI][51] = 127,
- [0][1][1][0][RTW89_KCC][51] = 12,
- [0][1][1][0][RTW89_FCC][53] = -2,
- [0][1][1][0][RTW89_ETSI][53] = 127,
- [0][1][1][0][RTW89_KCC][53] = 12,
- [0][1][1][0][RTW89_FCC][55] = -2,
- [0][1][1][0][RTW89_ETSI][55] = 127,
- [0][1][1][0][RTW89_KCC][55] = 12,
- [0][1][1][0][RTW89_FCC][57] = -2,
- [0][1][1][0][RTW89_ETSI][57] = 127,
- [0][1][1][0][RTW89_KCC][57] = 12,
- [0][1][1][0][RTW89_FCC][59] = -2,
- [0][1][1][0][RTW89_ETSI][59] = 127,
- [0][1][1][0][RTW89_KCC][59] = 12,
- [0][1][1][0][RTW89_FCC][60] = -2,
- [0][1][1][0][RTW89_ETSI][60] = 127,
- [0][1][1][0][RTW89_KCC][60] = 12,
- [0][1][1][0][RTW89_FCC][62] = -2,
- [0][1][1][0][RTW89_ETSI][62] = 127,
- [0][1][1][0][RTW89_KCC][62] = 12,
- [0][1][1][0][RTW89_FCC][64] = -2,
- [0][1][1][0][RTW89_ETSI][64] = 127,
- [0][1][1][0][RTW89_KCC][64] = 12,
- [0][1][1][0][RTW89_FCC][66] = -2,
- [0][1][1][0][RTW89_ETSI][66] = 127,
- [0][1][1][0][RTW89_KCC][66] = 12,
- [0][1][1][0][RTW89_FCC][68] = -2,
- [0][1][1][0][RTW89_ETSI][68] = 127,
- [0][1][1][0][RTW89_KCC][68] = 12,
- [0][1][1][0][RTW89_FCC][70] = -2,
- [0][1][1][0][RTW89_ETSI][70] = 127,
- [0][1][1][0][RTW89_KCC][70] = 12,
- [0][1][1][0][RTW89_FCC][72] = -2,
- [0][1][1][0][RTW89_ETSI][72] = 127,
- [0][1][1][0][RTW89_KCC][72] = 12,
- [0][1][1][0][RTW89_FCC][74] = -2,
- [0][1][1][0][RTW89_ETSI][74] = 127,
- [0][1][1][0][RTW89_KCC][74] = 12,
- [0][1][1][0][RTW89_FCC][75] = -2,
- [0][1][1][0][RTW89_ETSI][75] = 127,
- [0][1][1][0][RTW89_KCC][75] = 12,
- [0][1][1][0][RTW89_FCC][77] = -2,
- [0][1][1][0][RTW89_ETSI][77] = 127,
- [0][1][1][0][RTW89_KCC][77] = 12,
- [0][1][1][0][RTW89_FCC][79] = -2,
- [0][1][1][0][RTW89_ETSI][79] = 127,
- [0][1][1][0][RTW89_KCC][79] = 12,
- [0][1][1][0][RTW89_FCC][81] = -2,
- [0][1][1][0][RTW89_ETSI][81] = 127,
- [0][1][1][0][RTW89_KCC][81] = 12,
- [0][1][1][0][RTW89_FCC][83] = -2,
- [0][1][1][0][RTW89_ETSI][83] = 127,
- [0][1][1][0][RTW89_KCC][83] = 20,
- [0][1][1][0][RTW89_FCC][85] = -2,
- [0][1][1][0][RTW89_ETSI][85] = 127,
- [0][1][1][0][RTW89_KCC][85] = 20,
- [0][1][1][0][RTW89_FCC][87] = -2,
- [0][1][1][0][RTW89_ETSI][87] = 127,
- [0][1][1][0][RTW89_KCC][87] = 20,
- [0][1][1][0][RTW89_FCC][89] = -2,
- [0][1][1][0][RTW89_ETSI][89] = 127,
- [0][1][1][0][RTW89_KCC][89] = 20,
- [0][1][1][0][RTW89_FCC][90] = -2,
- [0][1][1][0][RTW89_ETSI][90] = 127,
- [0][1][1][0][RTW89_KCC][90] = 20,
- [0][1][1][0][RTW89_FCC][92] = -2,
- [0][1][1][0][RTW89_ETSI][92] = 127,
- [0][1][1][0][RTW89_KCC][92] = 20,
- [0][1][1][0][RTW89_FCC][94] = -2,
- [0][1][1][0][RTW89_ETSI][94] = 127,
- [0][1][1][0][RTW89_KCC][94] = 20,
- [0][1][1][0][RTW89_FCC][96] = -2,
- [0][1][1][0][RTW89_ETSI][96] = 127,
- [0][1][1][0][RTW89_KCC][96] = 20,
- [0][1][1][0][RTW89_FCC][98] = -2,
- [0][1][1][0][RTW89_ETSI][98] = 127,
- [0][1][1][0][RTW89_KCC][98] = 20,
- [0][1][1][0][RTW89_FCC][100] = -2,
- [0][1][1][0][RTW89_ETSI][100] = 127,
- [0][1][1][0][RTW89_KCC][100] = 20,
- [0][1][1][0][RTW89_FCC][102] = -2,
- [0][1][1][0][RTW89_ETSI][102] = 127,
- [0][1][1][0][RTW89_KCC][102] = 20,
- [0][1][1][0][RTW89_FCC][104] = -2,
- [0][1][1][0][RTW89_ETSI][104] = 127,
- [0][1][1][0][RTW89_KCC][104] = 20,
- [0][1][1][0][RTW89_FCC][105] = -2,
- [0][1][1][0][RTW89_ETSI][105] = 127,
- [0][1][1][0][RTW89_KCC][105] = 20,
- [0][1][1][0][RTW89_FCC][107] = 0,
- [0][1][1][0][RTW89_ETSI][107] = 127,
- [0][1][1][0][RTW89_KCC][107] = 20,
- [0][1][1][0][RTW89_FCC][109] = 0,
- [0][1][1][0][RTW89_ETSI][109] = 127,
- [0][1][1][0][RTW89_KCC][109] = 20,
- [0][1][1][0][RTW89_FCC][111] = 127,
- [0][1][1][0][RTW89_ETSI][111] = 127,
- [0][1][1][0][RTW89_KCC][111] = 127,
- [0][1][1][0][RTW89_FCC][113] = 127,
- [0][1][1][0][RTW89_ETSI][113] = 127,
- [0][1][1][0][RTW89_KCC][113] = 127,
- [0][1][1][0][RTW89_FCC][115] = 127,
- [0][1][1][0][RTW89_ETSI][115] = 127,
- [0][1][1][0][RTW89_KCC][115] = 127,
- [0][1][1][0][RTW89_FCC][117] = 127,
- [0][1][1][0][RTW89_ETSI][117] = 127,
- [0][1][1][0][RTW89_KCC][117] = 127,
- [0][1][1][0][RTW89_FCC][119] = 127,
- [0][1][1][0][RTW89_ETSI][119] = 127,
- [0][1][1][0][RTW89_KCC][119] = 127,
- [0][0][2][0][RTW89_FCC][0] = 24,
- [0][0][2][0][RTW89_ETSI][0] = 66,
- [0][0][2][0][RTW89_KCC][0] = 24,
- [0][0][2][0][RTW89_FCC][2] = 22,
- [0][0][2][0][RTW89_ETSI][2] = 66,
- [0][0][2][0][RTW89_KCC][2] = 24,
- [0][0][2][0][RTW89_FCC][4] = 22,
- [0][0][2][0][RTW89_ETSI][4] = 66,
- [0][0][2][0][RTW89_KCC][4] = 24,
- [0][0][2][0][RTW89_FCC][6] = 22,
- [0][0][2][0][RTW89_ETSI][6] = 66,
- [0][0][2][0][RTW89_KCC][6] = 24,
- [0][0][2][0][RTW89_FCC][8] = 22,
- [0][0][2][0][RTW89_ETSI][8] = 66,
- [0][0][2][0][RTW89_KCC][8] = 24,
- [0][0][2][0][RTW89_FCC][10] = 22,
- [0][0][2][0][RTW89_ETSI][10] = 66,
- [0][0][2][0][RTW89_KCC][10] = 24,
- [0][0][2][0][RTW89_FCC][12] = 22,
- [0][0][2][0][RTW89_ETSI][12] = 66,
- [0][0][2][0][RTW89_KCC][12] = 24,
- [0][0][2][0][RTW89_FCC][14] = 22,
- [0][0][2][0][RTW89_ETSI][14] = 66,
- [0][0][2][0][RTW89_KCC][14] = 24,
- [0][0][2][0][RTW89_FCC][15] = 22,
- [0][0][2][0][RTW89_ETSI][15] = 66,
- [0][0][2][0][RTW89_KCC][15] = 24,
- [0][0][2][0][RTW89_FCC][17] = 22,
- [0][0][2][0][RTW89_ETSI][17] = 66,
- [0][0][2][0][RTW89_KCC][17] = 24,
- [0][0][2][0][RTW89_FCC][19] = 22,
- [0][0][2][0][RTW89_ETSI][19] = 66,
- [0][0][2][0][RTW89_KCC][19] = 24,
- [0][0][2][0][RTW89_FCC][21] = 22,
- [0][0][2][0][RTW89_ETSI][21] = 66,
- [0][0][2][0][RTW89_KCC][21] = 24,
- [0][0][2][0][RTW89_FCC][23] = 22,
- [0][0][2][0][RTW89_ETSI][23] = 66,
- [0][0][2][0][RTW89_KCC][23] = 24,
- [0][0][2][0][RTW89_FCC][25] = 22,
- [0][0][2][0][RTW89_ETSI][25] = 66,
- [0][0][2][0][RTW89_KCC][25] = 24,
- [0][0][2][0][RTW89_FCC][27] = 22,
- [0][0][2][0][RTW89_ETSI][27] = 66,
- [0][0][2][0][RTW89_KCC][27] = 24,
- [0][0][2][0][RTW89_FCC][29] = 22,
- [0][0][2][0][RTW89_ETSI][29] = 66,
- [0][0][2][0][RTW89_KCC][29] = 24,
- [0][0][2][0][RTW89_FCC][30] = 22,
- [0][0][2][0][RTW89_ETSI][30] = 66,
- [0][0][2][0][RTW89_KCC][30] = 24,
- [0][0][2][0][RTW89_FCC][32] = 22,
- [0][0][2][0][RTW89_ETSI][32] = 66,
- [0][0][2][0][RTW89_KCC][32] = 24,
- [0][0][2][0][RTW89_FCC][34] = 22,
- [0][0][2][0][RTW89_ETSI][34] = 66,
- [0][0][2][0][RTW89_KCC][34] = 24,
- [0][0][2][0][RTW89_FCC][36] = 22,
- [0][0][2][0][RTW89_ETSI][36] = 66,
- [0][0][2][0][RTW89_KCC][36] = 24,
- [0][0][2][0][RTW89_FCC][38] = 22,
- [0][0][2][0][RTW89_ETSI][38] = 66,
- [0][0][2][0][RTW89_KCC][38] = 24,
- [0][0][2][0][RTW89_FCC][40] = 22,
- [0][0][2][0][RTW89_ETSI][40] = 66,
- [0][0][2][0][RTW89_KCC][40] = 24,
- [0][0][2][0][RTW89_FCC][42] = 22,
- [0][0][2][0][RTW89_ETSI][42] = 66,
- [0][0][2][0][RTW89_KCC][42] = 24,
- [0][0][2][0][RTW89_FCC][44] = 22,
- [0][0][2][0][RTW89_ETSI][44] = 66,
- [0][0][2][0][RTW89_KCC][44] = 24,
- [0][0][2][0][RTW89_FCC][45] = 22,
- [0][0][2][0][RTW89_ETSI][45] = 127,
- [0][0][2][0][RTW89_KCC][45] = 24,
- [0][0][2][0][RTW89_FCC][47] = 22,
- [0][0][2][0][RTW89_ETSI][47] = 127,
- [0][0][2][0][RTW89_KCC][47] = 24,
- [0][0][2][0][RTW89_FCC][49] = 24,
- [0][0][2][0][RTW89_ETSI][49] = 127,
- [0][0][2][0][RTW89_KCC][49] = 24,
- [0][0][2][0][RTW89_FCC][51] = 22,
- [0][0][2][0][RTW89_ETSI][51] = 127,
- [0][0][2][0][RTW89_KCC][51] = 24,
- [0][0][2][0][RTW89_FCC][53] = 22,
- [0][0][2][0][RTW89_ETSI][53] = 127,
- [0][0][2][0][RTW89_KCC][53] = 24,
- [0][0][2][0][RTW89_FCC][55] = 22,
- [0][0][2][0][RTW89_ETSI][55] = 127,
- [0][0][2][0][RTW89_KCC][55] = 26,
- [0][0][2][0][RTW89_FCC][57] = 22,
- [0][0][2][0][RTW89_ETSI][57] = 127,
- [0][0][2][0][RTW89_KCC][57] = 26,
- [0][0][2][0][RTW89_FCC][59] = 22,
- [0][0][2][0][RTW89_ETSI][59] = 127,
- [0][0][2][0][RTW89_KCC][59] = 26,
- [0][0][2][0][RTW89_FCC][60] = 22,
- [0][0][2][0][RTW89_ETSI][60] = 127,
- [0][0][2][0][RTW89_KCC][60] = 26,
- [0][0][2][0][RTW89_FCC][62] = 22,
- [0][0][2][0][RTW89_ETSI][62] = 127,
- [0][0][2][0][RTW89_KCC][62] = 26,
- [0][0][2][0][RTW89_FCC][64] = 22,
- [0][0][2][0][RTW89_ETSI][64] = 127,
- [0][0][2][0][RTW89_KCC][64] = 26,
- [0][0][2][0][RTW89_FCC][66] = 22,
- [0][0][2][0][RTW89_ETSI][66] = 127,
- [0][0][2][0][RTW89_KCC][66] = 26,
- [0][0][2][0][RTW89_FCC][68] = 22,
- [0][0][2][0][RTW89_ETSI][68] = 127,
- [0][0][2][0][RTW89_KCC][68] = 26,
- [0][0][2][0][RTW89_FCC][70] = 24,
- [0][0][2][0][RTW89_ETSI][70] = 127,
- [0][0][2][0][RTW89_KCC][70] = 26,
- [0][0][2][0][RTW89_FCC][72] = 22,
- [0][0][2][0][RTW89_ETSI][72] = 127,
- [0][0][2][0][RTW89_KCC][72] = 26,
- [0][0][2][0][RTW89_FCC][74] = 22,
- [0][0][2][0][RTW89_ETSI][74] = 127,
- [0][0][2][0][RTW89_KCC][74] = 26,
- [0][0][2][0][RTW89_FCC][75] = 22,
- [0][0][2][0][RTW89_ETSI][75] = 127,
- [0][0][2][0][RTW89_KCC][75] = 26,
- [0][0][2][0][RTW89_FCC][77] = 22,
- [0][0][2][0][RTW89_ETSI][77] = 127,
- [0][0][2][0][RTW89_KCC][77] = 26,
- [0][0][2][0][RTW89_FCC][79] = 22,
- [0][0][2][0][RTW89_ETSI][79] = 127,
- [0][0][2][0][RTW89_KCC][79] = 26,
- [0][0][2][0][RTW89_FCC][81] = 22,
- [0][0][2][0][RTW89_ETSI][81] = 127,
- [0][0][2][0][RTW89_KCC][81] = 26,
- [0][0][2][0][RTW89_FCC][83] = 22,
- [0][0][2][0][RTW89_ETSI][83] = 127,
- [0][0][2][0][RTW89_KCC][83] = 32,
- [0][0][2][0][RTW89_FCC][85] = 22,
- [0][0][2][0][RTW89_ETSI][85] = 127,
- [0][0][2][0][RTW89_KCC][85] = 32,
- [0][0][2][0][RTW89_FCC][87] = 22,
- [0][0][2][0][RTW89_ETSI][87] = 127,
- [0][0][2][0][RTW89_KCC][87] = 32,
- [0][0][2][0][RTW89_FCC][89] = 22,
- [0][0][2][0][RTW89_ETSI][89] = 127,
- [0][0][2][0][RTW89_KCC][89] = 32,
- [0][0][2][0][RTW89_FCC][90] = 22,
- [0][0][2][0][RTW89_ETSI][90] = 127,
- [0][0][2][0][RTW89_KCC][90] = 32,
- [0][0][2][0][RTW89_FCC][92] = 22,
- [0][0][2][0][RTW89_ETSI][92] = 127,
- [0][0][2][0][RTW89_KCC][92] = 32,
- [0][0][2][0][RTW89_FCC][94] = 22,
- [0][0][2][0][RTW89_ETSI][94] = 127,
- [0][0][2][0][RTW89_KCC][94] = 32,
- [0][0][2][0][RTW89_FCC][96] = 22,
- [0][0][2][0][RTW89_ETSI][96] = 127,
- [0][0][2][0][RTW89_KCC][96] = 32,
- [0][0][2][0][RTW89_FCC][98] = 22,
- [0][0][2][0][RTW89_ETSI][98] = 127,
- [0][0][2][0][RTW89_KCC][98] = 32,
- [0][0][2][0][RTW89_FCC][100] = 22,
- [0][0][2][0][RTW89_ETSI][100] = 127,
- [0][0][2][0][RTW89_KCC][100] = 32,
- [0][0][2][0][RTW89_FCC][102] = 22,
- [0][0][2][0][RTW89_ETSI][102] = 127,
- [0][0][2][0][RTW89_KCC][102] = 32,
- [0][0][2][0][RTW89_FCC][104] = 22,
- [0][0][2][0][RTW89_ETSI][104] = 127,
- [0][0][2][0][RTW89_KCC][104] = 32,
- [0][0][2][0][RTW89_FCC][105] = 22,
- [0][0][2][0][RTW89_ETSI][105] = 127,
- [0][0][2][0][RTW89_KCC][105] = 32,
- [0][0][2][0][RTW89_FCC][107] = 24,
- [0][0][2][0][RTW89_ETSI][107] = 127,
- [0][0][2][0][RTW89_KCC][107] = 32,
- [0][0][2][0][RTW89_FCC][109] = 24,
- [0][0][2][0][RTW89_ETSI][109] = 127,
- [0][0][2][0][RTW89_KCC][109] = 32,
- [0][0][2][0][RTW89_FCC][111] = 127,
- [0][0][2][0][RTW89_ETSI][111] = 127,
- [0][0][2][0][RTW89_KCC][111] = 127,
- [0][0][2][0][RTW89_FCC][113] = 127,
- [0][0][2][0][RTW89_ETSI][113] = 127,
- [0][0][2][0][RTW89_KCC][113] = 127,
- [0][0][2][0][RTW89_FCC][115] = 127,
- [0][0][2][0][RTW89_ETSI][115] = 127,
- [0][0][2][0][RTW89_KCC][115] = 127,
- [0][0][2][0][RTW89_FCC][117] = 127,
- [0][0][2][0][RTW89_ETSI][117] = 127,
- [0][0][2][0][RTW89_KCC][117] = 127,
- [0][0][2][0][RTW89_FCC][119] = 127,
- [0][0][2][0][RTW89_ETSI][119] = 127,
- [0][0][2][0][RTW89_KCC][119] = 127,
- [0][1][2][0][RTW89_FCC][0] = -2,
- [0][1][2][0][RTW89_ETSI][0] = 54,
- [0][1][2][0][RTW89_KCC][0] = 12,
- [0][1][2][0][RTW89_FCC][2] = -4,
- [0][1][2][0][RTW89_ETSI][2] = 54,
- [0][1][2][0][RTW89_KCC][2] = 12,
- [0][1][2][0][RTW89_FCC][4] = -4,
- [0][1][2][0][RTW89_ETSI][4] = 54,
- [0][1][2][0][RTW89_KCC][4] = 12,
- [0][1][2][0][RTW89_FCC][6] = -4,
- [0][1][2][0][RTW89_ETSI][6] = 54,
- [0][1][2][0][RTW89_KCC][6] = 12,
- [0][1][2][0][RTW89_FCC][8] = -4,
- [0][1][2][0][RTW89_ETSI][8] = 54,
- [0][1][2][0][RTW89_KCC][8] = 12,
- [0][1][2][0][RTW89_FCC][10] = -4,
- [0][1][2][0][RTW89_ETSI][10] = 54,
- [0][1][2][0][RTW89_KCC][10] = 12,
- [0][1][2][0][RTW89_FCC][12] = -4,
- [0][1][2][0][RTW89_ETSI][12] = 54,
- [0][1][2][0][RTW89_KCC][12] = 12,
- [0][1][2][0][RTW89_FCC][14] = -4,
- [0][1][2][0][RTW89_ETSI][14] = 54,
- [0][1][2][0][RTW89_KCC][14] = 12,
- [0][1][2][0][RTW89_FCC][15] = -4,
- [0][1][2][0][RTW89_ETSI][15] = 54,
- [0][1][2][0][RTW89_KCC][15] = 12,
- [0][1][2][0][RTW89_FCC][17] = -4,
- [0][1][2][0][RTW89_ETSI][17] = 54,
- [0][1][2][0][RTW89_KCC][17] = 12,
- [0][1][2][0][RTW89_FCC][19] = -4,
- [0][1][2][0][RTW89_ETSI][19] = 54,
- [0][1][2][0][RTW89_KCC][19] = 12,
- [0][1][2][0][RTW89_FCC][21] = -4,
- [0][1][2][0][RTW89_ETSI][21] = 54,
- [0][1][2][0][RTW89_KCC][21] = 12,
- [0][1][2][0][RTW89_FCC][23] = -4,
- [0][1][2][0][RTW89_ETSI][23] = 54,
- [0][1][2][0][RTW89_KCC][23] = 12,
- [0][1][2][0][RTW89_FCC][25] = -4,
- [0][1][2][0][RTW89_ETSI][25] = 54,
- [0][1][2][0][RTW89_KCC][25] = 12,
- [0][1][2][0][RTW89_FCC][27] = -4,
- [0][1][2][0][RTW89_ETSI][27] = 54,
- [0][1][2][0][RTW89_KCC][27] = 12,
- [0][1][2][0][RTW89_FCC][29] = -4,
- [0][1][2][0][RTW89_ETSI][29] = 54,
- [0][1][2][0][RTW89_KCC][29] = 12,
- [0][1][2][0][RTW89_FCC][30] = -4,
- [0][1][2][0][RTW89_ETSI][30] = 54,
- [0][1][2][0][RTW89_KCC][30] = 12,
- [0][1][2][0][RTW89_FCC][32] = -4,
- [0][1][2][0][RTW89_ETSI][32] = 54,
- [0][1][2][0][RTW89_KCC][32] = 12,
- [0][1][2][0][RTW89_FCC][34] = -4,
- [0][1][2][0][RTW89_ETSI][34] = 54,
- [0][1][2][0][RTW89_KCC][34] = 12,
- [0][1][2][0][RTW89_FCC][36] = -4,
- [0][1][2][0][RTW89_ETSI][36] = 54,
- [0][1][2][0][RTW89_KCC][36] = 12,
- [0][1][2][0][RTW89_FCC][38] = -4,
- [0][1][2][0][RTW89_ETSI][38] = 54,
- [0][1][2][0][RTW89_KCC][38] = 12,
- [0][1][2][0][RTW89_FCC][40] = -4,
- [0][1][2][0][RTW89_ETSI][40] = 54,
- [0][1][2][0][RTW89_KCC][40] = 12,
- [0][1][2][0][RTW89_FCC][42] = -4,
- [0][1][2][0][RTW89_ETSI][42] = 54,
- [0][1][2][0][RTW89_KCC][42] = 12,
- [0][1][2][0][RTW89_FCC][44] = -2,
- [0][1][2][0][RTW89_ETSI][44] = 54,
- [0][1][2][0][RTW89_KCC][44] = 12,
- [0][1][2][0][RTW89_FCC][45] = -2,
- [0][1][2][0][RTW89_ETSI][45] = 127,
- [0][1][2][0][RTW89_KCC][45] = 12,
- [0][1][2][0][RTW89_FCC][47] = -2,
- [0][1][2][0][RTW89_ETSI][47] = 127,
- [0][1][2][0][RTW89_KCC][47] = 12,
- [0][1][2][0][RTW89_FCC][49] = -2,
- [0][1][2][0][RTW89_ETSI][49] = 127,
- [0][1][2][0][RTW89_KCC][49] = 12,
- [0][1][2][0][RTW89_FCC][51] = -2,
- [0][1][2][0][RTW89_ETSI][51] = 127,
- [0][1][2][0][RTW89_KCC][51] = 12,
- [0][1][2][0][RTW89_FCC][53] = -2,
- [0][1][2][0][RTW89_ETSI][53] = 127,
- [0][1][2][0][RTW89_KCC][53] = 12,
- [0][1][2][0][RTW89_FCC][55] = -2,
- [0][1][2][0][RTW89_ETSI][55] = 127,
- [0][1][2][0][RTW89_KCC][55] = 12,
- [0][1][2][0][RTW89_FCC][57] = -2,
- [0][1][2][0][RTW89_ETSI][57] = 127,
- [0][1][2][0][RTW89_KCC][57] = 12,
- [0][1][2][0][RTW89_FCC][59] = -2,
- [0][1][2][0][RTW89_ETSI][59] = 127,
- [0][1][2][0][RTW89_KCC][59] = 12,
- [0][1][2][0][RTW89_FCC][60] = -2,
- [0][1][2][0][RTW89_ETSI][60] = 127,
- [0][1][2][0][RTW89_KCC][60] = 12,
- [0][1][2][0][RTW89_FCC][62] = -2,
- [0][1][2][0][RTW89_ETSI][62] = 127,
- [0][1][2][0][RTW89_KCC][62] = 12,
- [0][1][2][0][RTW89_FCC][64] = -2,
- [0][1][2][0][RTW89_ETSI][64] = 127,
- [0][1][2][0][RTW89_KCC][64] = 12,
- [0][1][2][0][RTW89_FCC][66] = -2,
- [0][1][2][0][RTW89_ETSI][66] = 127,
- [0][1][2][0][RTW89_KCC][66] = 12,
- [0][1][2][0][RTW89_FCC][68] = -2,
- [0][1][2][0][RTW89_ETSI][68] = 127,
- [0][1][2][0][RTW89_KCC][68] = 12,
- [0][1][2][0][RTW89_FCC][70] = -2,
- [0][1][2][0][RTW89_ETSI][70] = 127,
- [0][1][2][0][RTW89_KCC][70] = 12,
- [0][1][2][0][RTW89_FCC][72] = -2,
- [0][1][2][0][RTW89_ETSI][72] = 127,
- [0][1][2][0][RTW89_KCC][72] = 12,
- [0][1][2][0][RTW89_FCC][74] = -2,
- [0][1][2][0][RTW89_ETSI][74] = 127,
- [0][1][2][0][RTW89_KCC][74] = 12,
- [0][1][2][0][RTW89_FCC][75] = -2,
- [0][1][2][0][RTW89_ETSI][75] = 127,
- [0][1][2][0][RTW89_KCC][75] = 12,
- [0][1][2][0][RTW89_FCC][77] = -2,
- [0][1][2][0][RTW89_ETSI][77] = 127,
- [0][1][2][0][RTW89_KCC][77] = 12,
- [0][1][2][0][RTW89_FCC][79] = -2,
- [0][1][2][0][RTW89_ETSI][79] = 127,
- [0][1][2][0][RTW89_KCC][79] = 12,
- [0][1][2][0][RTW89_FCC][81] = -2,
- [0][1][2][0][RTW89_ETSI][81] = 127,
- [0][1][2][0][RTW89_KCC][81] = 12,
- [0][1][2][0][RTW89_FCC][83] = -2,
- [0][1][2][0][RTW89_ETSI][83] = 127,
- [0][1][2][0][RTW89_KCC][83] = 20,
- [0][1][2][0][RTW89_FCC][85] = -2,
- [0][1][2][0][RTW89_ETSI][85] = 127,
- [0][1][2][0][RTW89_KCC][85] = 20,
- [0][1][2][0][RTW89_FCC][87] = -2,
- [0][1][2][0][RTW89_ETSI][87] = 127,
- [0][1][2][0][RTW89_KCC][87] = 20,
- [0][1][2][0][RTW89_FCC][89] = -2,
- [0][1][2][0][RTW89_ETSI][89] = 127,
- [0][1][2][0][RTW89_KCC][89] = 20,
- [0][1][2][0][RTW89_FCC][90] = -2,
- [0][1][2][0][RTW89_ETSI][90] = 127,
- [0][1][2][0][RTW89_KCC][90] = 20,
- [0][1][2][0][RTW89_FCC][92] = -2,
- [0][1][2][0][RTW89_ETSI][92] = 127,
- [0][1][2][0][RTW89_KCC][92] = 20,
- [0][1][2][0][RTW89_FCC][94] = -2,
- [0][1][2][0][RTW89_ETSI][94] = 127,
- [0][1][2][0][RTW89_KCC][94] = 20,
- [0][1][2][0][RTW89_FCC][96] = -2,
- [0][1][2][0][RTW89_ETSI][96] = 127,
- [0][1][2][0][RTW89_KCC][96] = 20,
- [0][1][2][0][RTW89_FCC][98] = -2,
- [0][1][2][0][RTW89_ETSI][98] = 127,
- [0][1][2][0][RTW89_KCC][98] = 20,
- [0][1][2][0][RTW89_FCC][100] = -2,
- [0][1][2][0][RTW89_ETSI][100] = 127,
- [0][1][2][0][RTW89_KCC][100] = 20,
- [0][1][2][0][RTW89_FCC][102] = -2,
- [0][1][2][0][RTW89_ETSI][102] = 127,
- [0][1][2][0][RTW89_KCC][102] = 20,
- [0][1][2][0][RTW89_FCC][104] = -2,
- [0][1][2][0][RTW89_ETSI][104] = 127,
- [0][1][2][0][RTW89_KCC][104] = 20,
- [0][1][2][0][RTW89_FCC][105] = -2,
- [0][1][2][0][RTW89_ETSI][105] = 127,
- [0][1][2][0][RTW89_KCC][105] = 20,
- [0][1][2][0][RTW89_FCC][107] = 0,
- [0][1][2][0][RTW89_ETSI][107] = 127,
- [0][1][2][0][RTW89_KCC][107] = 20,
- [0][1][2][0][RTW89_FCC][109] = 0,
- [0][1][2][0][RTW89_ETSI][109] = 127,
- [0][1][2][0][RTW89_KCC][109] = 20,
- [0][1][2][0][RTW89_FCC][111] = 127,
- [0][1][2][0][RTW89_ETSI][111] = 127,
- [0][1][2][0][RTW89_KCC][111] = 127,
- [0][1][2][0][RTW89_FCC][113] = 127,
- [0][1][2][0][RTW89_ETSI][113] = 127,
- [0][1][2][0][RTW89_KCC][113] = 127,
- [0][1][2][0][RTW89_FCC][115] = 127,
- [0][1][2][0][RTW89_ETSI][115] = 127,
- [0][1][2][0][RTW89_KCC][115] = 127,
- [0][1][2][0][RTW89_FCC][117] = 127,
- [0][1][2][0][RTW89_ETSI][117] = 127,
- [0][1][2][0][RTW89_KCC][117] = 127,
- [0][1][2][0][RTW89_FCC][119] = 127,
- [0][1][2][0][RTW89_ETSI][119] = 127,
- [0][1][2][0][RTW89_KCC][119] = 127,
- [0][1][2][1][RTW89_FCC][0] = -2,
- [0][1][2][1][RTW89_ETSI][0] = 42,
- [0][1][2][1][RTW89_KCC][0] = 12,
- [0][1][2][1][RTW89_FCC][2] = -4,
- [0][1][2][1][RTW89_ETSI][2] = 42,
- [0][1][2][1][RTW89_KCC][2] = 12,
- [0][1][2][1][RTW89_FCC][4] = -4,
- [0][1][2][1][RTW89_ETSI][4] = 42,
- [0][1][2][1][RTW89_KCC][4] = 12,
- [0][1][2][1][RTW89_FCC][6] = -4,
- [0][1][2][1][RTW89_ETSI][6] = 42,
- [0][1][2][1][RTW89_KCC][6] = 12,
- [0][1][2][1][RTW89_FCC][8] = -4,
- [0][1][2][1][RTW89_ETSI][8] = 42,
- [0][1][2][1][RTW89_KCC][8] = 12,
- [0][1][2][1][RTW89_FCC][10] = -4,
- [0][1][2][1][RTW89_ETSI][10] = 42,
- [0][1][2][1][RTW89_KCC][10] = 12,
- [0][1][2][1][RTW89_FCC][12] = -4,
- [0][1][2][1][RTW89_ETSI][12] = 42,
- [0][1][2][1][RTW89_KCC][12] = 12,
- [0][1][2][1][RTW89_FCC][14] = -4,
- [0][1][2][1][RTW89_ETSI][14] = 42,
- [0][1][2][1][RTW89_KCC][14] = 12,
- [0][1][2][1][RTW89_FCC][15] = -4,
- [0][1][2][1][RTW89_ETSI][15] = 42,
- [0][1][2][1][RTW89_KCC][15] = 12,
- [0][1][2][1][RTW89_FCC][17] = -4,
- [0][1][2][1][RTW89_ETSI][17] = 42,
- [0][1][2][1][RTW89_KCC][17] = 12,
- [0][1][2][1][RTW89_FCC][19] = -4,
- [0][1][2][1][RTW89_ETSI][19] = 42,
- [0][1][2][1][RTW89_KCC][19] = 12,
- [0][1][2][1][RTW89_FCC][21] = -4,
- [0][1][2][1][RTW89_ETSI][21] = 42,
- [0][1][2][1][RTW89_KCC][21] = 12,
- [0][1][2][1][RTW89_FCC][23] = -4,
- [0][1][2][1][RTW89_ETSI][23] = 42,
- [0][1][2][1][RTW89_KCC][23] = 12,
- [0][1][2][1][RTW89_FCC][25] = -4,
- [0][1][2][1][RTW89_ETSI][25] = 42,
- [0][1][2][1][RTW89_KCC][25] = 12,
- [0][1][2][1][RTW89_FCC][27] = -4,
- [0][1][2][1][RTW89_ETSI][27] = 42,
- [0][1][2][1][RTW89_KCC][27] = 12,
- [0][1][2][1][RTW89_FCC][29] = -4,
- [0][1][2][1][RTW89_ETSI][29] = 42,
- [0][1][2][1][RTW89_KCC][29] = 12,
- [0][1][2][1][RTW89_FCC][30] = -4,
- [0][1][2][1][RTW89_ETSI][30] = 42,
- [0][1][2][1][RTW89_KCC][30] = 12,
- [0][1][2][1][RTW89_FCC][32] = -4,
- [0][1][2][1][RTW89_ETSI][32] = 42,
- [0][1][2][1][RTW89_KCC][32] = 12,
- [0][1][2][1][RTW89_FCC][34] = -4,
- [0][1][2][1][RTW89_ETSI][34] = 42,
- [0][1][2][1][RTW89_KCC][34] = 12,
- [0][1][2][1][RTW89_FCC][36] = -4,
- [0][1][2][1][RTW89_ETSI][36] = 42,
- [0][1][2][1][RTW89_KCC][36] = 12,
- [0][1][2][1][RTW89_FCC][38] = -4,
- [0][1][2][1][RTW89_ETSI][38] = 42,
- [0][1][2][1][RTW89_KCC][38] = 12,
- [0][1][2][1][RTW89_FCC][40] = -4,
- [0][1][2][1][RTW89_ETSI][40] = 42,
- [0][1][2][1][RTW89_KCC][40] = 12,
- [0][1][2][1][RTW89_FCC][42] = -4,
- [0][1][2][1][RTW89_ETSI][42] = 42,
- [0][1][2][1][RTW89_KCC][42] = 12,
- [0][1][2][1][RTW89_FCC][44] = -2,
- [0][1][2][1][RTW89_ETSI][44] = 42,
- [0][1][2][1][RTW89_KCC][44] = 12,
- [0][1][2][1][RTW89_FCC][45] = -2,
- [0][1][2][1][RTW89_ETSI][45] = 127,
- [0][1][2][1][RTW89_KCC][45] = 12,
- [0][1][2][1][RTW89_FCC][47] = -2,
- [0][1][2][1][RTW89_ETSI][47] = 127,
- [0][1][2][1][RTW89_KCC][47] = 12,
- [0][1][2][1][RTW89_FCC][49] = -2,
- [0][1][2][1][RTW89_ETSI][49] = 127,
- [0][1][2][1][RTW89_KCC][49] = 12,
- [0][1][2][1][RTW89_FCC][51] = -2,
- [0][1][2][1][RTW89_ETSI][51] = 127,
- [0][1][2][1][RTW89_KCC][51] = 12,
- [0][1][2][1][RTW89_FCC][53] = -2,
- [0][1][2][1][RTW89_ETSI][53] = 127,
- [0][1][2][1][RTW89_KCC][53] = 12,
- [0][1][2][1][RTW89_FCC][55] = -2,
- [0][1][2][1][RTW89_ETSI][55] = 127,
- [0][1][2][1][RTW89_KCC][55] = 12,
- [0][1][2][1][RTW89_FCC][57] = -2,
- [0][1][2][1][RTW89_ETSI][57] = 127,
- [0][1][2][1][RTW89_KCC][57] = 12,
- [0][1][2][1][RTW89_FCC][59] = -2,
- [0][1][2][1][RTW89_ETSI][59] = 127,
- [0][1][2][1][RTW89_KCC][59] = 12,
- [0][1][2][1][RTW89_FCC][60] = -2,
- [0][1][2][1][RTW89_ETSI][60] = 127,
- [0][1][2][1][RTW89_KCC][60] = 12,
- [0][1][2][1][RTW89_FCC][62] = -2,
- [0][1][2][1][RTW89_ETSI][62] = 127,
- [0][1][2][1][RTW89_KCC][62] = 12,
- [0][1][2][1][RTW89_FCC][64] = -2,
- [0][1][2][1][RTW89_ETSI][64] = 127,
- [0][1][2][1][RTW89_KCC][64] = 12,
- [0][1][2][1][RTW89_FCC][66] = -2,
- [0][1][2][1][RTW89_ETSI][66] = 127,
- [0][1][2][1][RTW89_KCC][66] = 12,
- [0][1][2][1][RTW89_FCC][68] = -2,
- [0][1][2][1][RTW89_ETSI][68] = 127,
- [0][1][2][1][RTW89_KCC][68] = 12,
- [0][1][2][1][RTW89_FCC][70] = -2,
- [0][1][2][1][RTW89_ETSI][70] = 127,
- [0][1][2][1][RTW89_KCC][70] = 12,
- [0][1][2][1][RTW89_FCC][72] = -2,
- [0][1][2][1][RTW89_ETSI][72] = 127,
- [0][1][2][1][RTW89_KCC][72] = 12,
- [0][1][2][1][RTW89_FCC][74] = -2,
- [0][1][2][1][RTW89_ETSI][74] = 127,
- [0][1][2][1][RTW89_KCC][74] = 12,
- [0][1][2][1][RTW89_FCC][75] = -2,
- [0][1][2][1][RTW89_ETSI][75] = 127,
- [0][1][2][1][RTW89_KCC][75] = 12,
- [0][1][2][1][RTW89_FCC][77] = -2,
- [0][1][2][1][RTW89_ETSI][77] = 127,
- [0][1][2][1][RTW89_KCC][77] = 12,
- [0][1][2][1][RTW89_FCC][79] = -2,
- [0][1][2][1][RTW89_ETSI][79] = 127,
- [0][1][2][1][RTW89_KCC][79] = 12,
- [0][1][2][1][RTW89_FCC][81] = -2,
- [0][1][2][1][RTW89_ETSI][81] = 127,
- [0][1][2][1][RTW89_KCC][81] = 12,
- [0][1][2][1][RTW89_FCC][83] = -2,
- [0][1][2][1][RTW89_ETSI][83] = 127,
- [0][1][2][1][RTW89_KCC][83] = 20,
- [0][1][2][1][RTW89_FCC][85] = -2,
- [0][1][2][1][RTW89_ETSI][85] = 127,
- [0][1][2][1][RTW89_KCC][85] = 20,
- [0][1][2][1][RTW89_FCC][87] = -2,
- [0][1][2][1][RTW89_ETSI][87] = 127,
- [0][1][2][1][RTW89_KCC][87] = 20,
- [0][1][2][1][RTW89_FCC][89] = -2,
- [0][1][2][1][RTW89_ETSI][89] = 127,
- [0][1][2][1][RTW89_KCC][89] = 20,
- [0][1][2][1][RTW89_FCC][90] = -2,
- [0][1][2][1][RTW89_ETSI][90] = 127,
- [0][1][2][1][RTW89_KCC][90] = 20,
- [0][1][2][1][RTW89_FCC][92] = -2,
- [0][1][2][1][RTW89_ETSI][92] = 127,
- [0][1][2][1][RTW89_KCC][92] = 20,
- [0][1][2][1][RTW89_FCC][94] = -2,
- [0][1][2][1][RTW89_ETSI][94] = 127,
- [0][1][2][1][RTW89_KCC][94] = 20,
- [0][1][2][1][RTW89_FCC][96] = -2,
- [0][1][2][1][RTW89_ETSI][96] = 127,
- [0][1][2][1][RTW89_KCC][96] = 20,
- [0][1][2][1][RTW89_FCC][98] = -2,
- [0][1][2][1][RTW89_ETSI][98] = 127,
- [0][1][2][1][RTW89_KCC][98] = 20,
- [0][1][2][1][RTW89_FCC][100] = -2,
- [0][1][2][1][RTW89_ETSI][100] = 127,
- [0][1][2][1][RTW89_KCC][100] = 20,
- [0][1][2][1][RTW89_FCC][102] = -2,
- [0][1][2][1][RTW89_ETSI][102] = 127,
- [0][1][2][1][RTW89_KCC][102] = 20,
- [0][1][2][1][RTW89_FCC][104] = -2,
- [0][1][2][1][RTW89_ETSI][104] = 127,
- [0][1][2][1][RTW89_KCC][104] = 20,
- [0][1][2][1][RTW89_FCC][105] = -2,
- [0][1][2][1][RTW89_ETSI][105] = 127,
- [0][1][2][1][RTW89_KCC][105] = 20,
- [0][1][2][1][RTW89_FCC][107] = 0,
- [0][1][2][1][RTW89_ETSI][107] = 127,
- [0][1][2][1][RTW89_KCC][107] = 20,
- [0][1][2][1][RTW89_FCC][109] = 0,
- [0][1][2][1][RTW89_ETSI][109] = 127,
- [0][1][2][1][RTW89_KCC][109] = 20,
- [0][1][2][1][RTW89_FCC][111] = 127,
- [0][1][2][1][RTW89_ETSI][111] = 127,
- [0][1][2][1][RTW89_KCC][111] = 127,
- [0][1][2][1][RTW89_FCC][113] = 127,
- [0][1][2][1][RTW89_ETSI][113] = 127,
- [0][1][2][1][RTW89_KCC][113] = 127,
- [0][1][2][1][RTW89_FCC][115] = 127,
- [0][1][2][1][RTW89_ETSI][115] = 127,
- [0][1][2][1][RTW89_KCC][115] = 127,
- [0][1][2][1][RTW89_FCC][117] = 127,
- [0][1][2][1][RTW89_ETSI][117] = 127,
- [0][1][2][1][RTW89_KCC][117] = 127,
- [0][1][2][1][RTW89_FCC][119] = 127,
- [0][1][2][1][RTW89_ETSI][119] = 127,
- [0][1][2][1][RTW89_KCC][119] = 127,
- [1][0][2][0][RTW89_FCC][1] = 34,
- [1][0][2][0][RTW89_ETSI][1] = 66,
- [1][0][2][0][RTW89_KCC][1] = 40,
- [1][0][2][0][RTW89_FCC][5] = 34,
- [1][0][2][0][RTW89_ETSI][5] = 66,
- [1][0][2][0][RTW89_KCC][5] = 40,
- [1][0][2][0][RTW89_FCC][9] = 34,
- [1][0][2][0][RTW89_ETSI][9] = 66,
- [1][0][2][0][RTW89_KCC][9] = 40,
- [1][0][2][0][RTW89_FCC][13] = 34,
- [1][0][2][0][RTW89_ETSI][13] = 66,
- [1][0][2][0][RTW89_KCC][13] = 40,
- [1][0][2][0][RTW89_FCC][16] = 34,
- [1][0][2][0][RTW89_ETSI][16] = 66,
- [1][0][2][0][RTW89_KCC][16] = 40,
- [1][0][2][0][RTW89_FCC][20] = 34,
- [1][0][2][0][RTW89_ETSI][20] = 66,
- [1][0][2][0][RTW89_KCC][20] = 40,
- [1][0][2][0][RTW89_FCC][24] = 36,
- [1][0][2][0][RTW89_ETSI][24] = 66,
- [1][0][2][0][RTW89_KCC][24] = 40,
- [1][0][2][0][RTW89_FCC][28] = 34,
- [1][0][2][0][RTW89_ETSI][28] = 66,
- [1][0][2][0][RTW89_KCC][28] = 40,
- [1][0][2][0][RTW89_FCC][31] = 34,
- [1][0][2][0][RTW89_ETSI][31] = 66,
- [1][0][2][0][RTW89_KCC][31] = 40,
- [1][0][2][0][RTW89_FCC][35] = 34,
- [1][0][2][0][RTW89_ETSI][35] = 66,
- [1][0][2][0][RTW89_KCC][35] = 40,
- [1][0][2][0][RTW89_FCC][39] = 34,
- [1][0][2][0][RTW89_ETSI][39] = 66,
- [1][0][2][0][RTW89_KCC][39] = 40,
- [1][0][2][0][RTW89_FCC][43] = 34,
- [1][0][2][0][RTW89_ETSI][43] = 66,
- [1][0][2][0][RTW89_KCC][43] = 40,
- [1][0][2][0][RTW89_FCC][46] = 34,
- [1][0][2][0][RTW89_ETSI][46] = 127,
- [1][0][2][0][RTW89_KCC][46] = 40,
- [1][0][2][0][RTW89_FCC][50] = 34,
- [1][0][2][0][RTW89_ETSI][50] = 127,
- [1][0][2][0][RTW89_KCC][50] = 40,
- [1][0][2][0][RTW89_FCC][54] = 36,
- [1][0][2][0][RTW89_ETSI][54] = 127,
- [1][0][2][0][RTW89_KCC][54] = 40,
- [1][0][2][0][RTW89_FCC][58] = 36,
- [1][0][2][0][RTW89_ETSI][58] = 127,
- [1][0][2][0][RTW89_KCC][58] = 40,
- [1][0][2][0][RTW89_FCC][61] = 34,
- [1][0][2][0][RTW89_ETSI][61] = 127,
- [1][0][2][0][RTW89_KCC][61] = 40,
- [1][0][2][0][RTW89_FCC][65] = 34,
- [1][0][2][0][RTW89_ETSI][65] = 127,
- [1][0][2][0][RTW89_KCC][65] = 40,
- [1][0][2][0][RTW89_FCC][69] = 34,
- [1][0][2][0][RTW89_ETSI][69] = 127,
- [1][0][2][0][RTW89_KCC][69] = 40,
- [1][0][2][0][RTW89_FCC][73] = 34,
- [1][0][2][0][RTW89_ETSI][73] = 127,
- [1][0][2][0][RTW89_KCC][73] = 40,
- [1][0][2][0][RTW89_FCC][76] = 34,
- [1][0][2][0][RTW89_ETSI][76] = 127,
- [1][0][2][0][RTW89_KCC][76] = 40,
- [1][0][2][0][RTW89_FCC][80] = 34,
- [1][0][2][0][RTW89_ETSI][80] = 127,
- [1][0][2][0][RTW89_KCC][80] = 42,
- [1][0][2][0][RTW89_FCC][84] = 34,
- [1][0][2][0][RTW89_ETSI][84] = 127,
- [1][0][2][0][RTW89_KCC][84] = 42,
- [1][0][2][0][RTW89_FCC][88] = 34,
- [1][0][2][0][RTW89_ETSI][88] = 127,
- [1][0][2][0][RTW89_KCC][88] = 42,
- [1][0][2][0][RTW89_FCC][91] = 36,
- [1][0][2][0][RTW89_ETSI][91] = 127,
- [1][0][2][0][RTW89_KCC][91] = 42,
- [1][0][2][0][RTW89_FCC][95] = 34,
- [1][0][2][0][RTW89_ETSI][95] = 127,
- [1][0][2][0][RTW89_KCC][95] = 42,
- [1][0][2][0][RTW89_FCC][99] = 34,
- [1][0][2][0][RTW89_ETSI][99] = 127,
- [1][0][2][0][RTW89_KCC][99] = 42,
- [1][0][2][0][RTW89_FCC][103] = 34,
- [1][0][2][0][RTW89_ETSI][103] = 127,
- [1][0][2][0][RTW89_KCC][103] = 42,
- [1][0][2][0][RTW89_FCC][106] = 36,
- [1][0][2][0][RTW89_ETSI][106] = 127,
- [1][0][2][0][RTW89_KCC][106] = 42,
- [1][0][2][0][RTW89_FCC][110] = 127,
- [1][0][2][0][RTW89_ETSI][110] = 127,
- [1][0][2][0][RTW89_KCC][110] = 127,
- [1][0][2][0][RTW89_FCC][114] = 127,
- [1][0][2][0][RTW89_ETSI][114] = 127,
- [1][0][2][0][RTW89_KCC][114] = 127,
- [1][0][2][0][RTW89_FCC][118] = 127,
- [1][0][2][0][RTW89_ETSI][118] = 127,
- [1][0][2][0][RTW89_KCC][118] = 127,
- [1][1][2][0][RTW89_FCC][1] = 10,
- [1][1][2][0][RTW89_ETSI][1] = 54,
- [1][1][2][0][RTW89_KCC][1] = 28,
- [1][1][2][0][RTW89_FCC][5] = 10,
- [1][1][2][0][RTW89_ETSI][5] = 54,
- [1][1][2][0][RTW89_KCC][5] = 28,
- [1][1][2][0][RTW89_FCC][9] = 10,
- [1][1][2][0][RTW89_ETSI][9] = 54,
- [1][1][2][0][RTW89_KCC][9] = 28,
- [1][1][2][0][RTW89_FCC][13] = 10,
- [1][1][2][0][RTW89_ETSI][13] = 54,
- [1][1][2][0][RTW89_KCC][13] = 28,
- [1][1][2][0][RTW89_FCC][16] = 10,
- [1][1][2][0][RTW89_ETSI][16] = 54,
- [1][1][2][0][RTW89_KCC][16] = 28,
- [1][1][2][0][RTW89_FCC][20] = 10,
- [1][1][2][0][RTW89_ETSI][20] = 54,
- [1][1][2][0][RTW89_KCC][20] = 28,
- [1][1][2][0][RTW89_FCC][24] = 10,
- [1][1][2][0][RTW89_ETSI][24] = 54,
- [1][1][2][0][RTW89_KCC][24] = 28,
- [1][1][2][0][RTW89_FCC][28] = 10,
- [1][1][2][0][RTW89_ETSI][28] = 54,
- [1][1][2][0][RTW89_KCC][28] = 28,
- [1][1][2][0][RTW89_FCC][31] = 10,
- [1][1][2][0][RTW89_ETSI][31] = 54,
- [1][1][2][0][RTW89_KCC][31] = 28,
- [1][1][2][0][RTW89_FCC][35] = 10,
- [1][1][2][0][RTW89_ETSI][35] = 54,
- [1][1][2][0][RTW89_KCC][35] = 28,
- [1][1][2][0][RTW89_FCC][39] = 10,
- [1][1][2][0][RTW89_ETSI][39] = 54,
- [1][1][2][0][RTW89_KCC][39] = 28,
- [1][1][2][0][RTW89_FCC][43] = 10,
- [1][1][2][0][RTW89_ETSI][43] = 54,
- [1][1][2][0][RTW89_KCC][43] = 28,
- [1][1][2][0][RTW89_FCC][46] = 12,
- [1][1][2][0][RTW89_ETSI][46] = 127,
- [1][1][2][0][RTW89_KCC][46] = 28,
- [1][1][2][0][RTW89_FCC][50] = 12,
- [1][1][2][0][RTW89_ETSI][50] = 127,
- [1][1][2][0][RTW89_KCC][50] = 28,
- [1][1][2][0][RTW89_FCC][54] = 10,
- [1][1][2][0][RTW89_ETSI][54] = 127,
- [1][1][2][0][RTW89_KCC][54] = 28,
- [1][1][2][0][RTW89_FCC][58] = 10,
- [1][1][2][0][RTW89_ETSI][58] = 127,
- [1][1][2][0][RTW89_KCC][58] = 28,
- [1][1][2][0][RTW89_FCC][61] = 10,
- [1][1][2][0][RTW89_ETSI][61] = 127,
- [1][1][2][0][RTW89_KCC][61] = 28,
- [1][1][2][0][RTW89_FCC][65] = 10,
- [1][1][2][0][RTW89_ETSI][65] = 127,
- [1][1][2][0][RTW89_KCC][65] = 28,
- [1][1][2][0][RTW89_FCC][69] = 10,
- [1][1][2][0][RTW89_ETSI][69] = 127,
- [1][1][2][0][RTW89_KCC][69] = 28,
- [1][1][2][0][RTW89_FCC][73] = 10,
- [1][1][2][0][RTW89_ETSI][73] = 127,
- [1][1][2][0][RTW89_KCC][73] = 28,
- [1][1][2][0][RTW89_FCC][76] = 10,
- [1][1][2][0][RTW89_ETSI][76] = 127,
- [1][1][2][0][RTW89_KCC][76] = 28,
- [1][1][2][0][RTW89_FCC][80] = 10,
- [1][1][2][0][RTW89_ETSI][80] = 127,
- [1][1][2][0][RTW89_KCC][80] = 32,
- [1][1][2][0][RTW89_FCC][84] = 10,
- [1][1][2][0][RTW89_ETSI][84] = 127,
- [1][1][2][0][RTW89_KCC][84] = 32,
- [1][1][2][0][RTW89_FCC][88] = 10,
- [1][1][2][0][RTW89_ETSI][88] = 127,
- [1][1][2][0][RTW89_KCC][88] = 32,
- [1][1][2][0][RTW89_FCC][91] = 12,
- [1][1][2][0][RTW89_ETSI][91] = 127,
- [1][1][2][0][RTW89_KCC][91] = 32,
- [1][1][2][0][RTW89_FCC][95] = 10,
- [1][1][2][0][RTW89_ETSI][95] = 127,
- [1][1][2][0][RTW89_KCC][95] = 32,
- [1][1][2][0][RTW89_FCC][99] = 10,
- [1][1][2][0][RTW89_ETSI][99] = 127,
- [1][1][2][0][RTW89_KCC][99] = 32,
- [1][1][2][0][RTW89_FCC][103] = 10,
- [1][1][2][0][RTW89_ETSI][103] = 127,
- [1][1][2][0][RTW89_KCC][103] = 32,
- [1][1][2][0][RTW89_FCC][106] = 12,
- [1][1][2][0][RTW89_ETSI][106] = 127,
- [1][1][2][0][RTW89_KCC][106] = 32,
- [1][1][2][0][RTW89_FCC][110] = 127,
- [1][1][2][0][RTW89_ETSI][110] = 127,
- [1][1][2][0][RTW89_KCC][110] = 127,
- [1][1][2][0][RTW89_FCC][114] = 127,
- [1][1][2][0][RTW89_ETSI][114] = 127,
- [1][1][2][0][RTW89_KCC][114] = 127,
- [1][1][2][0][RTW89_FCC][118] = 127,
- [1][1][2][0][RTW89_ETSI][118] = 127,
- [1][1][2][0][RTW89_KCC][118] = 127,
- [1][1][2][1][RTW89_FCC][1] = 10,
- [1][1][2][1][RTW89_ETSI][1] = 42,
- [1][1][2][1][RTW89_KCC][1] = 28,
- [1][1][2][1][RTW89_FCC][5] = 10,
- [1][1][2][1][RTW89_ETSI][5] = 42,
- [1][1][2][1][RTW89_KCC][5] = 28,
- [1][1][2][1][RTW89_FCC][9] = 10,
- [1][1][2][1][RTW89_ETSI][9] = 42,
- [1][1][2][1][RTW89_KCC][9] = 28,
- [1][1][2][1][RTW89_FCC][13] = 10,
- [1][1][2][1][RTW89_ETSI][13] = 42,
- [1][1][2][1][RTW89_KCC][13] = 28,
- [1][1][2][1][RTW89_FCC][16] = 10,
- [1][1][2][1][RTW89_ETSI][16] = 42,
- [1][1][2][1][RTW89_KCC][16] = 28,
- [1][1][2][1][RTW89_FCC][20] = 10,
- [1][1][2][1][RTW89_ETSI][20] = 42,
- [1][1][2][1][RTW89_KCC][20] = 28,
- [1][1][2][1][RTW89_FCC][24] = 10,
- [1][1][2][1][RTW89_ETSI][24] = 42,
- [1][1][2][1][RTW89_KCC][24] = 28,
- [1][1][2][1][RTW89_FCC][28] = 10,
- [1][1][2][1][RTW89_ETSI][28] = 42,
- [1][1][2][1][RTW89_KCC][28] = 28,
- [1][1][2][1][RTW89_FCC][31] = 10,
- [1][1][2][1][RTW89_ETSI][31] = 42,
- [1][1][2][1][RTW89_KCC][31] = 28,
- [1][1][2][1][RTW89_FCC][35] = 10,
- [1][1][2][1][RTW89_ETSI][35] = 42,
- [1][1][2][1][RTW89_KCC][35] = 28,
- [1][1][2][1][RTW89_FCC][39] = 10,
- [1][1][2][1][RTW89_ETSI][39] = 42,
- [1][1][2][1][RTW89_KCC][39] = 28,
- [1][1][2][1][RTW89_FCC][43] = 10,
- [1][1][2][1][RTW89_ETSI][43] = 42,
- [1][1][2][1][RTW89_KCC][43] = 28,
- [1][1][2][1][RTW89_FCC][46] = 12,
- [1][1][2][1][RTW89_ETSI][46] = 127,
- [1][1][2][1][RTW89_KCC][46] = 28,
- [1][1][2][1][RTW89_FCC][50] = 12,
- [1][1][2][1][RTW89_ETSI][50] = 127,
- [1][1][2][1][RTW89_KCC][50] = 28,
- [1][1][2][1][RTW89_FCC][54] = 10,
- [1][1][2][1][RTW89_ETSI][54] = 127,
- [1][1][2][1][RTW89_KCC][54] = 28,
- [1][1][2][1][RTW89_FCC][58] = 10,
- [1][1][2][1][RTW89_ETSI][58] = 127,
- [1][1][2][1][RTW89_KCC][58] = 28,
- [1][1][2][1][RTW89_FCC][61] = 10,
- [1][1][2][1][RTW89_ETSI][61] = 127,
- [1][1][2][1][RTW89_KCC][61] = 28,
- [1][1][2][1][RTW89_FCC][65] = 10,
- [1][1][2][1][RTW89_ETSI][65] = 127,
- [1][1][2][1][RTW89_KCC][65] = 28,
- [1][1][2][1][RTW89_FCC][69] = 10,
- [1][1][2][1][RTW89_ETSI][69] = 127,
- [1][1][2][1][RTW89_KCC][69] = 28,
- [1][1][2][1][RTW89_FCC][73] = 10,
- [1][1][2][1][RTW89_ETSI][73] = 127,
- [1][1][2][1][RTW89_KCC][73] = 28,
- [1][1][2][1][RTW89_FCC][76] = 10,
- [1][1][2][1][RTW89_ETSI][76] = 127,
- [1][1][2][1][RTW89_KCC][76] = 28,
- [1][1][2][1][RTW89_FCC][80] = 10,
- [1][1][2][1][RTW89_ETSI][80] = 127,
- [1][1][2][1][RTW89_KCC][80] = 32,
- [1][1][2][1][RTW89_FCC][84] = 10,
- [1][1][2][1][RTW89_ETSI][84] = 127,
- [1][1][2][1][RTW89_KCC][84] = 32,
- [1][1][2][1][RTW89_FCC][88] = 10,
- [1][1][2][1][RTW89_ETSI][88] = 127,
- [1][1][2][1][RTW89_KCC][88] = 32,
- [1][1][2][1][RTW89_FCC][91] = 12,
- [1][1][2][1][RTW89_ETSI][91] = 127,
- [1][1][2][1][RTW89_KCC][91] = 32,
- [1][1][2][1][RTW89_FCC][95] = 10,
- [1][1][2][1][RTW89_ETSI][95] = 127,
- [1][1][2][1][RTW89_KCC][95] = 32,
- [1][1][2][1][RTW89_FCC][99] = 10,
- [1][1][2][1][RTW89_ETSI][99] = 127,
- [1][1][2][1][RTW89_KCC][99] = 32,
- [1][1][2][1][RTW89_FCC][103] = 10,
- [1][1][2][1][RTW89_ETSI][103] = 127,
- [1][1][2][1][RTW89_KCC][103] = 32,
- [1][1][2][1][RTW89_FCC][106] = 12,
- [1][1][2][1][RTW89_ETSI][106] = 127,
- [1][1][2][1][RTW89_KCC][106] = 32,
- [1][1][2][1][RTW89_FCC][110] = 127,
- [1][1][2][1][RTW89_ETSI][110] = 127,
- [1][1][2][1][RTW89_KCC][110] = 127,
- [1][1][2][1][RTW89_FCC][114] = 127,
- [1][1][2][1][RTW89_ETSI][114] = 127,
- [1][1][2][1][RTW89_KCC][114] = 127,
- [1][1][2][1][RTW89_FCC][118] = 127,
- [1][1][2][1][RTW89_ETSI][118] = 127,
- [1][1][2][1][RTW89_KCC][118] = 127,
- [2][0][2][0][RTW89_FCC][3] = 46,
- [2][0][2][0][RTW89_ETSI][3] = 48,
- [2][0][2][0][RTW89_KCC][3] = 50,
- [2][0][2][0][RTW89_FCC][11] = 46,
- [2][0][2][0][RTW89_ETSI][11] = 48,
- [2][0][2][0][RTW89_KCC][11] = 50,
- [2][0][2][0][RTW89_FCC][18] = 46,
- [2][0][2][0][RTW89_ETSI][18] = 48,
- [2][0][2][0][RTW89_KCC][18] = 50,
- [2][0][2][0][RTW89_FCC][26] = 46,
- [2][0][2][0][RTW89_ETSI][26] = 48,
- [2][0][2][0][RTW89_KCC][26] = 50,
- [2][0][2][0][RTW89_FCC][33] = 46,
- [2][0][2][0][RTW89_ETSI][33] = 48,
- [2][0][2][0][RTW89_KCC][33] = 50,
- [2][0][2][0][RTW89_FCC][41] = 46,
- [2][0][2][0][RTW89_ETSI][41] = 48,
- [2][0][2][0][RTW89_KCC][41] = 50,
- [2][0][2][0][RTW89_FCC][48] = 46,
- [2][0][2][0][RTW89_ETSI][48] = 127,
- [2][0][2][0][RTW89_KCC][48] = 48,
- [2][0][2][0][RTW89_FCC][56] = 46,
- [2][0][2][0][RTW89_ETSI][56] = 127,
- [2][0][2][0][RTW89_KCC][56] = 48,
- [2][0][2][0][RTW89_FCC][63] = 46,
- [2][0][2][0][RTW89_ETSI][63] = 127,
- [2][0][2][0][RTW89_KCC][63] = 48,
- [2][0][2][0][RTW89_FCC][71] = 46,
- [2][0][2][0][RTW89_ETSI][71] = 127,
- [2][0][2][0][RTW89_KCC][71] = 48,
- [2][0][2][0][RTW89_FCC][78] = 46,
- [2][0][2][0][RTW89_ETSI][78] = 127,
- [2][0][2][0][RTW89_KCC][78] = 52,
- [2][0][2][0][RTW89_FCC][86] = 46,
- [2][0][2][0][RTW89_ETSI][86] = 127,
- [2][0][2][0][RTW89_KCC][86] = 52,
- [2][0][2][0][RTW89_FCC][93] = 46,
- [2][0][2][0][RTW89_ETSI][93] = 127,
- [2][0][2][0][RTW89_KCC][93] = 50,
- [2][0][2][0][RTW89_FCC][101] = 44,
- [2][0][2][0][RTW89_ETSI][101] = 127,
- [2][0][2][0][RTW89_KCC][101] = 50,
- [2][0][2][0][RTW89_FCC][108] = 127,
- [2][0][2][0][RTW89_ETSI][108] = 127,
- [2][0][2][0][RTW89_KCC][108] = 127,
- [2][0][2][0][RTW89_FCC][116] = 127,
- [2][0][2][0][RTW89_ETSI][116] = 127,
- [2][0][2][0][RTW89_KCC][116] = 127,
- [2][1][2][0][RTW89_FCC][3] = 22,
- [2][1][2][0][RTW89_ETSI][3] = 48,
- [2][1][2][0][RTW89_KCC][3] = 38,
- [2][1][2][0][RTW89_FCC][11] = 20,
- [2][1][2][0][RTW89_ETSI][11] = 48,
- [2][1][2][0][RTW89_KCC][11] = 38,
- [2][1][2][0][RTW89_FCC][18] = 20,
- [2][1][2][0][RTW89_ETSI][18] = 48,
- [2][1][2][0][RTW89_KCC][18] = 38,
- [2][1][2][0][RTW89_FCC][26] = 20,
- [2][1][2][0][RTW89_ETSI][26] = 48,
- [2][1][2][0][RTW89_KCC][26] = 38,
- [2][1][2][0][RTW89_FCC][33] = 20,
- [2][1][2][0][RTW89_ETSI][33] = 48,
- [2][1][2][0][RTW89_KCC][33] = 38,
- [2][1][2][0][RTW89_FCC][41] = 22,
- [2][1][2][0][RTW89_ETSI][41] = 48,
- [2][1][2][0][RTW89_KCC][41] = 38,
- [2][1][2][0][RTW89_FCC][48] = 22,
- [2][1][2][0][RTW89_ETSI][48] = 127,
- [2][1][2][0][RTW89_KCC][48] = 38,
- [2][1][2][0][RTW89_FCC][56] = 20,
- [2][1][2][0][RTW89_ETSI][56] = 127,
- [2][1][2][0][RTW89_KCC][56] = 38,
- [2][1][2][0][RTW89_FCC][63] = 22,
- [2][1][2][0][RTW89_ETSI][63] = 127,
- [2][1][2][0][RTW89_KCC][63] = 38,
- [2][1][2][0][RTW89_FCC][71] = 20,
- [2][1][2][0][RTW89_ETSI][71] = 127,
- [2][1][2][0][RTW89_KCC][71] = 38,
- [2][1][2][0][RTW89_FCC][78] = 20,
- [2][1][2][0][RTW89_ETSI][78] = 127,
- [2][1][2][0][RTW89_KCC][78] = 38,
- [2][1][2][0][RTW89_FCC][86] = 20,
- [2][1][2][0][RTW89_ETSI][86] = 127,
- [2][1][2][0][RTW89_KCC][86] = 38,
- [2][1][2][0][RTW89_FCC][93] = 22,
- [2][1][2][0][RTW89_ETSI][93] = 127,
- [2][1][2][0][RTW89_KCC][93] = 38,
- [2][1][2][0][RTW89_FCC][101] = 22,
- [2][1][2][0][RTW89_ETSI][101] = 127,
- [2][1][2][0][RTW89_KCC][101] = 38,
- [2][1][2][0][RTW89_FCC][108] = 127,
- [2][1][2][0][RTW89_ETSI][108] = 127,
- [2][1][2][0][RTW89_KCC][108] = 127,
- [2][1][2][0][RTW89_FCC][116] = 127,
- [2][1][2][0][RTW89_ETSI][116] = 127,
- [2][1][2][0][RTW89_KCC][116] = 127,
- [2][1][2][1][RTW89_FCC][3] = 22,
- [2][1][2][1][RTW89_ETSI][3] = 42,
- [2][1][2][1][RTW89_KCC][3] = 38,
- [2][1][2][1][RTW89_FCC][11] = 20,
- [2][1][2][1][RTW89_ETSI][11] = 42,
- [2][1][2][1][RTW89_KCC][11] = 38,
- [2][1][2][1][RTW89_FCC][18] = 20,
- [2][1][2][1][RTW89_ETSI][18] = 42,
- [2][1][2][1][RTW89_KCC][18] = 38,
- [2][1][2][1][RTW89_FCC][26] = 20,
- [2][1][2][1][RTW89_ETSI][26] = 42,
- [2][1][2][1][RTW89_KCC][26] = 38,
- [2][1][2][1][RTW89_FCC][33] = 20,
- [2][1][2][1][RTW89_ETSI][33] = 42,
- [2][1][2][1][RTW89_KCC][33] = 38,
- [2][1][2][1][RTW89_FCC][41] = 22,
- [2][1][2][1][RTW89_ETSI][41] = 42,
- [2][1][2][1][RTW89_KCC][41] = 38,
- [2][1][2][1][RTW89_FCC][48] = 22,
- [2][1][2][1][RTW89_ETSI][48] = 127,
- [2][1][2][1][RTW89_KCC][48] = 38,
- [2][1][2][1][RTW89_FCC][56] = 20,
- [2][1][2][1][RTW89_ETSI][56] = 127,
- [2][1][2][1][RTW89_KCC][56] = 38,
- [2][1][2][1][RTW89_FCC][63] = 22,
- [2][1][2][1][RTW89_ETSI][63] = 127,
- [2][1][2][1][RTW89_KCC][63] = 38,
- [2][1][2][1][RTW89_FCC][71] = 20,
- [2][1][2][1][RTW89_ETSI][71] = 127,
- [2][1][2][1][RTW89_KCC][71] = 38,
- [2][1][2][1][RTW89_FCC][78] = 20,
- [2][1][2][1][RTW89_ETSI][78] = 127,
- [2][1][2][1][RTW89_KCC][78] = 38,
- [2][1][2][1][RTW89_FCC][86] = 20,
- [2][1][2][1][RTW89_ETSI][86] = 127,
- [2][1][2][1][RTW89_KCC][86] = 38,
- [2][1][2][1][RTW89_FCC][93] = 22,
- [2][1][2][1][RTW89_ETSI][93] = 127,
- [2][1][2][1][RTW89_KCC][93] = 38,
- [2][1][2][1][RTW89_FCC][101] = 22,
- [2][1][2][1][RTW89_ETSI][101] = 127,
- [2][1][2][1][RTW89_KCC][101] = 38,
- [2][1][2][1][RTW89_FCC][108] = 127,
- [2][1][2][1][RTW89_ETSI][108] = 127,
- [2][1][2][1][RTW89_KCC][108] = 127,
- [2][1][2][1][RTW89_FCC][116] = 127,
- [2][1][2][1][RTW89_ETSI][116] = 127,
- [2][1][2][1][RTW89_KCC][116] = 127,
- [3][0][2][0][RTW89_FCC][7] = 52,
- [3][0][2][0][RTW89_ETSI][7] = 38,
- [3][0][2][0][RTW89_KCC][7] = 42,
- [3][0][2][0][RTW89_FCC][22] = 52,
- [3][0][2][0][RTW89_ETSI][22] = 38,
- [3][0][2][0][RTW89_KCC][22] = 42,
- [3][0][2][0][RTW89_FCC][37] = 52,
- [3][0][2][0][RTW89_ETSI][37] = 38,
- [3][0][2][0][RTW89_KCC][37] = 42,
- [3][0][2][0][RTW89_FCC][52] = 54,
- [3][0][2][0][RTW89_ETSI][52] = 127,
- [3][0][2][0][RTW89_KCC][52] = 56,
- [3][0][2][0][RTW89_FCC][67] = 54,
- [3][0][2][0][RTW89_ETSI][67] = 127,
- [3][0][2][0][RTW89_KCC][67] = 54,
- [3][0][2][0][RTW89_FCC][82] = 54,
- [3][0][2][0][RTW89_ETSI][82] = 127,
- [3][0][2][0][RTW89_KCC][82] = 26,
- [3][0][2][0][RTW89_FCC][97] = 40,
- [3][0][2][0][RTW89_ETSI][97] = 127,
- [3][0][2][0][RTW89_KCC][97] = 26,
- [3][0][2][0][RTW89_FCC][112] = 127,
- [3][0][2][0][RTW89_ETSI][112] = 127,
- [3][0][2][0][RTW89_KCC][112] = 127,
- [3][1][2][0][RTW89_FCC][7] = 32,
- [3][1][2][0][RTW89_ETSI][7] = 38,
- [3][1][2][0][RTW89_KCC][7] = 40,
- [3][1][2][0][RTW89_FCC][22] = 30,
- [3][1][2][0][RTW89_ETSI][22] = 38,
- [3][1][2][0][RTW89_KCC][22] = 40,
- [3][1][2][0][RTW89_FCC][37] = 30,
- [3][1][2][0][RTW89_ETSI][37] = 38,
- [3][1][2][0][RTW89_KCC][37] = 40,
- [3][1][2][0][RTW89_FCC][52] = 30,
- [3][1][2][0][RTW89_ETSI][52] = 127,
- [3][1][2][0][RTW89_KCC][52] = 48,
- [3][1][2][0][RTW89_FCC][67] = 32,
- [3][1][2][0][RTW89_ETSI][67] = 127,
- [3][1][2][0][RTW89_KCC][67] = 48,
- [3][1][2][0][RTW89_FCC][82] = 32,
- [3][1][2][0][RTW89_ETSI][82] = 127,
- [3][1][2][0][RTW89_KCC][82] = 24,
- [3][1][2][0][RTW89_FCC][97] = 14,
- [3][1][2][0][RTW89_ETSI][97] = 127,
- [3][1][2][0][RTW89_KCC][97] = 24,
- [3][1][2][0][RTW89_FCC][112] = 127,
- [3][1][2][0][RTW89_ETSI][112] = 127,
- [3][1][2][0][RTW89_KCC][112] = 127,
- [3][1][2][1][RTW89_FCC][7] = 32,
- [3][1][2][1][RTW89_ETSI][7] = 38,
- [3][1][2][1][RTW89_KCC][7] = 40,
- [3][1][2][1][RTW89_FCC][22] = 30,
- [3][1][2][1][RTW89_ETSI][22] = 38,
- [3][1][2][1][RTW89_KCC][22] = 40,
- [3][1][2][1][RTW89_FCC][37] = 30,
- [3][1][2][1][RTW89_ETSI][37] = 38,
- [3][1][2][1][RTW89_KCC][37] = 40,
- [3][1][2][1][RTW89_FCC][52] = 30,
- [3][1][2][1][RTW89_ETSI][52] = 127,
- [3][1][2][1][RTW89_KCC][52] = 48,
- [3][1][2][1][RTW89_FCC][67] = 32,
- [3][1][2][1][RTW89_ETSI][67] = 127,
- [3][1][2][1][RTW89_KCC][67] = 48,
- [3][1][2][1][RTW89_FCC][82] = 32,
- [3][1][2][1][RTW89_ETSI][82] = 127,
- [3][1][2][1][RTW89_KCC][82] = 24,
- [3][1][2][1][RTW89_FCC][97] = 14,
- [3][1][2][1][RTW89_ETSI][97] = 127,
- [3][1][2][1][RTW89_KCC][97] = 24,
- [3][1][2][1][RTW89_FCC][112] = 127,
- [3][1][2][1][RTW89_ETSI][112] = 127,
- [3][1][2][1][RTW89_KCC][112] = 127,
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM] = {
+ [0][0][1][0][RTW89_WW][0][0] = 24,
+ [0][0][1][0][RTW89_WW][1][0] = 24,
+ [0][0][1][0][RTW89_WW][2][0] = 56,
+ [0][0][1][0][RTW89_WW][0][2] = 22,
+ [0][0][1][0][RTW89_WW][1][2] = 22,
+ [0][0][1][0][RTW89_WW][2][2] = 56,
+ [0][0][1][0][RTW89_WW][0][4] = 22,
+ [0][0][1][0][RTW89_WW][1][4] = 22,
+ [0][0][1][0][RTW89_WW][2][4] = 56,
+ [0][0][1][0][RTW89_WW][0][6] = 22,
+ [0][0][1][0][RTW89_WW][1][6] = 22,
+ [0][0][1][0][RTW89_WW][2][6] = 56,
+ [0][0][1][0][RTW89_WW][0][8] = 22,
+ [0][0][1][0][RTW89_WW][1][8] = 22,
+ [0][0][1][0][RTW89_WW][2][8] = 56,
+ [0][0][1][0][RTW89_WW][0][10] = 22,
+ [0][0][1][0][RTW89_WW][1][10] = 22,
+ [0][0][1][0][RTW89_WW][2][10] = 56,
+ [0][0][1][0][RTW89_WW][0][12] = 22,
+ [0][0][1][0][RTW89_WW][1][12] = 22,
+ [0][0][1][0][RTW89_WW][2][12] = 56,
+ [0][0][1][0][RTW89_WW][0][14] = 22,
+ [0][0][1][0][RTW89_WW][1][14] = 22,
+ [0][0][1][0][RTW89_WW][2][14] = 56,
+ [0][0][1][0][RTW89_WW][0][15] = 22,
+ [0][0][1][0][RTW89_WW][1][15] = 22,
+ [0][0][1][0][RTW89_WW][2][15] = 56,
+ [0][0][1][0][RTW89_WW][0][17] = 22,
+ [0][0][1][0][RTW89_WW][1][17] = 22,
+ [0][0][1][0][RTW89_WW][2][17] = 56,
+ [0][0][1][0][RTW89_WW][0][19] = 22,
+ [0][0][1][0][RTW89_WW][1][19] = 22,
+ [0][0][1][0][RTW89_WW][2][19] = 56,
+ [0][0][1][0][RTW89_WW][0][21] = 22,
+ [0][0][1][0][RTW89_WW][1][21] = 22,
+ [0][0][1][0][RTW89_WW][2][21] = 56,
+ [0][0][1][0][RTW89_WW][0][23] = 22,
+ [0][0][1][0][RTW89_WW][1][23] = 22,
+ [0][0][1][0][RTW89_WW][2][23] = 70,
+ [0][0][1][0][RTW89_WW][0][25] = 22,
+ [0][0][1][0][RTW89_WW][1][25] = 22,
+ [0][0][1][0][RTW89_WW][2][25] = 70,
+ [0][0][1][0][RTW89_WW][0][27] = 22,
+ [0][0][1][0][RTW89_WW][1][27] = 22,
+ [0][0][1][0][RTW89_WW][2][27] = 70,
+ [0][0][1][0][RTW89_WW][0][29] = 22,
+ [0][0][1][0][RTW89_WW][1][29] = 22,
+ [0][0][1][0][RTW89_WW][2][29] = 70,
+ [0][0][1][0][RTW89_WW][0][30] = 22,
+ [0][0][1][0][RTW89_WW][1][30] = 22,
+ [0][0][1][0][RTW89_WW][2][30] = 70,
+ [0][0][1][0][RTW89_WW][0][32] = 22,
+ [0][0][1][0][RTW89_WW][1][32] = 22,
+ [0][0][1][0][RTW89_WW][2][32] = 70,
+ [0][0][1][0][RTW89_WW][0][34] = 22,
+ [0][0][1][0][RTW89_WW][1][34] = 22,
+ [0][0][1][0][RTW89_WW][2][34] = 70,
+ [0][0][1][0][RTW89_WW][0][36] = 22,
+ [0][0][1][0][RTW89_WW][1][36] = 22,
+ [0][0][1][0][RTW89_WW][2][36] = 70,
+ [0][0][1][0][RTW89_WW][0][38] = 22,
+ [0][0][1][0][RTW89_WW][1][38] = 22,
+ [0][0][1][0][RTW89_WW][2][38] = 70,
+ [0][0][1][0][RTW89_WW][0][40] = 22,
+ [0][0][1][0][RTW89_WW][1][40] = 22,
+ [0][0][1][0][RTW89_WW][2][40] = 70,
+ [0][0][1][0][RTW89_WW][0][42] = 22,
+ [0][0][1][0][RTW89_WW][1][42] = 22,
+ [0][0][1][0][RTW89_WW][2][42] = 70,
+ [0][0][1][0][RTW89_WW][0][44] = 22,
+ [0][0][1][0][RTW89_WW][1][44] = 22,
+ [0][0][1][0][RTW89_WW][2][44] = 70,
+ [0][0][1][0][RTW89_WW][0][45] = 22,
+ [0][0][1][0][RTW89_WW][1][45] = 22,
+ [0][0][1][0][RTW89_WW][2][45] = 0,
+ [0][0][1][0][RTW89_WW][0][47] = 22,
+ [0][0][1][0][RTW89_WW][1][47] = 22,
+ [0][0][1][0][RTW89_WW][2][47] = 0,
+ [0][0][1][0][RTW89_WW][0][49] = 24,
+ [0][0][1][0][RTW89_WW][1][49] = 24,
+ [0][0][1][0][RTW89_WW][2][49] = 0,
+ [0][0][1][0][RTW89_WW][0][51] = 22,
+ [0][0][1][0][RTW89_WW][1][51] = 22,
+ [0][0][1][0][RTW89_WW][2][51] = 0,
+ [0][0][1][0][RTW89_WW][0][53] = 22,
+ [0][0][1][0][RTW89_WW][1][53] = 22,
+ [0][0][1][0][RTW89_WW][2][53] = 0,
+ [0][0][1][0][RTW89_WW][0][55] = 22,
+ [0][0][1][0][RTW89_WW][1][55] = 22,
+ [0][0][1][0][RTW89_WW][2][55] = 68,
+ [0][0][1][0][RTW89_WW][0][57] = 22,
+ [0][0][1][0][RTW89_WW][1][57] = 22,
+ [0][0][1][0][RTW89_WW][2][57] = 68,
+ [0][0][1][0][RTW89_WW][0][59] = 22,
+ [0][0][1][0][RTW89_WW][1][59] = 22,
+ [0][0][1][0][RTW89_WW][2][59] = 68,
+ [0][0][1][0][RTW89_WW][0][60] = 22,
+ [0][0][1][0][RTW89_WW][1][60] = 22,
+ [0][0][1][0][RTW89_WW][2][60] = 68,
+ [0][0][1][0][RTW89_WW][0][62] = 22,
+ [0][0][1][0][RTW89_WW][1][62] = 22,
+ [0][0][1][0][RTW89_WW][2][62] = 68,
+ [0][0][1][0][RTW89_WW][0][64] = 22,
+ [0][0][1][0][RTW89_WW][1][64] = 22,
+ [0][0][1][0][RTW89_WW][2][64] = 68,
+ [0][0][1][0][RTW89_WW][0][66] = 22,
+ [0][0][1][0][RTW89_WW][1][66] = 22,
+ [0][0][1][0][RTW89_WW][2][66] = 68,
+ [0][0][1][0][RTW89_WW][0][68] = 22,
+ [0][0][1][0][RTW89_WW][1][68] = 22,
+ [0][0][1][0][RTW89_WW][2][68] = 68,
+ [0][0][1][0][RTW89_WW][0][70] = 24,
+ [0][0][1][0][RTW89_WW][1][70] = 24,
+ [0][0][1][0][RTW89_WW][2][70] = 68,
+ [0][0][1][0][RTW89_WW][0][72] = 22,
+ [0][0][1][0][RTW89_WW][1][72] = 22,
+ [0][0][1][0][RTW89_WW][2][72] = 68,
+ [0][0][1][0][RTW89_WW][0][74] = 22,
+ [0][0][1][0][RTW89_WW][1][74] = 22,
+ [0][0][1][0][RTW89_WW][2][74] = 68,
+ [0][0][1][0][RTW89_WW][0][75] = 22,
+ [0][0][1][0][RTW89_WW][1][75] = 22,
+ [0][0][1][0][RTW89_WW][2][75] = 68,
+ [0][0][1][0][RTW89_WW][0][77] = 22,
+ [0][0][1][0][RTW89_WW][1][77] = 22,
+ [0][0][1][0][RTW89_WW][2][77] = 68,
+ [0][0][1][0][RTW89_WW][0][79] = 22,
+ [0][0][1][0][RTW89_WW][1][79] = 22,
+ [0][0][1][0][RTW89_WW][2][79] = 68,
+ [0][0][1][0][RTW89_WW][0][81] = 22,
+ [0][0][1][0][RTW89_WW][1][81] = 22,
+ [0][0][1][0][RTW89_WW][2][81] = 68,
+ [0][0][1][0][RTW89_WW][0][83] = 22,
+ [0][0][1][0][RTW89_WW][1][83] = 22,
+ [0][0][1][0][RTW89_WW][2][83] = 68,
+ [0][0][1][0][RTW89_WW][0][85] = 22,
+ [0][0][1][0][RTW89_WW][1][85] = 22,
+ [0][0][1][0][RTW89_WW][2][85] = 68,
+ [0][0][1][0][RTW89_WW][0][87] = 22,
+ [0][0][1][0][RTW89_WW][1][87] = 22,
+ [0][0][1][0][RTW89_WW][2][87] = 0,
+ [0][0][1][0][RTW89_WW][0][89] = 22,
+ [0][0][1][0][RTW89_WW][1][89] = 22,
+ [0][0][1][0][RTW89_WW][2][89] = 0,
+ [0][0][1][0][RTW89_WW][0][90] = 22,
+ [0][0][1][0][RTW89_WW][1][90] = 22,
+ [0][0][1][0][RTW89_WW][2][90] = 0,
+ [0][0][1][0][RTW89_WW][0][92] = 22,
+ [0][0][1][0][RTW89_WW][1][92] = 22,
+ [0][0][1][0][RTW89_WW][2][92] = 0,
+ [0][0][1][0][RTW89_WW][0][94] = 22,
+ [0][0][1][0][RTW89_WW][1][94] = 22,
+ [0][0][1][0][RTW89_WW][2][94] = 0,
+ [0][0][1][0][RTW89_WW][0][96] = 22,
+ [0][0][1][0][RTW89_WW][1][96] = 22,
+ [0][0][1][0][RTW89_WW][2][96] = 0,
+ [0][0][1][0][RTW89_WW][0][98] = 22,
+ [0][0][1][0][RTW89_WW][1][98] = 22,
+ [0][0][1][0][RTW89_WW][2][98] = 0,
+ [0][0][1][0][RTW89_WW][0][100] = 22,
+ [0][0][1][0][RTW89_WW][1][100] = 22,
+ [0][0][1][0][RTW89_WW][2][100] = 0,
+ [0][0][1][0][RTW89_WW][0][102] = 22,
+ [0][0][1][0][RTW89_WW][1][102] = 22,
+ [0][0][1][0][RTW89_WW][2][102] = 0,
+ [0][0][1][0][RTW89_WW][0][104] = 22,
+ [0][0][1][0][RTW89_WW][1][104] = 22,
+ [0][0][1][0][RTW89_WW][2][104] = 0,
+ [0][0][1][0][RTW89_WW][0][105] = 22,
+ [0][0][1][0][RTW89_WW][1][105] = 22,
+ [0][0][1][0][RTW89_WW][2][105] = 0,
+ [0][0][1][0][RTW89_WW][0][107] = 24,
+ [0][0][1][0][RTW89_WW][1][107] = 24,
+ [0][0][1][0][RTW89_WW][2][107] = 0,
+ [0][0][1][0][RTW89_WW][0][109] = 24,
+ [0][0][1][0][RTW89_WW][1][109] = 24,
+ [0][0][1][0][RTW89_WW][2][109] = 0,
+ [0][0][1][0][RTW89_WW][0][111] = 0,
+ [0][0][1][0][RTW89_WW][1][111] = 0,
+ [0][0][1][0][RTW89_WW][2][111] = 0,
+ [0][0][1][0][RTW89_WW][0][113] = 0,
+ [0][0][1][0][RTW89_WW][1][113] = 0,
+ [0][0][1][0][RTW89_WW][2][113] = 0,
+ [0][0][1][0][RTW89_WW][0][115] = 0,
+ [0][0][1][0][RTW89_WW][1][115] = 0,
+ [0][0][1][0][RTW89_WW][2][115] = 0,
+ [0][0][1][0][RTW89_WW][0][117] = 0,
+ [0][0][1][0][RTW89_WW][1][117] = 0,
+ [0][0][1][0][RTW89_WW][2][117] = 0,
+ [0][0][1][0][RTW89_WW][0][119] = 0,
+ [0][0][1][0][RTW89_WW][1][119] = 0,
+ [0][0][1][0][RTW89_WW][2][119] = 0,
+ [0][1][1][0][RTW89_WW][0][0] = -2,
+ [0][1][1][0][RTW89_WW][1][0] = -2,
+ [0][1][1][0][RTW89_WW][2][0] = 54,
+ [0][1][1][0][RTW89_WW][0][2] = -4,
+ [0][1][1][0][RTW89_WW][1][2] = -4,
+ [0][1][1][0][RTW89_WW][2][2] = 54,
+ [0][1][1][0][RTW89_WW][0][4] = -4,
+ [0][1][1][0][RTW89_WW][1][4] = -4,
+ [0][1][1][0][RTW89_WW][2][4] = 54,
+ [0][1][1][0][RTW89_WW][0][6] = -4,
+ [0][1][1][0][RTW89_WW][1][6] = -4,
+ [0][1][1][0][RTW89_WW][2][6] = 54,
+ [0][1][1][0][RTW89_WW][0][8] = -4,
+ [0][1][1][0][RTW89_WW][1][8] = -4,
+ [0][1][1][0][RTW89_WW][2][8] = 54,
+ [0][1][1][0][RTW89_WW][0][10] = -4,
+ [0][1][1][0][RTW89_WW][1][10] = -4,
+ [0][1][1][0][RTW89_WW][2][10] = 54,
+ [0][1][1][0][RTW89_WW][0][12] = -4,
+ [0][1][1][0][RTW89_WW][1][12] = -4,
+ [0][1][1][0][RTW89_WW][2][12] = 54,
+ [0][1][1][0][RTW89_WW][0][14] = -4,
+ [0][1][1][0][RTW89_WW][1][14] = -4,
+ [0][1][1][0][RTW89_WW][2][14] = 54,
+ [0][1][1][0][RTW89_WW][0][15] = -4,
+ [0][1][1][0][RTW89_WW][1][15] = -4,
+ [0][1][1][0][RTW89_WW][2][15] = 54,
+ [0][1][1][0][RTW89_WW][0][17] = -4,
+ [0][1][1][0][RTW89_WW][1][17] = -4,
+ [0][1][1][0][RTW89_WW][2][17] = 54,
+ [0][1][1][0][RTW89_WW][0][19] = -4,
+ [0][1][1][0][RTW89_WW][1][19] = -4,
+ [0][1][1][0][RTW89_WW][2][19] = 54,
+ [0][1][1][0][RTW89_WW][0][21] = -4,
+ [0][1][1][0][RTW89_WW][1][21] = -4,
+ [0][1][1][0][RTW89_WW][2][21] = 54,
+ [0][1][1][0][RTW89_WW][0][23] = -4,
+ [0][1][1][0][RTW89_WW][1][23] = -4,
+ [0][1][1][0][RTW89_WW][2][23] = 68,
+ [0][1][1][0][RTW89_WW][0][25] = -4,
+ [0][1][1][0][RTW89_WW][1][25] = -4,
+ [0][1][1][0][RTW89_WW][2][25] = 68,
+ [0][1][1][0][RTW89_WW][0][27] = -4,
+ [0][1][1][0][RTW89_WW][1][27] = -4,
+ [0][1][1][0][RTW89_WW][2][27] = 68,
+ [0][1][1][0][RTW89_WW][0][29] = -4,
+ [0][1][1][0][RTW89_WW][1][29] = -4,
+ [0][1][1][0][RTW89_WW][2][29] = 68,
+ [0][1][1][0][RTW89_WW][0][30] = -4,
+ [0][1][1][0][RTW89_WW][1][30] = -4,
+ [0][1][1][0][RTW89_WW][2][30] = 68,
+ [0][1][1][0][RTW89_WW][0][32] = -4,
+ [0][1][1][0][RTW89_WW][1][32] = -4,
+ [0][1][1][0][RTW89_WW][2][32] = 68,
+ [0][1][1][0][RTW89_WW][0][34] = -4,
+ [0][1][1][0][RTW89_WW][1][34] = -4,
+ [0][1][1][0][RTW89_WW][2][34] = 68,
+ [0][1][1][0][RTW89_WW][0][36] = -4,
+ [0][1][1][0][RTW89_WW][1][36] = -4,
+ [0][1][1][0][RTW89_WW][2][36] = 68,
+ [0][1][1][0][RTW89_WW][0][38] = -4,
+ [0][1][1][0][RTW89_WW][1][38] = -4,
+ [0][1][1][0][RTW89_WW][2][38] = 68,
+ [0][1][1][0][RTW89_WW][0][40] = -4,
+ [0][1][1][0][RTW89_WW][1][40] = -4,
+ [0][1][1][0][RTW89_WW][2][40] = 68,
+ [0][1][1][0][RTW89_WW][0][42] = -4,
+ [0][1][1][0][RTW89_WW][1][42] = -4,
+ [0][1][1][0][RTW89_WW][2][42] = 68,
+ [0][1][1][0][RTW89_WW][0][44] = -2,
+ [0][1][1][0][RTW89_WW][1][44] = -2,
+ [0][1][1][0][RTW89_WW][2][44] = 68,
+ [0][1][1][0][RTW89_WW][0][45] = -2,
+ [0][1][1][0][RTW89_WW][1][45] = -2,
+ [0][1][1][0][RTW89_WW][2][45] = 0,
+ [0][1][1][0][RTW89_WW][0][47] = -2,
+ [0][1][1][0][RTW89_WW][1][47] = -2,
+ [0][1][1][0][RTW89_WW][2][47] = 0,
+ [0][1][1][0][RTW89_WW][0][49] = -2,
+ [0][1][1][0][RTW89_WW][1][49] = -2,
+ [0][1][1][0][RTW89_WW][2][49] = 0,
+ [0][1][1][0][RTW89_WW][0][51] = -2,
+ [0][1][1][0][RTW89_WW][1][51] = -2,
+ [0][1][1][0][RTW89_WW][2][51] = 0,
+ [0][1][1][0][RTW89_WW][0][53] = -2,
+ [0][1][1][0][RTW89_WW][1][53] = -2,
+ [0][1][1][0][RTW89_WW][2][53] = 0,
+ [0][1][1][0][RTW89_WW][0][55] = -2,
+ [0][1][1][0][RTW89_WW][1][55] = -2,
+ [0][1][1][0][RTW89_WW][2][55] = 68,
+ [0][1][1][0][RTW89_WW][0][57] = -2,
+ [0][1][1][0][RTW89_WW][1][57] = -2,
+ [0][1][1][0][RTW89_WW][2][57] = 68,
+ [0][1][1][0][RTW89_WW][0][59] = -2,
+ [0][1][1][0][RTW89_WW][1][59] = -2,
+ [0][1][1][0][RTW89_WW][2][59] = 68,
+ [0][1][1][0][RTW89_WW][0][60] = -2,
+ [0][1][1][0][RTW89_WW][1][60] = -2,
+ [0][1][1][0][RTW89_WW][2][60] = 68,
+ [0][1][1][0][RTW89_WW][0][62] = -2,
+ [0][1][1][0][RTW89_WW][1][62] = -2,
+ [0][1][1][0][RTW89_WW][2][62] = 68,
+ [0][1][1][0][RTW89_WW][0][64] = -2,
+ [0][1][1][0][RTW89_WW][1][64] = -2,
+ [0][1][1][0][RTW89_WW][2][64] = 68,
+ [0][1][1][0][RTW89_WW][0][66] = -2,
+ [0][1][1][0][RTW89_WW][1][66] = -2,
+ [0][1][1][0][RTW89_WW][2][66] = 68,
+ [0][1][1][0][RTW89_WW][0][68] = -2,
+ [0][1][1][0][RTW89_WW][1][68] = -2,
+ [0][1][1][0][RTW89_WW][2][68] = 68,
+ [0][1][1][0][RTW89_WW][0][70] = -2,
+ [0][1][1][0][RTW89_WW][1][70] = -2,
+ [0][1][1][0][RTW89_WW][2][70] = 68,
+ [0][1][1][0][RTW89_WW][0][72] = -2,
+ [0][1][1][0][RTW89_WW][1][72] = -2,
+ [0][1][1][0][RTW89_WW][2][72] = 68,
+ [0][1][1][0][RTW89_WW][0][74] = -2,
+ [0][1][1][0][RTW89_WW][1][74] = -2,
+ [0][1][1][0][RTW89_WW][2][74] = 68,
+ [0][1][1][0][RTW89_WW][0][75] = -2,
+ [0][1][1][0][RTW89_WW][1][75] = -2,
+ [0][1][1][0][RTW89_WW][2][75] = 68,
+ [0][1][1][0][RTW89_WW][0][77] = -2,
+ [0][1][1][0][RTW89_WW][1][77] = -2,
+ [0][1][1][0][RTW89_WW][2][77] = 68,
+ [0][1][1][0][RTW89_WW][0][79] = -2,
+ [0][1][1][0][RTW89_WW][1][79] = -2,
+ [0][1][1][0][RTW89_WW][2][79] = 68,
+ [0][1][1][0][RTW89_WW][0][81] = -2,
+ [0][1][1][0][RTW89_WW][1][81] = -2,
+ [0][1][1][0][RTW89_WW][2][81] = 68,
+ [0][1][1][0][RTW89_WW][0][83] = -2,
+ [0][1][1][0][RTW89_WW][1][83] = -2,
+ [0][1][1][0][RTW89_WW][2][83] = 68,
+ [0][1][1][0][RTW89_WW][0][85] = -2,
+ [0][1][1][0][RTW89_WW][1][85] = -2,
+ [0][1][1][0][RTW89_WW][2][85] = 68,
+ [0][1][1][0][RTW89_WW][0][87] = -2,
+ [0][1][1][0][RTW89_WW][1][87] = -2,
+ [0][1][1][0][RTW89_WW][2][87] = 0,
+ [0][1][1][0][RTW89_WW][0][89] = -2,
+ [0][1][1][0][RTW89_WW][1][89] = -2,
+ [0][1][1][0][RTW89_WW][2][89] = 0,
+ [0][1][1][0][RTW89_WW][0][90] = -2,
+ [0][1][1][0][RTW89_WW][1][90] = -2,
+ [0][1][1][0][RTW89_WW][2][90] = 0,
+ [0][1][1][0][RTW89_WW][0][92] = -2,
+ [0][1][1][0][RTW89_WW][1][92] = -2,
+ [0][1][1][0][RTW89_WW][2][92] = 0,
+ [0][1][1][0][RTW89_WW][0][94] = -2,
+ [0][1][1][0][RTW89_WW][1][94] = -2,
+ [0][1][1][0][RTW89_WW][2][94] = 0,
+ [0][1][1][0][RTW89_WW][0][96] = -2,
+ [0][1][1][0][RTW89_WW][1][96] = -2,
+ [0][1][1][0][RTW89_WW][2][96] = 0,
+ [0][1][1][0][RTW89_WW][0][98] = -2,
+ [0][1][1][0][RTW89_WW][1][98] = -2,
+ [0][1][1][0][RTW89_WW][2][98] = 0,
+ [0][1][1][0][RTW89_WW][0][100] = -2,
+ [0][1][1][0][RTW89_WW][1][100] = -2,
+ [0][1][1][0][RTW89_WW][2][100] = 0,
+ [0][1][1][0][RTW89_WW][0][102] = -2,
+ [0][1][1][0][RTW89_WW][1][102] = -2,
+ [0][1][1][0][RTW89_WW][2][102] = 0,
+ [0][1][1][0][RTW89_WW][0][104] = -2,
+ [0][1][1][0][RTW89_WW][1][104] = -2,
+ [0][1][1][0][RTW89_WW][2][104] = 0,
+ [0][1][1][0][RTW89_WW][0][105] = -2,
+ [0][1][1][0][RTW89_WW][1][105] = -2,
+ [0][1][1][0][RTW89_WW][2][105] = 0,
+ [0][1][1][0][RTW89_WW][0][107] = 1,
+ [0][1][1][0][RTW89_WW][1][107] = 1,
+ [0][1][1][0][RTW89_WW][2][107] = 0,
+ [0][1][1][0][RTW89_WW][0][109] = 1,
+ [0][1][1][0][RTW89_WW][1][109] = 1,
+ [0][1][1][0][RTW89_WW][2][109] = 0,
+ [0][1][1][0][RTW89_WW][0][111] = 0,
+ [0][1][1][0][RTW89_WW][1][111] = 0,
+ [0][1][1][0][RTW89_WW][2][111] = 0,
+ [0][1][1][0][RTW89_WW][0][113] = 0,
+ [0][1][1][0][RTW89_WW][1][113] = 0,
+ [0][1][1][0][RTW89_WW][2][113] = 0,
+ [0][1][1][0][RTW89_WW][0][115] = 0,
+ [0][1][1][0][RTW89_WW][1][115] = 0,
+ [0][1][1][0][RTW89_WW][2][115] = 0,
+ [0][1][1][0][RTW89_WW][0][117] = 0,
+ [0][1][1][0][RTW89_WW][1][117] = 0,
+ [0][1][1][0][RTW89_WW][2][117] = 0,
+ [0][1][1][0][RTW89_WW][0][119] = 0,
+ [0][1][1][0][RTW89_WW][1][119] = 0,
+ [0][1][1][0][RTW89_WW][2][119] = 0,
+ [0][0][2][0][RTW89_WW][0][0] = 24,
+ [0][0][2][0][RTW89_WW][1][0] = 24,
+ [0][0][2][0][RTW89_WW][2][0] = 56,
+ [0][0][2][0][RTW89_WW][0][2] = 22,
+ [0][0][2][0][RTW89_WW][1][2] = 22,
+ [0][0][2][0][RTW89_WW][2][2] = 56,
+ [0][0][2][0][RTW89_WW][0][4] = 22,
+ [0][0][2][0][RTW89_WW][1][4] = 22,
+ [0][0][2][0][RTW89_WW][2][4] = 56,
+ [0][0][2][0][RTW89_WW][0][6] = 22,
+ [0][0][2][0][RTW89_WW][1][6] = 22,
+ [0][0][2][0][RTW89_WW][2][6] = 56,
+ [0][0][2][0][RTW89_WW][0][8] = 22,
+ [0][0][2][0][RTW89_WW][1][8] = 22,
+ [0][0][2][0][RTW89_WW][2][8] = 56,
+ [0][0][2][0][RTW89_WW][0][10] = 22,
+ [0][0][2][0][RTW89_WW][1][10] = 22,
+ [0][0][2][0][RTW89_WW][2][10] = 56,
+ [0][0][2][0][RTW89_WW][0][12] = 22,
+ [0][0][2][0][RTW89_WW][1][12] = 22,
+ [0][0][2][0][RTW89_WW][2][12] = 56,
+ [0][0][2][0][RTW89_WW][0][14] = 22,
+ [0][0][2][0][RTW89_WW][1][14] = 22,
+ [0][0][2][0][RTW89_WW][2][14] = 56,
+ [0][0][2][0][RTW89_WW][0][15] = 22,
+ [0][0][2][0][RTW89_WW][1][15] = 22,
+ [0][0][2][0][RTW89_WW][2][15] = 56,
+ [0][0][2][0][RTW89_WW][0][17] = 22,
+ [0][0][2][0][RTW89_WW][1][17] = 22,
+ [0][0][2][0][RTW89_WW][2][17] = 56,
+ [0][0][2][0][RTW89_WW][0][19] = 22,
+ [0][0][2][0][RTW89_WW][1][19] = 22,
+ [0][0][2][0][RTW89_WW][2][19] = 56,
+ [0][0][2][0][RTW89_WW][0][21] = 22,
+ [0][0][2][0][RTW89_WW][1][21] = 22,
+ [0][0][2][0][RTW89_WW][2][21] = 56,
+ [0][0][2][0][RTW89_WW][0][23] = 22,
+ [0][0][2][0][RTW89_WW][1][23] = 22,
+ [0][0][2][0][RTW89_WW][2][23] = 70,
+ [0][0][2][0][RTW89_WW][0][25] = 22,
+ [0][0][2][0][RTW89_WW][1][25] = 22,
+ [0][0][2][0][RTW89_WW][2][25] = 70,
+ [0][0][2][0][RTW89_WW][0][27] = 22,
+ [0][0][2][0][RTW89_WW][1][27] = 22,
+ [0][0][2][0][RTW89_WW][2][27] = 70,
+ [0][0][2][0][RTW89_WW][0][29] = 22,
+ [0][0][2][0][RTW89_WW][1][29] = 22,
+ [0][0][2][0][RTW89_WW][2][29] = 70,
+ [0][0][2][0][RTW89_WW][0][30] = 22,
+ [0][0][2][0][RTW89_WW][1][30] = 22,
+ [0][0][2][0][RTW89_WW][2][30] = 70,
+ [0][0][2][0][RTW89_WW][0][32] = 22,
+ [0][0][2][0][RTW89_WW][1][32] = 22,
+ [0][0][2][0][RTW89_WW][2][32] = 70,
+ [0][0][2][0][RTW89_WW][0][34] = 22,
+ [0][0][2][0][RTW89_WW][1][34] = 22,
+ [0][0][2][0][RTW89_WW][2][34] = 70,
+ [0][0][2][0][RTW89_WW][0][36] = 22,
+ [0][0][2][0][RTW89_WW][1][36] = 22,
+ [0][0][2][0][RTW89_WW][2][36] = 70,
+ [0][0][2][0][RTW89_WW][0][38] = 22,
+ [0][0][2][0][RTW89_WW][1][38] = 22,
+ [0][0][2][0][RTW89_WW][2][38] = 70,
+ [0][0][2][0][RTW89_WW][0][40] = 22,
+ [0][0][2][0][RTW89_WW][1][40] = 22,
+ [0][0][2][0][RTW89_WW][2][40] = 70,
+ [0][0][2][0][RTW89_WW][0][42] = 22,
+ [0][0][2][0][RTW89_WW][1][42] = 22,
+ [0][0][2][0][RTW89_WW][2][42] = 70,
+ [0][0][2][0][RTW89_WW][0][44] = 22,
+ [0][0][2][0][RTW89_WW][1][44] = 22,
+ [0][0][2][0][RTW89_WW][2][44] = 70,
+ [0][0][2][0][RTW89_WW][0][45] = 22,
+ [0][0][2][0][RTW89_WW][1][45] = 22,
+ [0][0][2][0][RTW89_WW][2][45] = 0,
+ [0][0][2][0][RTW89_WW][0][47] = 22,
+ [0][0][2][0][RTW89_WW][1][47] = 22,
+ [0][0][2][0][RTW89_WW][2][47] = 0,
+ [0][0][2][0][RTW89_WW][0][49] = 24,
+ [0][0][2][0][RTW89_WW][1][49] = 24,
+ [0][0][2][0][RTW89_WW][2][49] = 0,
+ [0][0][2][0][RTW89_WW][0][51] = 22,
+ [0][0][2][0][RTW89_WW][1][51] = 22,
+ [0][0][2][0][RTW89_WW][2][51] = 0,
+ [0][0][2][0][RTW89_WW][0][53] = 22,
+ [0][0][2][0][RTW89_WW][1][53] = 22,
+ [0][0][2][0][RTW89_WW][2][53] = 0,
+ [0][0][2][0][RTW89_WW][0][55] = 22,
+ [0][0][2][0][RTW89_WW][1][55] = 22,
+ [0][0][2][0][RTW89_WW][2][55] = 68,
+ [0][0][2][0][RTW89_WW][0][57] = 22,
+ [0][0][2][0][RTW89_WW][1][57] = 22,
+ [0][0][2][0][RTW89_WW][2][57] = 68,
+ [0][0][2][0][RTW89_WW][0][59] = 22,
+ [0][0][2][0][RTW89_WW][1][59] = 22,
+ [0][0][2][0][RTW89_WW][2][59] = 68,
+ [0][0][2][0][RTW89_WW][0][60] = 22,
+ [0][0][2][0][RTW89_WW][1][60] = 22,
+ [0][0][2][0][RTW89_WW][2][60] = 68,
+ [0][0][2][0][RTW89_WW][0][62] = 22,
+ [0][0][2][0][RTW89_WW][1][62] = 22,
+ [0][0][2][0][RTW89_WW][2][62] = 68,
+ [0][0][2][0][RTW89_WW][0][64] = 22,
+ [0][0][2][0][RTW89_WW][1][64] = 22,
+ [0][0][2][0][RTW89_WW][2][64] = 68,
+ [0][0][2][0][RTW89_WW][0][66] = 22,
+ [0][0][2][0][RTW89_WW][1][66] = 22,
+ [0][0][2][0][RTW89_WW][2][66] = 68,
+ [0][0][2][0][RTW89_WW][0][68] = 22,
+ [0][0][2][0][RTW89_WW][1][68] = 22,
+ [0][0][2][0][RTW89_WW][2][68] = 68,
+ [0][0][2][0][RTW89_WW][0][70] = 24,
+ [0][0][2][0][RTW89_WW][1][70] = 24,
+ [0][0][2][0][RTW89_WW][2][70] = 68,
+ [0][0][2][0][RTW89_WW][0][72] = 22,
+ [0][0][2][0][RTW89_WW][1][72] = 22,
+ [0][0][2][0][RTW89_WW][2][72] = 68,
+ [0][0][2][0][RTW89_WW][0][74] = 22,
+ [0][0][2][0][RTW89_WW][1][74] = 22,
+ [0][0][2][0][RTW89_WW][2][74] = 68,
+ [0][0][2][0][RTW89_WW][0][75] = 22,
+ [0][0][2][0][RTW89_WW][1][75] = 22,
+ [0][0][2][0][RTW89_WW][2][75] = 68,
+ [0][0][2][0][RTW89_WW][0][77] = 22,
+ [0][0][2][0][RTW89_WW][1][77] = 22,
+ [0][0][2][0][RTW89_WW][2][77] = 68,
+ [0][0][2][0][RTW89_WW][0][79] = 22,
+ [0][0][2][0][RTW89_WW][1][79] = 22,
+ [0][0][2][0][RTW89_WW][2][79] = 68,
+ [0][0][2][0][RTW89_WW][0][81] = 22,
+ [0][0][2][0][RTW89_WW][1][81] = 22,
+ [0][0][2][0][RTW89_WW][2][81] = 68,
+ [0][0][2][0][RTW89_WW][0][83] = 22,
+ [0][0][2][0][RTW89_WW][1][83] = 22,
+ [0][0][2][0][RTW89_WW][2][83] = 68,
+ [0][0][2][0][RTW89_WW][0][85] = 22,
+ [0][0][2][0][RTW89_WW][1][85] = 22,
+ [0][0][2][0][RTW89_WW][2][85] = 68,
+ [0][0][2][0][RTW89_WW][0][87] = 22,
+ [0][0][2][0][RTW89_WW][1][87] = 22,
+ [0][0][2][0][RTW89_WW][2][87] = 0,
+ [0][0][2][0][RTW89_WW][0][89] = 22,
+ [0][0][2][0][RTW89_WW][1][89] = 22,
+ [0][0][2][0][RTW89_WW][2][89] = 0,
+ [0][0][2][0][RTW89_WW][0][90] = 22,
+ [0][0][2][0][RTW89_WW][1][90] = 22,
+ [0][0][2][0][RTW89_WW][2][90] = 0,
+ [0][0][2][0][RTW89_WW][0][92] = 22,
+ [0][0][2][0][RTW89_WW][1][92] = 22,
+ [0][0][2][0][RTW89_WW][2][92] = 0,
+ [0][0][2][0][RTW89_WW][0][94] = 22,
+ [0][0][2][0][RTW89_WW][1][94] = 22,
+ [0][0][2][0][RTW89_WW][2][94] = 0,
+ [0][0][2][0][RTW89_WW][0][96] = 22,
+ [0][0][2][0][RTW89_WW][1][96] = 22,
+ [0][0][2][0][RTW89_WW][2][96] = 0,
+ [0][0][2][0][RTW89_WW][0][98] = 22,
+ [0][0][2][0][RTW89_WW][1][98] = 22,
+ [0][0][2][0][RTW89_WW][2][98] = 0,
+ [0][0][2][0][RTW89_WW][0][100] = 22,
+ [0][0][2][0][RTW89_WW][1][100] = 22,
+ [0][0][2][0][RTW89_WW][2][100] = 0,
+ [0][0][2][0][RTW89_WW][0][102] = 22,
+ [0][0][2][0][RTW89_WW][1][102] = 22,
+ [0][0][2][0][RTW89_WW][2][102] = 0,
+ [0][0][2][0][RTW89_WW][0][104] = 22,
+ [0][0][2][0][RTW89_WW][1][104] = 22,
+ [0][0][2][0][RTW89_WW][2][104] = 0,
+ [0][0][2][0][RTW89_WW][0][105] = 22,
+ [0][0][2][0][RTW89_WW][1][105] = 22,
+ [0][0][2][0][RTW89_WW][2][105] = 0,
+ [0][0][2][0][RTW89_WW][0][107] = 24,
+ [0][0][2][0][RTW89_WW][1][107] = 24,
+ [0][0][2][0][RTW89_WW][2][107] = 0,
+ [0][0][2][0][RTW89_WW][0][109] = 24,
+ [0][0][2][0][RTW89_WW][1][109] = 24,
+ [0][0][2][0][RTW89_WW][2][109] = 0,
+ [0][0][2][0][RTW89_WW][0][111] = 0,
+ [0][0][2][0][RTW89_WW][1][111] = 0,
+ [0][0][2][0][RTW89_WW][2][111] = 0,
+ [0][0][2][0][RTW89_WW][0][113] = 0,
+ [0][0][2][0][RTW89_WW][1][113] = 0,
+ [0][0][2][0][RTW89_WW][2][113] = 0,
+ [0][0][2][0][RTW89_WW][0][115] = 0,
+ [0][0][2][0][RTW89_WW][1][115] = 0,
+ [0][0][2][0][RTW89_WW][2][115] = 0,
+ [0][0][2][0][RTW89_WW][0][117] = 0,
+ [0][0][2][0][RTW89_WW][1][117] = 0,
+ [0][0][2][0][RTW89_WW][2][117] = 0,
+ [0][0][2][0][RTW89_WW][0][119] = 0,
+ [0][0][2][0][RTW89_WW][1][119] = 0,
+ [0][0][2][0][RTW89_WW][2][119] = 0,
+ [0][1][2][0][RTW89_WW][0][0] = -2,
+ [0][1][2][0][RTW89_WW][1][0] = -2,
+ [0][1][2][0][RTW89_WW][2][0] = 54,
+ [0][1][2][0][RTW89_WW][0][2] = -4,
+ [0][1][2][0][RTW89_WW][1][2] = -4,
+ [0][1][2][0][RTW89_WW][2][2] = 54,
+ [0][1][2][0][RTW89_WW][0][4] = -4,
+ [0][1][2][0][RTW89_WW][1][4] = -4,
+ [0][1][2][0][RTW89_WW][2][4] = 54,
+ [0][1][2][0][RTW89_WW][0][6] = -4,
+ [0][1][2][0][RTW89_WW][1][6] = -4,
+ [0][1][2][0][RTW89_WW][2][6] = 54,
+ [0][1][2][0][RTW89_WW][0][8] = -4,
+ [0][1][2][0][RTW89_WW][1][8] = -4,
+ [0][1][2][0][RTW89_WW][2][8] = 54,
+ [0][1][2][0][RTW89_WW][0][10] = -4,
+ [0][1][2][0][RTW89_WW][1][10] = -4,
+ [0][1][2][0][RTW89_WW][2][10] = 54,
+ [0][1][2][0][RTW89_WW][0][12] = -4,
+ [0][1][2][0][RTW89_WW][1][12] = -4,
+ [0][1][2][0][RTW89_WW][2][12] = 54,
+ [0][1][2][0][RTW89_WW][0][14] = -4,
+ [0][1][2][0][RTW89_WW][1][14] = -4,
+ [0][1][2][0][RTW89_WW][2][14] = 54,
+ [0][1][2][0][RTW89_WW][0][15] = -4,
+ [0][1][2][0][RTW89_WW][1][15] = -4,
+ [0][1][2][0][RTW89_WW][2][15] = 54,
+ [0][1][2][0][RTW89_WW][0][17] = -4,
+ [0][1][2][0][RTW89_WW][1][17] = -4,
+ [0][1][2][0][RTW89_WW][2][17] = 54,
+ [0][1][2][0][RTW89_WW][0][19] = -4,
+ [0][1][2][0][RTW89_WW][1][19] = -4,
+ [0][1][2][0][RTW89_WW][2][19] = 54,
+ [0][1][2][0][RTW89_WW][0][21] = -4,
+ [0][1][2][0][RTW89_WW][1][21] = -4,
+ [0][1][2][0][RTW89_WW][2][21] = 54,
+ [0][1][2][0][RTW89_WW][0][23] = -4,
+ [0][1][2][0][RTW89_WW][1][23] = -4,
+ [0][1][2][0][RTW89_WW][2][23] = 68,
+ [0][1][2][0][RTW89_WW][0][25] = -4,
+ [0][1][2][0][RTW89_WW][1][25] = -4,
+ [0][1][2][0][RTW89_WW][2][25] = 68,
+ [0][1][2][0][RTW89_WW][0][27] = -4,
+ [0][1][2][0][RTW89_WW][1][27] = -4,
+ [0][1][2][0][RTW89_WW][2][27] = 68,
+ [0][1][2][0][RTW89_WW][0][29] = -4,
+ [0][1][2][0][RTW89_WW][1][29] = -4,
+ [0][1][2][0][RTW89_WW][2][29] = 68,
+ [0][1][2][0][RTW89_WW][0][30] = -4,
+ [0][1][2][0][RTW89_WW][1][30] = -4,
+ [0][1][2][0][RTW89_WW][2][30] = 68,
+ [0][1][2][0][RTW89_WW][0][32] = -4,
+ [0][1][2][0][RTW89_WW][1][32] = -4,
+ [0][1][2][0][RTW89_WW][2][32] = 68,
+ [0][1][2][0][RTW89_WW][0][34] = -4,
+ [0][1][2][0][RTW89_WW][1][34] = -4,
+ [0][1][2][0][RTW89_WW][2][34] = 68,
+ [0][1][2][0][RTW89_WW][0][36] = -4,
+ [0][1][2][0][RTW89_WW][1][36] = -4,
+ [0][1][2][0][RTW89_WW][2][36] = 68,
+ [0][1][2][0][RTW89_WW][0][38] = -4,
+ [0][1][2][0][RTW89_WW][1][38] = -4,
+ [0][1][2][0][RTW89_WW][2][38] = 68,
+ [0][1][2][0][RTW89_WW][0][40] = -4,
+ [0][1][2][0][RTW89_WW][1][40] = -4,
+ [0][1][2][0][RTW89_WW][2][40] = 68,
+ [0][1][2][0][RTW89_WW][0][42] = -4,
+ [0][1][2][0][RTW89_WW][1][42] = -4,
+ [0][1][2][0][RTW89_WW][2][42] = 68,
+ [0][1][2][0][RTW89_WW][0][44] = -2,
+ [0][1][2][0][RTW89_WW][1][44] = -2,
+ [0][1][2][0][RTW89_WW][2][44] = 68,
+ [0][1][2][0][RTW89_WW][0][45] = -2,
+ [0][1][2][0][RTW89_WW][1][45] = -2,
+ [0][1][2][0][RTW89_WW][2][45] = 0,
+ [0][1][2][0][RTW89_WW][0][47] = -2,
+ [0][1][2][0][RTW89_WW][1][47] = -2,
+ [0][1][2][0][RTW89_WW][2][47] = 0,
+ [0][1][2][0][RTW89_WW][0][49] = -2,
+ [0][1][2][0][RTW89_WW][1][49] = -2,
+ [0][1][2][0][RTW89_WW][2][49] = 0,
+ [0][1][2][0][RTW89_WW][0][51] = -2,
+ [0][1][2][0][RTW89_WW][1][51] = -2,
+ [0][1][2][0][RTW89_WW][2][51] = 0,
+ [0][1][2][0][RTW89_WW][0][53] = -2,
+ [0][1][2][0][RTW89_WW][1][53] = -2,
+ [0][1][2][0][RTW89_WW][2][53] = 0,
+ [0][1][2][0][RTW89_WW][0][55] = -2,
+ [0][1][2][0][RTW89_WW][1][55] = -2,
+ [0][1][2][0][RTW89_WW][2][55] = 68,
+ [0][1][2][0][RTW89_WW][0][57] = -2,
+ [0][1][2][0][RTW89_WW][1][57] = -2,
+ [0][1][2][0][RTW89_WW][2][57] = 68,
+ [0][1][2][0][RTW89_WW][0][59] = -2,
+ [0][1][2][0][RTW89_WW][1][59] = -2,
+ [0][1][2][0][RTW89_WW][2][59] = 68,
+ [0][1][2][0][RTW89_WW][0][60] = -2,
+ [0][1][2][0][RTW89_WW][1][60] = -2,
+ [0][1][2][0][RTW89_WW][2][60] = 68,
+ [0][1][2][0][RTW89_WW][0][62] = -2,
+ [0][1][2][0][RTW89_WW][1][62] = -2,
+ [0][1][2][0][RTW89_WW][2][62] = 68,
+ [0][1][2][0][RTW89_WW][0][64] = -2,
+ [0][1][2][0][RTW89_WW][1][64] = -2,
+ [0][1][2][0][RTW89_WW][2][64] = 68,
+ [0][1][2][0][RTW89_WW][0][66] = -2,
+ [0][1][2][0][RTW89_WW][1][66] = -2,
+ [0][1][2][0][RTW89_WW][2][66] = 68,
+ [0][1][2][0][RTW89_WW][0][68] = -2,
+ [0][1][2][0][RTW89_WW][1][68] = -2,
+ [0][1][2][0][RTW89_WW][2][68] = 68,
+ [0][1][2][0][RTW89_WW][0][70] = -2,
+ [0][1][2][0][RTW89_WW][1][70] = -2,
+ [0][1][2][0][RTW89_WW][2][70] = 68,
+ [0][1][2][0][RTW89_WW][0][72] = -2,
+ [0][1][2][0][RTW89_WW][1][72] = -2,
+ [0][1][2][0][RTW89_WW][2][72] = 68,
+ [0][1][2][0][RTW89_WW][0][74] = -2,
+ [0][1][2][0][RTW89_WW][1][74] = -2,
+ [0][1][2][0][RTW89_WW][2][74] = 68,
+ [0][1][2][0][RTW89_WW][0][75] = -2,
+ [0][1][2][0][RTW89_WW][1][75] = -2,
+ [0][1][2][0][RTW89_WW][2][75] = 68,
+ [0][1][2][0][RTW89_WW][0][77] = -2,
+ [0][1][2][0][RTW89_WW][1][77] = -2,
+ [0][1][2][0][RTW89_WW][2][77] = 68,
+ [0][1][2][0][RTW89_WW][0][79] = -2,
+ [0][1][2][0][RTW89_WW][1][79] = -2,
+ [0][1][2][0][RTW89_WW][2][79] = 68,
+ [0][1][2][0][RTW89_WW][0][81] = -2,
+ [0][1][2][0][RTW89_WW][1][81] = -2,
+ [0][1][2][0][RTW89_WW][2][81] = 68,
+ [0][1][2][0][RTW89_WW][0][83] = -2,
+ [0][1][2][0][RTW89_WW][1][83] = -2,
+ [0][1][2][0][RTW89_WW][2][83] = 68,
+ [0][1][2][0][RTW89_WW][0][85] = -2,
+ [0][1][2][0][RTW89_WW][1][85] = -2,
+ [0][1][2][0][RTW89_WW][2][85] = 68,
+ [0][1][2][0][RTW89_WW][0][87] = -2,
+ [0][1][2][0][RTW89_WW][1][87] = -2,
+ [0][1][2][0][RTW89_WW][2][87] = 0,
+ [0][1][2][0][RTW89_WW][0][89] = -2,
+ [0][1][2][0][RTW89_WW][1][89] = -2,
+ [0][1][2][0][RTW89_WW][2][89] = 0,
+ [0][1][2][0][RTW89_WW][0][90] = -2,
+ [0][1][2][0][RTW89_WW][1][90] = -2,
+ [0][1][2][0][RTW89_WW][2][90] = 0,
+ [0][1][2][0][RTW89_WW][0][92] = -2,
+ [0][1][2][0][RTW89_WW][1][92] = -2,
+ [0][1][2][0][RTW89_WW][2][92] = 0,
+ [0][1][2][0][RTW89_WW][0][94] = -2,
+ [0][1][2][0][RTW89_WW][1][94] = -2,
+ [0][1][2][0][RTW89_WW][2][94] = 0,
+ [0][1][2][0][RTW89_WW][0][96] = -2,
+ [0][1][2][0][RTW89_WW][1][96] = -2,
+ [0][1][2][0][RTW89_WW][2][96] = 0,
+ [0][1][2][0][RTW89_WW][0][98] = -2,
+ [0][1][2][0][RTW89_WW][1][98] = -2,
+ [0][1][2][0][RTW89_WW][2][98] = 0,
+ [0][1][2][0][RTW89_WW][0][100] = -2,
+ [0][1][2][0][RTW89_WW][1][100] = -2,
+ [0][1][2][0][RTW89_WW][2][100] = 0,
+ [0][1][2][0][RTW89_WW][0][102] = -2,
+ [0][1][2][0][RTW89_WW][1][102] = -2,
+ [0][1][2][0][RTW89_WW][2][102] = 0,
+ [0][1][2][0][RTW89_WW][0][104] = -2,
+ [0][1][2][0][RTW89_WW][1][104] = -2,
+ [0][1][2][0][RTW89_WW][2][104] = 0,
+ [0][1][2][0][RTW89_WW][0][105] = -2,
+ [0][1][2][0][RTW89_WW][1][105] = -2,
+ [0][1][2][0][RTW89_WW][2][105] = 0,
+ [0][1][2][0][RTW89_WW][0][107] = 1,
+ [0][1][2][0][RTW89_WW][1][107] = 1,
+ [0][1][2][0][RTW89_WW][2][107] = 0,
+ [0][1][2][0][RTW89_WW][0][109] = 1,
+ [0][1][2][0][RTW89_WW][1][109] = 1,
+ [0][1][2][0][RTW89_WW][2][109] = 0,
+ [0][1][2][0][RTW89_WW][0][111] = 0,
+ [0][1][2][0][RTW89_WW][1][111] = 0,
+ [0][1][2][0][RTW89_WW][2][111] = 0,
+ [0][1][2][0][RTW89_WW][0][113] = 0,
+ [0][1][2][0][RTW89_WW][1][113] = 0,
+ [0][1][2][0][RTW89_WW][2][113] = 0,
+ [0][1][2][0][RTW89_WW][0][115] = 0,
+ [0][1][2][0][RTW89_WW][1][115] = 0,
+ [0][1][2][0][RTW89_WW][2][115] = 0,
+ [0][1][2][0][RTW89_WW][0][117] = 0,
+ [0][1][2][0][RTW89_WW][1][117] = 0,
+ [0][1][2][0][RTW89_WW][2][117] = 0,
+ [0][1][2][0][RTW89_WW][0][119] = 0,
+ [0][1][2][0][RTW89_WW][1][119] = 0,
+ [0][1][2][0][RTW89_WW][2][119] = 0,
+ [0][1][2][1][RTW89_WW][0][0] = -2,
+ [0][1][2][1][RTW89_WW][1][0] = -2,
+ [0][1][2][1][RTW89_WW][2][0] = 54,
+ [0][1][2][1][RTW89_WW][0][2] = -4,
+ [0][1][2][1][RTW89_WW][1][2] = -4,
+ [0][1][2][1][RTW89_WW][2][2] = 54,
+ [0][1][2][1][RTW89_WW][0][4] = -4,
+ [0][1][2][1][RTW89_WW][1][4] = -4,
+ [0][1][2][1][RTW89_WW][2][4] = 54,
+ [0][1][2][1][RTW89_WW][0][6] = -4,
+ [0][1][2][1][RTW89_WW][1][6] = -4,
+ [0][1][2][1][RTW89_WW][2][6] = 54,
+ [0][1][2][1][RTW89_WW][0][8] = -4,
+ [0][1][2][1][RTW89_WW][1][8] = -4,
+ [0][1][2][1][RTW89_WW][2][8] = 54,
+ [0][1][2][1][RTW89_WW][0][10] = -4,
+ [0][1][2][1][RTW89_WW][1][10] = -4,
+ [0][1][2][1][RTW89_WW][2][10] = 54,
+ [0][1][2][1][RTW89_WW][0][12] = -4,
+ [0][1][2][1][RTW89_WW][1][12] = -4,
+ [0][1][2][1][RTW89_WW][2][12] = 54,
+ [0][1][2][1][RTW89_WW][0][14] = -4,
+ [0][1][2][1][RTW89_WW][1][14] = -4,
+ [0][1][2][1][RTW89_WW][2][14] = 54,
+ [0][1][2][1][RTW89_WW][0][15] = -4,
+ [0][1][2][1][RTW89_WW][1][15] = -4,
+ [0][1][2][1][RTW89_WW][2][15] = 54,
+ [0][1][2][1][RTW89_WW][0][17] = -4,
+ [0][1][2][1][RTW89_WW][1][17] = -4,
+ [0][1][2][1][RTW89_WW][2][17] = 54,
+ [0][1][2][1][RTW89_WW][0][19] = -4,
+ [0][1][2][1][RTW89_WW][1][19] = -4,
+ [0][1][2][1][RTW89_WW][2][19] = 54,
+ [0][1][2][1][RTW89_WW][0][21] = -4,
+ [0][1][2][1][RTW89_WW][1][21] = -4,
+ [0][1][2][1][RTW89_WW][2][21] = 54,
+ [0][1][2][1][RTW89_WW][0][23] = -4,
+ [0][1][2][1][RTW89_WW][1][23] = -4,
+ [0][1][2][1][RTW89_WW][2][23] = 68,
+ [0][1][2][1][RTW89_WW][0][25] = -4,
+ [0][1][2][1][RTW89_WW][1][25] = -4,
+ [0][1][2][1][RTW89_WW][2][25] = 68,
+ [0][1][2][1][RTW89_WW][0][27] = -4,
+ [0][1][2][1][RTW89_WW][1][27] = -4,
+ [0][1][2][1][RTW89_WW][2][27] = 68,
+ [0][1][2][1][RTW89_WW][0][29] = -4,
+ [0][1][2][1][RTW89_WW][1][29] = -4,
+ [0][1][2][1][RTW89_WW][2][29] = 68,
+ [0][1][2][1][RTW89_WW][0][30] = -4,
+ [0][1][2][1][RTW89_WW][1][30] = -4,
+ [0][1][2][1][RTW89_WW][2][30] = 68,
+ [0][1][2][1][RTW89_WW][0][32] = -4,
+ [0][1][2][1][RTW89_WW][1][32] = -4,
+ [0][1][2][1][RTW89_WW][2][32] = 68,
+ [0][1][2][1][RTW89_WW][0][34] = -4,
+ [0][1][2][1][RTW89_WW][1][34] = -4,
+ [0][1][2][1][RTW89_WW][2][34] = 68,
+ [0][1][2][1][RTW89_WW][0][36] = -4,
+ [0][1][2][1][RTW89_WW][1][36] = -4,
+ [0][1][2][1][RTW89_WW][2][36] = 68,
+ [0][1][2][1][RTW89_WW][0][38] = -4,
+ [0][1][2][1][RTW89_WW][1][38] = -4,
+ [0][1][2][1][RTW89_WW][2][38] = 68,
+ [0][1][2][1][RTW89_WW][0][40] = -4,
+ [0][1][2][1][RTW89_WW][1][40] = -4,
+ [0][1][2][1][RTW89_WW][2][40] = 68,
+ [0][1][2][1][RTW89_WW][0][42] = -4,
+ [0][1][2][1][RTW89_WW][1][42] = -4,
+ [0][1][2][1][RTW89_WW][2][42] = 68,
+ [0][1][2][1][RTW89_WW][0][44] = -2,
+ [0][1][2][1][RTW89_WW][1][44] = -2,
+ [0][1][2][1][RTW89_WW][2][44] = 68,
+ [0][1][2][1][RTW89_WW][0][45] = -2,
+ [0][1][2][1][RTW89_WW][1][45] = -2,
+ [0][1][2][1][RTW89_WW][2][45] = 0,
+ [0][1][2][1][RTW89_WW][0][47] = -2,
+ [0][1][2][1][RTW89_WW][1][47] = -2,
+ [0][1][2][1][RTW89_WW][2][47] = 0,
+ [0][1][2][1][RTW89_WW][0][49] = -2,
+ [0][1][2][1][RTW89_WW][1][49] = -2,
+ [0][1][2][1][RTW89_WW][2][49] = 0,
+ [0][1][2][1][RTW89_WW][0][51] = -2,
+ [0][1][2][1][RTW89_WW][1][51] = -2,
+ [0][1][2][1][RTW89_WW][2][51] = 0,
+ [0][1][2][1][RTW89_WW][0][53] = -2,
+ [0][1][2][1][RTW89_WW][1][53] = -2,
+ [0][1][2][1][RTW89_WW][2][53] = 0,
+ [0][1][2][1][RTW89_WW][0][55] = -2,
+ [0][1][2][1][RTW89_WW][1][55] = -2,
+ [0][1][2][1][RTW89_WW][2][55] = 68,
+ [0][1][2][1][RTW89_WW][0][57] = -2,
+ [0][1][2][1][RTW89_WW][1][57] = -2,
+ [0][1][2][1][RTW89_WW][2][57] = 68,
+ [0][1][2][1][RTW89_WW][0][59] = -2,
+ [0][1][2][1][RTW89_WW][1][59] = -2,
+ [0][1][2][1][RTW89_WW][2][59] = 68,
+ [0][1][2][1][RTW89_WW][0][60] = -2,
+ [0][1][2][1][RTW89_WW][1][60] = -2,
+ [0][1][2][1][RTW89_WW][2][60] = 68,
+ [0][1][2][1][RTW89_WW][0][62] = -2,
+ [0][1][2][1][RTW89_WW][1][62] = -2,
+ [0][1][2][1][RTW89_WW][2][62] = 68,
+ [0][1][2][1][RTW89_WW][0][64] = -2,
+ [0][1][2][1][RTW89_WW][1][64] = -2,
+ [0][1][2][1][RTW89_WW][2][64] = 68,
+ [0][1][2][1][RTW89_WW][0][66] = -2,
+ [0][1][2][1][RTW89_WW][1][66] = -2,
+ [0][1][2][1][RTW89_WW][2][66] = 68,
+ [0][1][2][1][RTW89_WW][0][68] = -2,
+ [0][1][2][1][RTW89_WW][1][68] = -2,
+ [0][1][2][1][RTW89_WW][2][68] = 68,
+ [0][1][2][1][RTW89_WW][0][70] = -2,
+ [0][1][2][1][RTW89_WW][1][70] = -2,
+ [0][1][2][1][RTW89_WW][2][70] = 68,
+ [0][1][2][1][RTW89_WW][0][72] = -2,
+ [0][1][2][1][RTW89_WW][1][72] = -2,
+ [0][1][2][1][RTW89_WW][2][72] = 68,
+ [0][1][2][1][RTW89_WW][0][74] = -2,
+ [0][1][2][1][RTW89_WW][1][74] = -2,
+ [0][1][2][1][RTW89_WW][2][74] = 68,
+ [0][1][2][1][RTW89_WW][0][75] = -2,
+ [0][1][2][1][RTW89_WW][1][75] = -2,
+ [0][1][2][1][RTW89_WW][2][75] = 68,
+ [0][1][2][1][RTW89_WW][0][77] = -2,
+ [0][1][2][1][RTW89_WW][1][77] = -2,
+ [0][1][2][1][RTW89_WW][2][77] = 68,
+ [0][1][2][1][RTW89_WW][0][79] = -2,
+ [0][1][2][1][RTW89_WW][1][79] = -2,
+ [0][1][2][1][RTW89_WW][2][79] = 68,
+ [0][1][2][1][RTW89_WW][0][81] = -2,
+ [0][1][2][1][RTW89_WW][1][81] = -2,
+ [0][1][2][1][RTW89_WW][2][81] = 68,
+ [0][1][2][1][RTW89_WW][0][83] = -2,
+ [0][1][2][1][RTW89_WW][1][83] = -2,
+ [0][1][2][1][RTW89_WW][2][83] = 68,
+ [0][1][2][1][RTW89_WW][0][85] = -2,
+ [0][1][2][1][RTW89_WW][1][85] = -2,
+ [0][1][2][1][RTW89_WW][2][85] = 68,
+ [0][1][2][1][RTW89_WW][0][87] = -2,
+ [0][1][2][1][RTW89_WW][1][87] = -2,
+ [0][1][2][1][RTW89_WW][2][87] = 0,
+ [0][1][2][1][RTW89_WW][0][89] = -2,
+ [0][1][2][1][RTW89_WW][1][89] = -2,
+ [0][1][2][1][RTW89_WW][2][89] = 0,
+ [0][1][2][1][RTW89_WW][0][90] = -2,
+ [0][1][2][1][RTW89_WW][1][90] = -2,
+ [0][1][2][1][RTW89_WW][2][90] = 0,
+ [0][1][2][1][RTW89_WW][0][92] = -2,
+ [0][1][2][1][RTW89_WW][1][92] = -2,
+ [0][1][2][1][RTW89_WW][2][92] = 0,
+ [0][1][2][1][RTW89_WW][0][94] = -2,
+ [0][1][2][1][RTW89_WW][1][94] = -2,
+ [0][1][2][1][RTW89_WW][2][94] = 0,
+ [0][1][2][1][RTW89_WW][0][96] = -2,
+ [0][1][2][1][RTW89_WW][1][96] = -2,
+ [0][1][2][1][RTW89_WW][2][96] = 0,
+ [0][1][2][1][RTW89_WW][0][98] = -2,
+ [0][1][2][1][RTW89_WW][1][98] = -2,
+ [0][1][2][1][RTW89_WW][2][98] = 0,
+ [0][1][2][1][RTW89_WW][0][100] = -2,
+ [0][1][2][1][RTW89_WW][1][100] = -2,
+ [0][1][2][1][RTW89_WW][2][100] = 0,
+ [0][1][2][1][RTW89_WW][0][102] = -2,
+ [0][1][2][1][RTW89_WW][1][102] = -2,
+ [0][1][2][1][RTW89_WW][2][102] = 0,
+ [0][1][2][1][RTW89_WW][0][104] = -2,
+ [0][1][2][1][RTW89_WW][1][104] = -2,
+ [0][1][2][1][RTW89_WW][2][104] = 0,
+ [0][1][2][1][RTW89_WW][0][105] = -2,
+ [0][1][2][1][RTW89_WW][1][105] = -2,
+ [0][1][2][1][RTW89_WW][2][105] = 0,
+ [0][1][2][1][RTW89_WW][0][107] = 1,
+ [0][1][2][1][RTW89_WW][1][107] = 1,
+ [0][1][2][1][RTW89_WW][2][107] = 0,
+ [0][1][2][1][RTW89_WW][0][109] = 1,
+ [0][1][2][1][RTW89_WW][1][109] = 1,
+ [0][1][2][1][RTW89_WW][2][109] = 0,
+ [0][1][2][1][RTW89_WW][0][111] = 0,
+ [0][1][2][1][RTW89_WW][1][111] = 0,
+ [0][1][2][1][RTW89_WW][2][111] = 0,
+ [0][1][2][1][RTW89_WW][0][113] = 0,
+ [0][1][2][1][RTW89_WW][1][113] = 0,
+ [0][1][2][1][RTW89_WW][2][113] = 0,
+ [0][1][2][1][RTW89_WW][0][115] = 0,
+ [0][1][2][1][RTW89_WW][1][115] = 0,
+ [0][1][2][1][RTW89_WW][2][115] = 0,
+ [0][1][2][1][RTW89_WW][0][117] = 0,
+ [0][1][2][1][RTW89_WW][1][117] = 0,
+ [0][1][2][1][RTW89_WW][2][117] = 0,
+ [0][1][2][1][RTW89_WW][0][119] = 0,
+ [0][1][2][1][RTW89_WW][1][119] = 0,
+ [0][1][2][1][RTW89_WW][2][119] = 0,
+ [1][0][2][0][RTW89_WW][0][1] = 24,
+ [1][0][2][0][RTW89_WW][1][1] = 34,
+ [1][0][2][0][RTW89_WW][2][1] = 70,
+ [1][0][2][0][RTW89_WW][0][5] = 24,
+ [1][0][2][0][RTW89_WW][1][5] = 34,
+ [1][0][2][0][RTW89_WW][2][5] = 70,
+ [1][0][2][0][RTW89_WW][0][9] = 24,
+ [1][0][2][0][RTW89_WW][1][9] = 34,
+ [1][0][2][0][RTW89_WW][2][9] = 70,
+ [1][0][2][0][RTW89_WW][0][13] = 24,
+ [1][0][2][0][RTW89_WW][1][13] = 34,
+ [1][0][2][0][RTW89_WW][2][13] = 70,
+ [1][0][2][0][RTW89_WW][0][16] = 24,
+ [1][0][2][0][RTW89_WW][1][16] = 34,
+ [1][0][2][0][RTW89_WW][2][16] = 70,
+ [1][0][2][0][RTW89_WW][0][20] = 24,
+ [1][0][2][0][RTW89_WW][1][20] = 34,
+ [1][0][2][0][RTW89_WW][2][20] = 70,
+ [1][0][2][0][RTW89_WW][0][24] = 26,
+ [1][0][2][0][RTW89_WW][1][24] = 36,
+ [1][0][2][0][RTW89_WW][2][24] = 70,
+ [1][0][2][0][RTW89_WW][0][28] = 26,
+ [1][0][2][0][RTW89_WW][1][28] = 34,
+ [1][0][2][0][RTW89_WW][2][28] = 70,
+ [1][0][2][0][RTW89_WW][0][31] = 26,
+ [1][0][2][0][RTW89_WW][1][31] = 34,
+ [1][0][2][0][RTW89_WW][2][31] = 70,
+ [1][0][2][0][RTW89_WW][0][35] = 26,
+ [1][0][2][0][RTW89_WW][1][35] = 34,
+ [1][0][2][0][RTW89_WW][2][35] = 70,
+ [1][0][2][0][RTW89_WW][0][39] = 26,
+ [1][0][2][0][RTW89_WW][1][39] = 34,
+ [1][0][2][0][RTW89_WW][2][39] = 70,
+ [1][0][2][0][RTW89_WW][0][43] = 26,
+ [1][0][2][0][RTW89_WW][1][43] = 34,
+ [1][0][2][0][RTW89_WW][2][43] = 70,
+ [1][0][2][0][RTW89_WW][0][46] = 34,
+ [1][0][2][0][RTW89_WW][1][46] = 34,
+ [1][0][2][0][RTW89_WW][2][46] = 0,
+ [1][0][2][0][RTW89_WW][0][50] = 34,
+ [1][0][2][0][RTW89_WW][1][50] = 34,
+ [1][0][2][0][RTW89_WW][2][50] = 0,
+ [1][0][2][0][RTW89_WW][0][54] = 36,
+ [1][0][2][0][RTW89_WW][1][54] = 36,
+ [1][0][2][0][RTW89_WW][2][54] = 0,
+ [1][0][2][0][RTW89_WW][0][58] = 36,
+ [1][0][2][0][RTW89_WW][1][58] = 36,
+ [1][0][2][0][RTW89_WW][2][58] = 66,
+ [1][0][2][0][RTW89_WW][0][61] = 34,
+ [1][0][2][0][RTW89_WW][1][61] = 34,
+ [1][0][2][0][RTW89_WW][2][61] = 66,
+ [1][0][2][0][RTW89_WW][0][65] = 34,
+ [1][0][2][0][RTW89_WW][1][65] = 34,
+ [1][0][2][0][RTW89_WW][2][65] = 66,
+ [1][0][2][0][RTW89_WW][0][69] = 34,
+ [1][0][2][0][RTW89_WW][1][69] = 34,
+ [1][0][2][0][RTW89_WW][2][69] = 66,
+ [1][0][2][0][RTW89_WW][0][73] = 34,
+ [1][0][2][0][RTW89_WW][1][73] = 34,
+ [1][0][2][0][RTW89_WW][2][73] = 66,
+ [1][0][2][0][RTW89_WW][0][76] = 34,
+ [1][0][2][0][RTW89_WW][1][76] = 34,
+ [1][0][2][0][RTW89_WW][2][76] = 66,
+ [1][0][2][0][RTW89_WW][0][80] = 34,
+ [1][0][2][0][RTW89_WW][1][80] = 34,
+ [1][0][2][0][RTW89_WW][2][80] = 66,
+ [1][0][2][0][RTW89_WW][0][84] = 34,
+ [1][0][2][0][RTW89_WW][1][84] = 34,
+ [1][0][2][0][RTW89_WW][2][84] = 66,
+ [1][0][2][0][RTW89_WW][0][88] = 34,
+ [1][0][2][0][RTW89_WW][1][88] = 34,
+ [1][0][2][0][RTW89_WW][2][88] = 0,
+ [1][0][2][0][RTW89_WW][0][91] = 36,
+ [1][0][2][0][RTW89_WW][1][91] = 36,
+ [1][0][2][0][RTW89_WW][2][91] = 0,
+ [1][0][2][0][RTW89_WW][0][95] = 34,
+ [1][0][2][0][RTW89_WW][1][95] = 34,
+ [1][0][2][0][RTW89_WW][2][95] = 0,
+ [1][0][2][0][RTW89_WW][0][99] = 34,
+ [1][0][2][0][RTW89_WW][1][99] = 34,
+ [1][0][2][0][RTW89_WW][2][99] = 0,
+ [1][0][2][0][RTW89_WW][0][103] = 34,
+ [1][0][2][0][RTW89_WW][1][103] = 34,
+ [1][0][2][0][RTW89_WW][2][103] = 0,
+ [1][0][2][0][RTW89_WW][0][106] = 36,
+ [1][0][2][0][RTW89_WW][1][106] = 36,
+ [1][0][2][0][RTW89_WW][2][106] = 0,
+ [1][0][2][0][RTW89_WW][0][110] = 0,
+ [1][0][2][0][RTW89_WW][1][110] = 0,
+ [1][0][2][0][RTW89_WW][2][110] = 0,
+ [1][0][2][0][RTW89_WW][0][114] = 0,
+ [1][0][2][0][RTW89_WW][1][114] = 0,
+ [1][0][2][0][RTW89_WW][2][114] = 0,
+ [1][0][2][0][RTW89_WW][0][118] = 0,
+ [1][0][2][0][RTW89_WW][1][118] = 0,
+ [1][0][2][0][RTW89_WW][2][118] = 0,
+ [1][1][2][0][RTW89_WW][0][1] = 10,
+ [1][1][2][0][RTW89_WW][1][1] = 10,
+ [1][1][2][0][RTW89_WW][2][1] = 58,
+ [1][1][2][0][RTW89_WW][0][5] = 10,
+ [1][1][2][0][RTW89_WW][1][5] = 10,
+ [1][1][2][0][RTW89_WW][2][5] = 58,
+ [1][1][2][0][RTW89_WW][0][9] = 10,
+ [1][1][2][0][RTW89_WW][1][9] = 10,
+ [1][1][2][0][RTW89_WW][2][9] = 58,
+ [1][1][2][0][RTW89_WW][0][13] = 10,
+ [1][1][2][0][RTW89_WW][1][13] = 10,
+ [1][1][2][0][RTW89_WW][2][13] = 58,
+ [1][1][2][0][RTW89_WW][0][16] = 10,
+ [1][1][2][0][RTW89_WW][1][16] = 10,
+ [1][1][2][0][RTW89_WW][2][16] = 58,
+ [1][1][2][0][RTW89_WW][0][20] = 10,
+ [1][1][2][0][RTW89_WW][1][20] = 10,
+ [1][1][2][0][RTW89_WW][2][20] = 58,
+ [1][1][2][0][RTW89_WW][0][24] = 10,
+ [1][1][2][0][RTW89_WW][1][24] = 10,
+ [1][1][2][0][RTW89_WW][2][24] = 70,
+ [1][1][2][0][RTW89_WW][0][28] = 10,
+ [1][1][2][0][RTW89_WW][1][28] = 10,
+ [1][1][2][0][RTW89_WW][2][28] = 70,
+ [1][1][2][0][RTW89_WW][0][31] = 10,
+ [1][1][2][0][RTW89_WW][1][31] = 10,
+ [1][1][2][0][RTW89_WW][2][31] = 70,
+ [1][1][2][0][RTW89_WW][0][35] = 10,
+ [1][1][2][0][RTW89_WW][1][35] = 10,
+ [1][1][2][0][RTW89_WW][2][35] = 70,
+ [1][1][2][0][RTW89_WW][0][39] = 10,
+ [1][1][2][0][RTW89_WW][1][39] = 10,
+ [1][1][2][0][RTW89_WW][2][39] = 70,
+ [1][1][2][0][RTW89_WW][0][43] = 10,
+ [1][1][2][0][RTW89_WW][1][43] = 10,
+ [1][1][2][0][RTW89_WW][2][43] = 70,
+ [1][1][2][0][RTW89_WW][0][46] = 12,
+ [1][1][2][0][RTW89_WW][1][46] = 12,
+ [1][1][2][0][RTW89_WW][2][46] = 0,
+ [1][1][2][0][RTW89_WW][0][50] = 12,
+ [1][1][2][0][RTW89_WW][1][50] = 12,
+ [1][1][2][0][RTW89_WW][2][50] = 0,
+ [1][1][2][0][RTW89_WW][0][54] = 10,
+ [1][1][2][0][RTW89_WW][1][54] = 10,
+ [1][1][2][0][RTW89_WW][2][54] = 0,
+ [1][1][2][0][RTW89_WW][0][58] = 10,
+ [1][1][2][0][RTW89_WW][1][58] = 10,
+ [1][1][2][0][RTW89_WW][2][58] = 66,
+ [1][1][2][0][RTW89_WW][0][61] = 10,
+ [1][1][2][0][RTW89_WW][1][61] = 10,
+ [1][1][2][0][RTW89_WW][2][61] = 66,
+ [1][1][2][0][RTW89_WW][0][65] = 10,
+ [1][1][2][0][RTW89_WW][1][65] = 10,
+ [1][1][2][0][RTW89_WW][2][65] = 66,
+ [1][1][2][0][RTW89_WW][0][69] = 10,
+ [1][1][2][0][RTW89_WW][1][69] = 10,
+ [1][1][2][0][RTW89_WW][2][69] = 66,
+ [1][1][2][0][RTW89_WW][0][73] = 10,
+ [1][1][2][0][RTW89_WW][1][73] = 10,
+ [1][1][2][0][RTW89_WW][2][73] = 66,
+ [1][1][2][0][RTW89_WW][0][76] = 10,
+ [1][1][2][0][RTW89_WW][1][76] = 10,
+ [1][1][2][0][RTW89_WW][2][76] = 66,
+ [1][1][2][0][RTW89_WW][0][80] = 10,
+ [1][1][2][0][RTW89_WW][1][80] = 10,
+ [1][1][2][0][RTW89_WW][2][80] = 66,
+ [1][1][2][0][RTW89_WW][0][84] = 10,
+ [1][1][2][0][RTW89_WW][1][84] = 10,
+ [1][1][2][0][RTW89_WW][2][84] = 66,
+ [1][1][2][0][RTW89_WW][0][88] = 10,
+ [1][1][2][0][RTW89_WW][1][88] = 10,
+ [1][1][2][0][RTW89_WW][2][88] = 0,
+ [1][1][2][0][RTW89_WW][0][91] = 12,
+ [1][1][2][0][RTW89_WW][1][91] = 12,
+ [1][1][2][0][RTW89_WW][2][91] = 0,
+ [1][1][2][0][RTW89_WW][0][95] = 10,
+ [1][1][2][0][RTW89_WW][1][95] = 10,
+ [1][1][2][0][RTW89_WW][2][95] = 0,
+ [1][1][2][0][RTW89_WW][0][99] = 10,
+ [1][1][2][0][RTW89_WW][1][99] = 10,
+ [1][1][2][0][RTW89_WW][2][99] = 0,
+ [1][1][2][0][RTW89_WW][0][103] = 10,
+ [1][1][2][0][RTW89_WW][1][103] = 10,
+ [1][1][2][0][RTW89_WW][2][103] = 0,
+ [1][1][2][0][RTW89_WW][0][106] = 12,
+ [1][1][2][0][RTW89_WW][1][106] = 12,
+ [1][1][2][0][RTW89_WW][2][106] = 0,
+ [1][1][2][0][RTW89_WW][0][110] = 0,
+ [1][1][2][0][RTW89_WW][1][110] = 0,
+ [1][1][2][0][RTW89_WW][2][110] = 0,
+ [1][1][2][0][RTW89_WW][0][114] = 0,
+ [1][1][2][0][RTW89_WW][1][114] = 0,
+ [1][1][2][0][RTW89_WW][2][114] = 0,
+ [1][1][2][0][RTW89_WW][0][118] = 0,
+ [1][1][2][0][RTW89_WW][1][118] = 0,
+ [1][1][2][0][RTW89_WW][2][118] = 0,
+ [1][1][2][1][RTW89_WW][0][1] = 6,
+ [1][1][2][1][RTW89_WW][1][1] = 10,
+ [1][1][2][1][RTW89_WW][2][1] = 58,
+ [1][1][2][1][RTW89_WW][0][5] = 6,
+ [1][1][2][1][RTW89_WW][1][5] = 10,
+ [1][1][2][1][RTW89_WW][2][5] = 58,
+ [1][1][2][1][RTW89_WW][0][9] = 6,
+ [1][1][2][1][RTW89_WW][1][9] = 10,
+ [1][1][2][1][RTW89_WW][2][9] = 58,
+ [1][1][2][1][RTW89_WW][0][13] = 6,
+ [1][1][2][1][RTW89_WW][1][13] = 10,
+ [1][1][2][1][RTW89_WW][2][13] = 58,
+ [1][1][2][1][RTW89_WW][0][16] = 6,
+ [1][1][2][1][RTW89_WW][1][16] = 10,
+ [1][1][2][1][RTW89_WW][2][16] = 58,
+ [1][1][2][1][RTW89_WW][0][20] = 6,
+ [1][1][2][1][RTW89_WW][1][20] = 10,
+ [1][1][2][1][RTW89_WW][2][20] = 58,
+ [1][1][2][1][RTW89_WW][0][24] = 6,
+ [1][1][2][1][RTW89_WW][1][24] = 10,
+ [1][1][2][1][RTW89_WW][2][24] = 70,
+ [1][1][2][1][RTW89_WW][0][28] = 6,
+ [1][1][2][1][RTW89_WW][1][28] = 10,
+ [1][1][2][1][RTW89_WW][2][28] = 70,
+ [1][1][2][1][RTW89_WW][0][31] = 6,
+ [1][1][2][1][RTW89_WW][1][31] = 10,
+ [1][1][2][1][RTW89_WW][2][31] = 70,
+ [1][1][2][1][RTW89_WW][0][35] = 6,
+ [1][1][2][1][RTW89_WW][1][35] = 10,
+ [1][1][2][1][RTW89_WW][2][35] = 70,
+ [1][1][2][1][RTW89_WW][0][39] = 6,
+ [1][1][2][1][RTW89_WW][1][39] = 10,
+ [1][1][2][1][RTW89_WW][2][39] = 70,
+ [1][1][2][1][RTW89_WW][0][43] = 6,
+ [1][1][2][1][RTW89_WW][1][43] = 10,
+ [1][1][2][1][RTW89_WW][2][43] = 70,
+ [1][1][2][1][RTW89_WW][0][46] = 12,
+ [1][1][2][1][RTW89_WW][1][46] = 12,
+ [1][1][2][1][RTW89_WW][2][46] = 0,
+ [1][1][2][1][RTW89_WW][0][50] = 12,
+ [1][1][2][1][RTW89_WW][1][50] = 12,
+ [1][1][2][1][RTW89_WW][2][50] = 0,
+ [1][1][2][1][RTW89_WW][0][54] = 10,
+ [1][1][2][1][RTW89_WW][1][54] = 10,
+ [1][1][2][1][RTW89_WW][2][54] = 0,
+ [1][1][2][1][RTW89_WW][0][58] = 10,
+ [1][1][2][1][RTW89_WW][1][58] = 10,
+ [1][1][2][1][RTW89_WW][2][58] = 66,
+ [1][1][2][1][RTW89_WW][0][61] = 10,
+ [1][1][2][1][RTW89_WW][1][61] = 10,
+ [1][1][2][1][RTW89_WW][2][61] = 66,
+ [1][1][2][1][RTW89_WW][0][65] = 10,
+ [1][1][2][1][RTW89_WW][1][65] = 10,
+ [1][1][2][1][RTW89_WW][2][65] = 66,
+ [1][1][2][1][RTW89_WW][0][69] = 10,
+ [1][1][2][1][RTW89_WW][1][69] = 10,
+ [1][1][2][1][RTW89_WW][2][69] = 66,
+ [1][1][2][1][RTW89_WW][0][73] = 10,
+ [1][1][2][1][RTW89_WW][1][73] = 10,
+ [1][1][2][1][RTW89_WW][2][73] = 66,
+ [1][1][2][1][RTW89_WW][0][76] = 10,
+ [1][1][2][1][RTW89_WW][1][76] = 10,
+ [1][1][2][1][RTW89_WW][2][76] = 66,
+ [1][1][2][1][RTW89_WW][0][80] = 10,
+ [1][1][2][1][RTW89_WW][1][80] = 10,
+ [1][1][2][1][RTW89_WW][2][80] = 66,
+ [1][1][2][1][RTW89_WW][0][84] = 10,
+ [1][1][2][1][RTW89_WW][1][84] = 10,
+ [1][1][2][1][RTW89_WW][2][84] = 66,
+ [1][1][2][1][RTW89_WW][0][88] = 10,
+ [1][1][2][1][RTW89_WW][1][88] = 10,
+ [1][1][2][1][RTW89_WW][2][88] = 0,
+ [1][1][2][1][RTW89_WW][0][91] = 12,
+ [1][1][2][1][RTW89_WW][1][91] = 12,
+ [1][1][2][1][RTW89_WW][2][91] = 0,
+ [1][1][2][1][RTW89_WW][0][95] = 10,
+ [1][1][2][1][RTW89_WW][1][95] = 10,
+ [1][1][2][1][RTW89_WW][2][95] = 0,
+ [1][1][2][1][RTW89_WW][0][99] = 10,
+ [1][1][2][1][RTW89_WW][1][99] = 10,
+ [1][1][2][1][RTW89_WW][2][99] = 0,
+ [1][1][2][1][RTW89_WW][0][103] = 10,
+ [1][1][2][1][RTW89_WW][1][103] = 10,
+ [1][1][2][1][RTW89_WW][2][103] = 0,
+ [1][1][2][1][RTW89_WW][0][106] = 12,
+ [1][1][2][1][RTW89_WW][1][106] = 12,
+ [1][1][2][1][RTW89_WW][2][106] = 0,
+ [1][1][2][1][RTW89_WW][0][110] = 0,
+ [1][1][2][1][RTW89_WW][1][110] = 0,
+ [1][1][2][1][RTW89_WW][2][110] = 0,
+ [1][1][2][1][RTW89_WW][0][114] = 0,
+ [1][1][2][1][RTW89_WW][1][114] = 0,
+ [1][1][2][1][RTW89_WW][2][114] = 0,
+ [1][1][2][1][RTW89_WW][0][118] = 0,
+ [1][1][2][1][RTW89_WW][1][118] = 0,
+ [1][1][2][1][RTW89_WW][2][118] = 0,
+ [2][0][2][0][RTW89_WW][0][3] = 24,
+ [2][0][2][0][RTW89_WW][1][3] = 46,
+ [2][0][2][0][RTW89_WW][2][3] = 60,
+ [2][0][2][0][RTW89_WW][0][11] = 24,
+ [2][0][2][0][RTW89_WW][1][11] = 46,
+ [2][0][2][0][RTW89_WW][2][11] = 60,
+ [2][0][2][0][RTW89_WW][0][18] = 24,
+ [2][0][2][0][RTW89_WW][1][18] = 46,
+ [2][0][2][0][RTW89_WW][2][18] = 60,
+ [2][0][2][0][RTW89_WW][0][26] = 24,
+ [2][0][2][0][RTW89_WW][1][26] = 46,
+ [2][0][2][0][RTW89_WW][2][26] = 60,
+ [2][0][2][0][RTW89_WW][0][33] = 24,
+ [2][0][2][0][RTW89_WW][1][33] = 46,
+ [2][0][2][0][RTW89_WW][2][33] = 60,
+ [2][0][2][0][RTW89_WW][0][41] = 24,
+ [2][0][2][0][RTW89_WW][1][41] = 46,
+ [2][0][2][0][RTW89_WW][2][41] = 60,
+ [2][0][2][0][RTW89_WW][0][48] = 46,
+ [2][0][2][0][RTW89_WW][1][48] = 46,
+ [2][0][2][0][RTW89_WW][2][48] = 0,
+ [2][0][2][0][RTW89_WW][0][56] = 46,
+ [2][0][2][0][RTW89_WW][1][56] = 46,
+ [2][0][2][0][RTW89_WW][2][56] = 0,
+ [2][0][2][0][RTW89_WW][0][63] = 46,
+ [2][0][2][0][RTW89_WW][1][63] = 46,
+ [2][0][2][0][RTW89_WW][2][63] = 58,
+ [2][0][2][0][RTW89_WW][0][71] = 46,
+ [2][0][2][0][RTW89_WW][1][71] = 46,
+ [2][0][2][0][RTW89_WW][2][71] = 58,
+ [2][0][2][0][RTW89_WW][0][78] = 46,
+ [2][0][2][0][RTW89_WW][1][78] = 46,
+ [2][0][2][0][RTW89_WW][2][78] = 58,
+ [2][0][2][0][RTW89_WW][0][86] = 46,
+ [2][0][2][0][RTW89_WW][1][86] = 46,
+ [2][0][2][0][RTW89_WW][2][86] = 0,
+ [2][0][2][0][RTW89_WW][0][93] = 46,
+ [2][0][2][0][RTW89_WW][1][93] = 46,
+ [2][0][2][0][RTW89_WW][2][93] = 0,
+ [2][0][2][0][RTW89_WW][0][101] = 44,
+ [2][0][2][0][RTW89_WW][1][101] = 44,
+ [2][0][2][0][RTW89_WW][2][101] = 0,
+ [2][0][2][0][RTW89_WW][0][108] = 0,
+ [2][0][2][0][RTW89_WW][1][108] = 0,
+ [2][0][2][0][RTW89_WW][2][108] = 0,
+ [2][0][2][0][RTW89_WW][0][116] = 0,
+ [2][0][2][0][RTW89_WW][1][116] = 0,
+ [2][0][2][0][RTW89_WW][2][116] = 0,
+ [2][1][2][0][RTW89_WW][0][3] = 12,
+ [2][1][2][0][RTW89_WW][1][3] = 22,
+ [2][1][2][0][RTW89_WW][2][3] = 50,
+ [2][1][2][0][RTW89_WW][0][11] = 12,
+ [2][1][2][0][RTW89_WW][1][11] = 20,
+ [2][1][2][0][RTW89_WW][2][11] = 50,
+ [2][1][2][0][RTW89_WW][0][18] = 12,
+ [2][1][2][0][RTW89_WW][1][18] = 20,
+ [2][1][2][0][RTW89_WW][2][18] = 50,
+ [2][1][2][0][RTW89_WW][0][26] = 12,
+ [2][1][2][0][RTW89_WW][1][26] = 20,
+ [2][1][2][0][RTW89_WW][2][26] = 60,
+ [2][1][2][0][RTW89_WW][0][33] = 12,
+ [2][1][2][0][RTW89_WW][1][33] = 20,
+ [2][1][2][0][RTW89_WW][2][33] = 60,
+ [2][1][2][0][RTW89_WW][0][41] = 12,
+ [2][1][2][0][RTW89_WW][1][41] = 22,
+ [2][1][2][0][RTW89_WW][2][41] = 60,
+ [2][1][2][0][RTW89_WW][0][48] = 22,
+ [2][1][2][0][RTW89_WW][1][48] = 22,
+ [2][1][2][0][RTW89_WW][2][48] = 0,
+ [2][1][2][0][RTW89_WW][0][56] = 20,
+ [2][1][2][0][RTW89_WW][1][56] = 20,
+ [2][1][2][0][RTW89_WW][2][56] = 0,
+ [2][1][2][0][RTW89_WW][0][63] = 22,
+ [2][1][2][0][RTW89_WW][1][63] = 22,
+ [2][1][2][0][RTW89_WW][2][63] = 58,
+ [2][1][2][0][RTW89_WW][0][71] = 20,
+ [2][1][2][0][RTW89_WW][1][71] = 20,
+ [2][1][2][0][RTW89_WW][2][71] = 58,
+ [2][1][2][0][RTW89_WW][0][78] = 20,
+ [2][1][2][0][RTW89_WW][1][78] = 20,
+ [2][1][2][0][RTW89_WW][2][78] = 58,
+ [2][1][2][0][RTW89_WW][0][86] = 20,
+ [2][1][2][0][RTW89_WW][1][86] = 20,
+ [2][1][2][0][RTW89_WW][2][86] = 0,
+ [2][1][2][0][RTW89_WW][0][93] = 22,
+ [2][1][2][0][RTW89_WW][1][93] = 22,
+ [2][1][2][0][RTW89_WW][2][93] = 0,
+ [2][1][2][0][RTW89_WW][0][101] = 22,
+ [2][1][2][0][RTW89_WW][1][101] = 22,
+ [2][1][2][0][RTW89_WW][2][101] = 0,
+ [2][1][2][0][RTW89_WW][0][108] = 0,
+ [2][1][2][0][RTW89_WW][1][108] = 0,
+ [2][1][2][0][RTW89_WW][2][108] = 0,
+ [2][1][2][0][RTW89_WW][0][116] = 0,
+ [2][1][2][0][RTW89_WW][1][116] = 0,
+ [2][1][2][0][RTW89_WW][2][116] = 0,
+ [2][1][2][1][RTW89_WW][0][3] = 6,
+ [2][1][2][1][RTW89_WW][1][3] = 22,
+ [2][1][2][1][RTW89_WW][2][3] = 50,
+ [2][1][2][1][RTW89_WW][0][11] = 6,
+ [2][1][2][1][RTW89_WW][1][11] = 20,
+ [2][1][2][1][RTW89_WW][2][11] = 50,
+ [2][1][2][1][RTW89_WW][0][18] = 6,
+ [2][1][2][1][RTW89_WW][1][18] = 20,
+ [2][1][2][1][RTW89_WW][2][18] = 50,
+ [2][1][2][1][RTW89_WW][0][26] = 6,
+ [2][1][2][1][RTW89_WW][1][26] = 20,
+ [2][1][2][1][RTW89_WW][2][26] = 60,
+ [2][1][2][1][RTW89_WW][0][33] = 6,
+ [2][1][2][1][RTW89_WW][1][33] = 20,
+ [2][1][2][1][RTW89_WW][2][33] = 60,
+ [2][1][2][1][RTW89_WW][0][41] = 6,
+ [2][1][2][1][RTW89_WW][1][41] = 22,
+ [2][1][2][1][RTW89_WW][2][41] = 60,
+ [2][1][2][1][RTW89_WW][0][48] = 22,
+ [2][1][2][1][RTW89_WW][1][48] = 22,
+ [2][1][2][1][RTW89_WW][2][48] = 0,
+ [2][1][2][1][RTW89_WW][0][56] = 20,
+ [2][1][2][1][RTW89_WW][1][56] = 20,
+ [2][1][2][1][RTW89_WW][2][56] = 0,
+ [2][1][2][1][RTW89_WW][0][63] = 22,
+ [2][1][2][1][RTW89_WW][1][63] = 22,
+ [2][1][2][1][RTW89_WW][2][63] = 58,
+ [2][1][2][1][RTW89_WW][0][71] = 20,
+ [2][1][2][1][RTW89_WW][1][71] = 20,
+ [2][1][2][1][RTW89_WW][2][71] = 58,
+ [2][1][2][1][RTW89_WW][0][78] = 20,
+ [2][1][2][1][RTW89_WW][1][78] = 20,
+ [2][1][2][1][RTW89_WW][2][78] = 58,
+ [2][1][2][1][RTW89_WW][0][86] = 20,
+ [2][1][2][1][RTW89_WW][1][86] = 20,
+ [2][1][2][1][RTW89_WW][2][86] = 0,
+ [2][1][2][1][RTW89_WW][0][93] = 22,
+ [2][1][2][1][RTW89_WW][1][93] = 22,
+ [2][1][2][1][RTW89_WW][2][93] = 0,
+ [2][1][2][1][RTW89_WW][0][101] = 22,
+ [2][1][2][1][RTW89_WW][1][101] = 22,
+ [2][1][2][1][RTW89_WW][2][101] = 0,
+ [2][1][2][1][RTW89_WW][0][108] = 0,
+ [2][1][2][1][RTW89_WW][1][108] = 0,
+ [2][1][2][1][RTW89_WW][2][108] = 0,
+ [2][1][2][1][RTW89_WW][0][116] = 0,
+ [2][1][2][1][RTW89_WW][1][116] = 0,
+ [2][1][2][1][RTW89_WW][2][116] = 0,
+ [3][0][2][0][RTW89_WW][0][7] = 22,
+ [3][0][2][0][RTW89_WW][1][7] = 42,
+ [3][0][2][0][RTW89_WW][2][7] = 52,
+ [3][0][2][0][RTW89_WW][0][22] = 20,
+ [3][0][2][0][RTW89_WW][1][22] = 42,
+ [3][0][2][0][RTW89_WW][2][22] = 52,
+ [3][0][2][0][RTW89_WW][0][37] = 20,
+ [3][0][2][0][RTW89_WW][1][37] = 42,
+ [3][0][2][0][RTW89_WW][2][37] = 52,
+ [3][0][2][0][RTW89_WW][0][52] = 54,
+ [3][0][2][0][RTW89_WW][1][52] = 54,
+ [3][0][2][0][RTW89_WW][2][52] = 0,
+ [3][0][2][0][RTW89_WW][0][67] = 54,
+ [3][0][2][0][RTW89_WW][1][67] = 54,
+ [3][0][2][0][RTW89_WW][2][67] = 54,
+ [3][0][2][0][RTW89_WW][0][82] = 26,
+ [3][0][2][0][RTW89_WW][1][82] = 26,
+ [3][0][2][0][RTW89_WW][2][82] = 0,
+ [3][0][2][0][RTW89_WW][0][97] = 26,
+ [3][0][2][0][RTW89_WW][1][97] = 26,
+ [3][0][2][0][RTW89_WW][2][97] = 0,
+ [3][0][2][0][RTW89_WW][0][112] = 0,
+ [3][0][2][0][RTW89_WW][1][112] = 0,
+ [3][0][2][0][RTW89_WW][2][112] = 0,
+ [3][1][2][0][RTW89_WW][0][7] = 10,
+ [3][1][2][0][RTW89_WW][1][7] = 32,
+ [3][1][2][0][RTW89_WW][2][7] = 46,
+ [3][1][2][0][RTW89_WW][0][22] = 8,
+ [3][1][2][0][RTW89_WW][1][22] = 30,
+ [3][1][2][0][RTW89_WW][2][22] = 52,
+ [3][1][2][0][RTW89_WW][0][37] = 8,
+ [3][1][2][0][RTW89_WW][1][37] = 30,
+ [3][1][2][0][RTW89_WW][2][37] = 52,
+ [3][1][2][0][RTW89_WW][0][52] = 30,
+ [3][1][2][0][RTW89_WW][1][52] = 30,
+ [3][1][2][0][RTW89_WW][2][52] = 0,
+ [3][1][2][0][RTW89_WW][0][67] = 32,
+ [3][1][2][0][RTW89_WW][1][67] = 32,
+ [3][1][2][0][RTW89_WW][2][67] = 54,
+ [3][1][2][0][RTW89_WW][0][82] = 24,
+ [3][1][2][0][RTW89_WW][1][82] = 24,
+ [3][1][2][0][RTW89_WW][2][82] = 0,
+ [3][1][2][0][RTW89_WW][0][97] = 24,
+ [3][1][2][0][RTW89_WW][1][97] = 24,
+ [3][1][2][0][RTW89_WW][2][97] = 0,
+ [3][1][2][0][RTW89_WW][0][112] = 0,
+ [3][1][2][0][RTW89_WW][1][112] = 0,
+ [3][1][2][0][RTW89_WW][2][112] = 0,
+ [3][1][2][1][RTW89_WW][0][7] = 6,
+ [3][1][2][1][RTW89_WW][1][7] = 32,
+ [3][1][2][1][RTW89_WW][2][7] = 46,
+ [3][1][2][1][RTW89_WW][0][22] = 6,
+ [3][1][2][1][RTW89_WW][1][22] = 30,
+ [3][1][2][1][RTW89_WW][2][22] = 52,
+ [3][1][2][1][RTW89_WW][0][37] = 6,
+ [3][1][2][1][RTW89_WW][1][37] = 30,
+ [3][1][2][1][RTW89_WW][2][37] = 52,
+ [3][1][2][1][RTW89_WW][0][52] = 30,
+ [3][1][2][1][RTW89_WW][1][52] = 30,
+ [3][1][2][1][RTW89_WW][2][52] = 0,
+ [3][1][2][1][RTW89_WW][0][67] = 32,
+ [3][1][2][1][RTW89_WW][1][67] = 32,
+ [3][1][2][1][RTW89_WW][2][67] = 54,
+ [3][1][2][1][RTW89_WW][0][82] = 24,
+ [3][1][2][1][RTW89_WW][1][82] = 24,
+ [3][1][2][1][RTW89_WW][2][82] = 0,
+ [3][1][2][1][RTW89_WW][0][97] = 24,
+ [3][1][2][1][RTW89_WW][1][97] = 24,
+ [3][1][2][1][RTW89_WW][2][97] = 0,
+ [3][1][2][1][RTW89_WW][0][112] = 0,
+ [3][1][2][1][RTW89_WW][1][112] = 0,
+ [3][1][2][1][RTW89_WW][2][112] = 0,
+ [0][0][1][0][RTW89_FCC][1][0] = 24,
+ [0][0][1][0][RTW89_FCC][2][0] = 56,
+ [0][0][1][0][RTW89_ETSI][1][0] = 66,
+ [0][0][1][0][RTW89_ETSI][0][0] = 28,
+ [0][0][1][0][RTW89_MKK][1][0] = 66,
+ [0][0][1][0][RTW89_MKK][0][0] = 26,
+ [0][0][1][0][RTW89_IC][1][0] = 24,
+ [0][0][1][0][RTW89_KCC][1][0] = 24,
+ [0][0][1][0][RTW89_KCC][0][0] = 24,
+ [0][0][1][0][RTW89_ACMA][1][0] = 66,
+ [0][0][1][0][RTW89_ACMA][0][0] = 28,
+ [0][0][1][0][RTW89_CHILE][1][0] = 24,
+ [0][0][1][0][RTW89_QATAR][1][0] = 66,
+ [0][0][1][0][RTW89_QATAR][0][0] = 28,
+ [0][0][1][0][RTW89_UK][1][0] = 66,
+ [0][0][1][0][RTW89_UK][0][0] = 28,
+ [0][0][1][0][RTW89_FCC][1][2] = 22,
+ [0][0][1][0][RTW89_FCC][2][2] = 56,
+ [0][0][1][0][RTW89_ETSI][1][2] = 66,
+ [0][0][1][0][RTW89_ETSI][0][2] = 28,
+ [0][0][1][0][RTW89_MKK][1][2] = 66,
+ [0][0][1][0][RTW89_MKK][0][2] = 26,
+ [0][0][1][0][RTW89_IC][1][2] = 22,
+ [0][0][1][0][RTW89_KCC][1][2] = 24,
+ [0][0][1][0][RTW89_KCC][0][2] = 24,
+ [0][0][1][0][RTW89_ACMA][1][2] = 66,
+ [0][0][1][0][RTW89_ACMA][0][2] = 28,
+ [0][0][1][0][RTW89_CHILE][1][2] = 22,
+ [0][0][1][0][RTW89_QATAR][1][2] = 66,
+ [0][0][1][0][RTW89_QATAR][0][2] = 28,
+ [0][0][1][0][RTW89_UK][1][2] = 66,
+ [0][0][1][0][RTW89_UK][0][2] = 28,
+ [0][0][1][0][RTW89_FCC][1][4] = 22,
+ [0][0][1][0][RTW89_FCC][2][4] = 56,
+ [0][0][1][0][RTW89_ETSI][1][4] = 66,
+ [0][0][1][0][RTW89_ETSI][0][4] = 28,
+ [0][0][1][0][RTW89_MKK][1][4] = 66,
+ [0][0][1][0][RTW89_MKK][0][4] = 26,
+ [0][0][1][0][RTW89_IC][1][4] = 22,
+ [0][0][1][0][RTW89_KCC][1][4] = 24,
+ [0][0][1][0][RTW89_KCC][0][4] = 24,
+ [0][0][1][0][RTW89_ACMA][1][4] = 66,
+ [0][0][1][0][RTW89_ACMA][0][4] = 28,
+ [0][0][1][0][RTW89_CHILE][1][4] = 22,
+ [0][0][1][0][RTW89_QATAR][1][4] = 66,
+ [0][0][1][0][RTW89_QATAR][0][4] = 28,
+ [0][0][1][0][RTW89_UK][1][4] = 66,
+ [0][0][1][0][RTW89_UK][0][4] = 28,
+ [0][0][1][0][RTW89_FCC][1][6] = 22,
+ [0][0][1][0][RTW89_FCC][2][6] = 56,
+ [0][0][1][0][RTW89_ETSI][1][6] = 66,
+ [0][0][1][0][RTW89_ETSI][0][6] = 28,
+ [0][0][1][0][RTW89_MKK][1][6] = 66,
+ [0][0][1][0][RTW89_MKK][0][6] = 26,
+ [0][0][1][0][RTW89_IC][1][6] = 22,
+ [0][0][1][0][RTW89_KCC][1][6] = 24,
+ [0][0][1][0][RTW89_KCC][0][6] = 24,
+ [0][0][1][0][RTW89_ACMA][1][6] = 66,
+ [0][0][1][0][RTW89_ACMA][0][6] = 28,
+ [0][0][1][0][RTW89_CHILE][1][6] = 22,
+ [0][0][1][0][RTW89_QATAR][1][6] = 66,
+ [0][0][1][0][RTW89_QATAR][0][6] = 28,
+ [0][0][1][0][RTW89_UK][1][6] = 66,
+ [0][0][1][0][RTW89_UK][0][6] = 28,
+ [0][0][1][0][RTW89_FCC][1][8] = 22,
+ [0][0][1][0][RTW89_FCC][2][8] = 56,
+ [0][0][1][0][RTW89_ETSI][1][8] = 66,
+ [0][0][1][0][RTW89_ETSI][0][8] = 28,
+ [0][0][1][0][RTW89_MKK][1][8] = 66,
+ [0][0][1][0][RTW89_MKK][0][8] = 26,
+ [0][0][1][0][RTW89_IC][1][8] = 22,
+ [0][0][1][0][RTW89_KCC][1][8] = 24,
+ [0][0][1][0][RTW89_KCC][0][8] = 24,
+ [0][0][1][0][RTW89_ACMA][1][8] = 66,
+ [0][0][1][0][RTW89_ACMA][0][8] = 28,
+ [0][0][1][0][RTW89_CHILE][1][8] = 22,
+ [0][0][1][0][RTW89_QATAR][1][8] = 66,
+ [0][0][1][0][RTW89_QATAR][0][8] = 28,
+ [0][0][1][0][RTW89_UK][1][8] = 66,
+ [0][0][1][0][RTW89_UK][0][8] = 28,
+ [0][0][1][0][RTW89_FCC][1][10] = 22,
+ [0][0][1][0][RTW89_FCC][2][10] = 56,
+ [0][0][1][0][RTW89_ETSI][1][10] = 66,
+ [0][0][1][0][RTW89_ETSI][0][10] = 28,
+ [0][0][1][0][RTW89_MKK][1][10] = 66,
+ [0][0][1][0][RTW89_MKK][0][10] = 26,
+ [0][0][1][0][RTW89_IC][1][10] = 22,
+ [0][0][1][0][RTW89_KCC][1][10] = 24,
+ [0][0][1][0][RTW89_KCC][0][10] = 24,
+ [0][0][1][0][RTW89_ACMA][1][10] = 66,
+ [0][0][1][0][RTW89_ACMA][0][10] = 28,
+ [0][0][1][0][RTW89_CHILE][1][10] = 22,
+ [0][0][1][0][RTW89_QATAR][1][10] = 66,
+ [0][0][1][0][RTW89_QATAR][0][10] = 28,
+ [0][0][1][0][RTW89_UK][1][10] = 66,
+ [0][0][1][0][RTW89_UK][0][10] = 28,
+ [0][0][1][0][RTW89_FCC][1][12] = 22,
+ [0][0][1][0][RTW89_FCC][2][12] = 56,
+ [0][0][1][0][RTW89_ETSI][1][12] = 66,
+ [0][0][1][0][RTW89_ETSI][0][12] = 28,
+ [0][0][1][0][RTW89_MKK][1][12] = 66,
+ [0][0][1][0][RTW89_MKK][0][12] = 26,
+ [0][0][1][0][RTW89_IC][1][12] = 22,
+ [0][0][1][0][RTW89_KCC][1][12] = 24,
+ [0][0][1][0][RTW89_KCC][0][12] = 24,
+ [0][0][1][0][RTW89_ACMA][1][12] = 66,
+ [0][0][1][0][RTW89_ACMA][0][12] = 28,
+ [0][0][1][0][RTW89_CHILE][1][12] = 22,
+ [0][0][1][0][RTW89_QATAR][1][12] = 66,
+ [0][0][1][0][RTW89_QATAR][0][12] = 28,
+ [0][0][1][0][RTW89_UK][1][12] = 66,
+ [0][0][1][0][RTW89_UK][0][12] = 28,
+ [0][0][1][0][RTW89_FCC][1][14] = 22,
+ [0][0][1][0][RTW89_FCC][2][14] = 56,
+ [0][0][1][0][RTW89_ETSI][1][14] = 66,
+ [0][0][1][0][RTW89_ETSI][0][14] = 28,
+ [0][0][1][0][RTW89_MKK][1][14] = 66,
+ [0][0][1][0][RTW89_MKK][0][14] = 26,
+ [0][0][1][0][RTW89_IC][1][14] = 22,
+ [0][0][1][0][RTW89_KCC][1][14] = 24,
+ [0][0][1][0][RTW89_KCC][0][14] = 24,
+ [0][0][1][0][RTW89_ACMA][1][14] = 66,
+ [0][0][1][0][RTW89_ACMA][0][14] = 28,
+ [0][0][1][0][RTW89_CHILE][1][14] = 22,
+ [0][0][1][0][RTW89_QATAR][1][14] = 66,
+ [0][0][1][0][RTW89_QATAR][0][14] = 28,
+ [0][0][1][0][RTW89_UK][1][14] = 66,
+ [0][0][1][0][RTW89_UK][0][14] = 28,
+ [0][0][1][0][RTW89_FCC][1][15] = 22,
+ [0][0][1][0][RTW89_FCC][2][15] = 56,
+ [0][0][1][0][RTW89_ETSI][1][15] = 66,
+ [0][0][1][0][RTW89_ETSI][0][15] = 28,
+ [0][0][1][0][RTW89_MKK][1][15] = 66,
+ [0][0][1][0][RTW89_MKK][0][15] = 26,
+ [0][0][1][0][RTW89_IC][1][15] = 22,
+ [0][0][1][0][RTW89_KCC][1][15] = 24,
+ [0][0][1][0][RTW89_KCC][0][15] = 24,
+ [0][0][1][0][RTW89_ACMA][1][15] = 66,
+ [0][0][1][0][RTW89_ACMA][0][15] = 28,
+ [0][0][1][0][RTW89_CHILE][1][15] = 22,
+ [0][0][1][0][RTW89_QATAR][1][15] = 66,
+ [0][0][1][0][RTW89_QATAR][0][15] = 28,
+ [0][0][1][0][RTW89_UK][1][15] = 66,
+ [0][0][1][0][RTW89_UK][0][15] = 28,
+ [0][0][1][0][RTW89_FCC][1][17] = 22,
+ [0][0][1][0][RTW89_FCC][2][17] = 56,
+ [0][0][1][0][RTW89_ETSI][1][17] = 66,
+ [0][0][1][0][RTW89_ETSI][0][17] = 28,
+ [0][0][1][0][RTW89_MKK][1][17] = 66,
+ [0][0][1][0][RTW89_MKK][0][17] = 26,
+ [0][0][1][0][RTW89_IC][1][17] = 22,
+ [0][0][1][0][RTW89_KCC][1][17] = 24,
+ [0][0][1][0][RTW89_KCC][0][17] = 24,
+ [0][0][1][0][RTW89_ACMA][1][17] = 66,
+ [0][0][1][0][RTW89_ACMA][0][17] = 28,
+ [0][0][1][0][RTW89_CHILE][1][17] = 22,
+ [0][0][1][0][RTW89_QATAR][1][17] = 66,
+ [0][0][1][0][RTW89_QATAR][0][17] = 28,
+ [0][0][1][0][RTW89_UK][1][17] = 66,
+ [0][0][1][0][RTW89_UK][0][17] = 28,
+ [0][0][1][0][RTW89_FCC][1][19] = 22,
+ [0][0][1][0][RTW89_FCC][2][19] = 56,
+ [0][0][1][0][RTW89_ETSI][1][19] = 66,
+ [0][0][1][0][RTW89_ETSI][0][19] = 28,
+ [0][0][1][0][RTW89_MKK][1][19] = 66,
+ [0][0][1][0][RTW89_MKK][0][19] = 26,
+ [0][0][1][0][RTW89_IC][1][19] = 22,
+ [0][0][1][0][RTW89_KCC][1][19] = 24,
+ [0][0][1][0][RTW89_KCC][0][19] = 24,
+ [0][0][1][0][RTW89_ACMA][1][19] = 66,
+ [0][0][1][0][RTW89_ACMA][0][19] = 28,
+ [0][0][1][0][RTW89_CHILE][1][19] = 22,
+ [0][0][1][0][RTW89_QATAR][1][19] = 66,
+ [0][0][1][0][RTW89_QATAR][0][19] = 28,
+ [0][0][1][0][RTW89_UK][1][19] = 66,
+ [0][0][1][0][RTW89_UK][0][19] = 28,
+ [0][0][1][0][RTW89_FCC][1][21] = 22,
+ [0][0][1][0][RTW89_FCC][2][21] = 56,
+ [0][0][1][0][RTW89_ETSI][1][21] = 66,
+ [0][0][1][0][RTW89_ETSI][0][21] = 28,
+ [0][0][1][0][RTW89_MKK][1][21] = 66,
+ [0][0][1][0][RTW89_MKK][0][21] = 26,
+ [0][0][1][0][RTW89_IC][1][21] = 22,
+ [0][0][1][0][RTW89_KCC][1][21] = 24,
+ [0][0][1][0][RTW89_KCC][0][21] = 24,
+ [0][0][1][0][RTW89_ACMA][1][21] = 66,
+ [0][0][1][0][RTW89_ACMA][0][21] = 28,
+ [0][0][1][0][RTW89_CHILE][1][21] = 22,
+ [0][0][1][0][RTW89_QATAR][1][21] = 66,
+ [0][0][1][0][RTW89_QATAR][0][21] = 28,
+ [0][0][1][0][RTW89_UK][1][21] = 66,
+ [0][0][1][0][RTW89_UK][0][21] = 28,
+ [0][0][1][0][RTW89_FCC][1][23] = 22,
+ [0][0][1][0][RTW89_FCC][2][23] = 70,
+ [0][0][1][0][RTW89_ETSI][1][23] = 66,
+ [0][0][1][0][RTW89_ETSI][0][23] = 28,
+ [0][0][1][0][RTW89_MKK][1][23] = 66,
+ [0][0][1][0][RTW89_MKK][0][23] = 26,
+ [0][0][1][0][RTW89_IC][1][23] = 22,
+ [0][0][1][0][RTW89_KCC][1][23] = 24,
+ [0][0][1][0][RTW89_KCC][0][23] = 26,
+ [0][0][1][0][RTW89_ACMA][1][23] = 66,
+ [0][0][1][0][RTW89_ACMA][0][23] = 28,
+ [0][0][1][0][RTW89_CHILE][1][23] = 22,
+ [0][0][1][0][RTW89_QATAR][1][23] = 66,
+ [0][0][1][0][RTW89_QATAR][0][23] = 28,
+ [0][0][1][0][RTW89_UK][1][23] = 66,
+ [0][0][1][0][RTW89_UK][0][23] = 28,
+ [0][0][1][0][RTW89_FCC][1][25] = 22,
+ [0][0][1][0][RTW89_FCC][2][25] = 70,
+ [0][0][1][0][RTW89_ETSI][1][25] = 66,
+ [0][0][1][0][RTW89_ETSI][0][25] = 28,
+ [0][0][1][0][RTW89_MKK][1][25] = 66,
+ [0][0][1][0][RTW89_MKK][0][25] = 26,
+ [0][0][1][0][RTW89_IC][1][25] = 22,
+ [0][0][1][0][RTW89_KCC][1][25] = 24,
+ [0][0][1][0][RTW89_KCC][0][25] = 26,
+ [0][0][1][0][RTW89_ACMA][1][25] = 66,
+ [0][0][1][0][RTW89_ACMA][0][25] = 28,
+ [0][0][1][0][RTW89_CHILE][1][25] = 22,
+ [0][0][1][0][RTW89_QATAR][1][25] = 66,
+ [0][0][1][0][RTW89_QATAR][0][25] = 28,
+ [0][0][1][0][RTW89_UK][1][25] = 66,
+ [0][0][1][0][RTW89_UK][0][25] = 28,
+ [0][0][1][0][RTW89_FCC][1][27] = 22,
+ [0][0][1][0][RTW89_FCC][2][27] = 70,
+ [0][0][1][0][RTW89_ETSI][1][27] = 66,
+ [0][0][1][0][RTW89_ETSI][0][27] = 28,
+ [0][0][1][0][RTW89_MKK][1][27] = 66,
+ [0][0][1][0][RTW89_MKK][0][27] = 26,
+ [0][0][1][0][RTW89_IC][1][27] = 22,
+ [0][0][1][0][RTW89_KCC][1][27] = 24,
+ [0][0][1][0][RTW89_KCC][0][27] = 26,
+ [0][0][1][0][RTW89_ACMA][1][27] = 66,
+ [0][0][1][0][RTW89_ACMA][0][27] = 28,
+ [0][0][1][0][RTW89_CHILE][1][27] = 22,
+ [0][0][1][0][RTW89_QATAR][1][27] = 66,
+ [0][0][1][0][RTW89_QATAR][0][27] = 28,
+ [0][0][1][0][RTW89_UK][1][27] = 66,
+ [0][0][1][0][RTW89_UK][0][27] = 28,
+ [0][0][1][0][RTW89_FCC][1][29] = 22,
+ [0][0][1][0][RTW89_FCC][2][29] = 70,
+ [0][0][1][0][RTW89_ETSI][1][29] = 66,
+ [0][0][1][0][RTW89_ETSI][0][29] = 28,
+ [0][0][1][0][RTW89_MKK][1][29] = 66,
+ [0][0][1][0][RTW89_MKK][0][29] = 26,
+ [0][0][1][0][RTW89_IC][1][29] = 22,
+ [0][0][1][0][RTW89_KCC][1][29] = 24,
+ [0][0][1][0][RTW89_KCC][0][29] = 26,
+ [0][0][1][0][RTW89_ACMA][1][29] = 66,
+ [0][0][1][0][RTW89_ACMA][0][29] = 28,
+ [0][0][1][0][RTW89_CHILE][1][29] = 22,
+ [0][0][1][0][RTW89_QATAR][1][29] = 66,
+ [0][0][1][0][RTW89_QATAR][0][29] = 28,
+ [0][0][1][0][RTW89_UK][1][29] = 66,
+ [0][0][1][0][RTW89_UK][0][29] = 28,
+ [0][0][1][0][RTW89_FCC][1][30] = 22,
+ [0][0][1][0][RTW89_FCC][2][30] = 70,
+ [0][0][1][0][RTW89_ETSI][1][30] = 66,
+ [0][0][1][0][RTW89_ETSI][0][30] = 28,
+ [0][0][1][0][RTW89_MKK][1][30] = 66,
+ [0][0][1][0][RTW89_MKK][0][30] = 26,
+ [0][0][1][0][RTW89_IC][1][30] = 22,
+ [0][0][1][0][RTW89_KCC][1][30] = 24,
+ [0][0][1][0][RTW89_KCC][0][30] = 26,
+ [0][0][1][0][RTW89_ACMA][1][30] = 66,
+ [0][0][1][0][RTW89_ACMA][0][30] = 28,
+ [0][0][1][0][RTW89_CHILE][1][30] = 22,
+ [0][0][1][0][RTW89_QATAR][1][30] = 66,
+ [0][0][1][0][RTW89_QATAR][0][30] = 28,
+ [0][0][1][0][RTW89_UK][1][30] = 66,
+ [0][0][1][0][RTW89_UK][0][30] = 28,
+ [0][0][1][0][RTW89_FCC][1][32] = 22,
+ [0][0][1][0][RTW89_FCC][2][32] = 70,
+ [0][0][1][0][RTW89_ETSI][1][32] = 66,
+ [0][0][1][0][RTW89_ETSI][0][32] = 28,
+ [0][0][1][0][RTW89_MKK][1][32] = 66,
+ [0][0][1][0][RTW89_MKK][0][32] = 26,
+ [0][0][1][0][RTW89_IC][1][32] = 22,
+ [0][0][1][0][RTW89_KCC][1][32] = 24,
+ [0][0][1][0][RTW89_KCC][0][32] = 26,
+ [0][0][1][0][RTW89_ACMA][1][32] = 66,
+ [0][0][1][0][RTW89_ACMA][0][32] = 28,
+ [0][0][1][0][RTW89_CHILE][1][32] = 22,
+ [0][0][1][0][RTW89_QATAR][1][32] = 66,
+ [0][0][1][0][RTW89_QATAR][0][32] = 28,
+ [0][0][1][0][RTW89_UK][1][32] = 66,
+ [0][0][1][0][RTW89_UK][0][32] = 28,
+ [0][0][1][0][RTW89_FCC][1][34] = 22,
+ [0][0][1][0][RTW89_FCC][2][34] = 70,
+ [0][0][1][0][RTW89_ETSI][1][34] = 66,
+ [0][0][1][0][RTW89_ETSI][0][34] = 28,
+ [0][0][1][0][RTW89_MKK][1][34] = 66,
+ [0][0][1][0][RTW89_MKK][0][34] = 26,
+ [0][0][1][0][RTW89_IC][1][34] = 22,
+ [0][0][1][0][RTW89_KCC][1][34] = 24,
+ [0][0][1][0][RTW89_KCC][0][34] = 26,
+ [0][0][1][0][RTW89_ACMA][1][34] = 66,
+ [0][0][1][0][RTW89_ACMA][0][34] = 28,
+ [0][0][1][0][RTW89_CHILE][1][34] = 22,
+ [0][0][1][0][RTW89_QATAR][1][34] = 66,
+ [0][0][1][0][RTW89_QATAR][0][34] = 28,
+ [0][0][1][0][RTW89_UK][1][34] = 66,
+ [0][0][1][0][RTW89_UK][0][34] = 28,
+ [0][0][1][0][RTW89_FCC][1][36] = 22,
+ [0][0][1][0][RTW89_FCC][2][36] = 70,
+ [0][0][1][0][RTW89_ETSI][1][36] = 66,
+ [0][0][1][0][RTW89_ETSI][0][36] = 28,
+ [0][0][1][0][RTW89_MKK][1][36] = 66,
+ [0][0][1][0][RTW89_MKK][0][36] = 26,
+ [0][0][1][0][RTW89_IC][1][36] = 22,
+ [0][0][1][0][RTW89_KCC][1][36] = 24,
+ [0][0][1][0][RTW89_KCC][0][36] = 26,
+ [0][0][1][0][RTW89_ACMA][1][36] = 66,
+ [0][0][1][0][RTW89_ACMA][0][36] = 28,
+ [0][0][1][0][RTW89_CHILE][1][36] = 22,
+ [0][0][1][0][RTW89_QATAR][1][36] = 66,
+ [0][0][1][0][RTW89_QATAR][0][36] = 28,
+ [0][0][1][0][RTW89_UK][1][36] = 66,
+ [0][0][1][0][RTW89_UK][0][36] = 28,
+ [0][0][1][0][RTW89_FCC][1][38] = 22,
+ [0][0][1][0][RTW89_FCC][2][38] = 70,
+ [0][0][1][0][RTW89_ETSI][1][38] = 66,
+ [0][0][1][0][RTW89_ETSI][0][38] = 28,
+ [0][0][1][0][RTW89_MKK][1][38] = 66,
+ [0][0][1][0][RTW89_MKK][0][38] = 26,
+ [0][0][1][0][RTW89_IC][1][38] = 22,
+ [0][0][1][0][RTW89_KCC][1][38] = 24,
+ [0][0][1][0][RTW89_KCC][0][38] = 26,
+ [0][0][1][0][RTW89_ACMA][1][38] = 66,
+ [0][0][1][0][RTW89_ACMA][0][38] = 28,
+ [0][0][1][0][RTW89_CHILE][1][38] = 22,
+ [0][0][1][0][RTW89_QATAR][1][38] = 66,
+ [0][0][1][0][RTW89_QATAR][0][38] = 28,
+ [0][0][1][0][RTW89_UK][1][38] = 66,
+ [0][0][1][0][RTW89_UK][0][38] = 28,
+ [0][0][1][0][RTW89_FCC][1][40] = 22,
+ [0][0][1][0][RTW89_FCC][2][40] = 70,
+ [0][0][1][0][RTW89_ETSI][1][40] = 66,
+ [0][0][1][0][RTW89_ETSI][0][40] = 28,
+ [0][0][1][0][RTW89_MKK][1][40] = 66,
+ [0][0][1][0][RTW89_MKK][0][40] = 26,
+ [0][0][1][0][RTW89_IC][1][40] = 22,
+ [0][0][1][0][RTW89_KCC][1][40] = 24,
+ [0][0][1][0][RTW89_KCC][0][40] = 26,
+ [0][0][1][0][RTW89_ACMA][1][40] = 66,
+ [0][0][1][0][RTW89_ACMA][0][40] = 28,
+ [0][0][1][0][RTW89_CHILE][1][40] = 22,
+ [0][0][1][0][RTW89_QATAR][1][40] = 66,
+ [0][0][1][0][RTW89_QATAR][0][40] = 28,
+ [0][0][1][0][RTW89_UK][1][40] = 66,
+ [0][0][1][0][RTW89_UK][0][40] = 28,
+ [0][0][1][0][RTW89_FCC][1][42] = 22,
+ [0][0][1][0][RTW89_FCC][2][42] = 70,
+ [0][0][1][0][RTW89_ETSI][1][42] = 66,
+ [0][0][1][0][RTW89_ETSI][0][42] = 28,
+ [0][0][1][0][RTW89_MKK][1][42] = 66,
+ [0][0][1][0][RTW89_MKK][0][42] = 26,
+ [0][0][1][0][RTW89_IC][1][42] = 22,
+ [0][0][1][0][RTW89_KCC][1][42] = 24,
+ [0][0][1][0][RTW89_KCC][0][42] = 26,
+ [0][0][1][0][RTW89_ACMA][1][42] = 66,
+ [0][0][1][0][RTW89_ACMA][0][42] = 28,
+ [0][0][1][0][RTW89_CHILE][1][42] = 22,
+ [0][0][1][0][RTW89_QATAR][1][42] = 66,
+ [0][0][1][0][RTW89_QATAR][0][42] = 28,
+ [0][0][1][0][RTW89_UK][1][42] = 66,
+ [0][0][1][0][RTW89_UK][0][42] = 28,
+ [0][0][1][0][RTW89_FCC][1][44] = 22,
+ [0][0][1][0][RTW89_FCC][2][44] = 70,
+ [0][0][1][0][RTW89_ETSI][1][44] = 66,
+ [0][0][1][0][RTW89_ETSI][0][44] = 30,
+ [0][0][1][0][RTW89_MKK][1][44] = 44,
+ [0][0][1][0][RTW89_MKK][0][44] = 28,
+ [0][0][1][0][RTW89_IC][1][44] = 22,
+ [0][0][1][0][RTW89_KCC][1][44] = 24,
+ [0][0][1][0][RTW89_KCC][0][44] = 26,
+ [0][0][1][0][RTW89_ACMA][1][44] = 66,
+ [0][0][1][0][RTW89_ACMA][0][44] = 30,
+ [0][0][1][0][RTW89_CHILE][1][44] = 22,
+ [0][0][1][0][RTW89_QATAR][1][44] = 66,
+ [0][0][1][0][RTW89_QATAR][0][44] = 30,
+ [0][0][1][0][RTW89_UK][1][44] = 66,
+ [0][0][1][0][RTW89_UK][0][44] = 30,
+ [0][0][1][0][RTW89_FCC][1][45] = 22,
+ [0][0][1][0][RTW89_FCC][2][45] = 127,
+ [0][0][1][0][RTW89_ETSI][1][45] = 127,
+ [0][0][1][0][RTW89_ETSI][0][45] = 127,
+ [0][0][1][0][RTW89_MKK][1][45] = 127,
+ [0][0][1][0][RTW89_MKK][0][45] = 127,
+ [0][0][1][0][RTW89_IC][1][45] = 22,
+ [0][0][1][0][RTW89_KCC][1][45] = 24,
+ [0][0][1][0][RTW89_KCC][0][45] = 127,
+ [0][0][1][0][RTW89_ACMA][1][45] = 127,
+ [0][0][1][0][RTW89_ACMA][0][45] = 127,
+ [0][0][1][0][RTW89_CHILE][1][45] = 22,
+ [0][0][1][0][RTW89_QATAR][1][45] = 127,
+ [0][0][1][0][RTW89_QATAR][0][45] = 127,
+ [0][0][1][0][RTW89_UK][1][45] = 127,
+ [0][0][1][0][RTW89_UK][0][45] = 127,
+ [0][0][1][0][RTW89_FCC][1][47] = 22,
+ [0][0][1][0][RTW89_FCC][2][47] = 127,
+ [0][0][1][0][RTW89_ETSI][1][47] = 127,
+ [0][0][1][0][RTW89_ETSI][0][47] = 127,
+ [0][0][1][0][RTW89_MKK][1][47] = 127,
+ [0][0][1][0][RTW89_MKK][0][47] = 127,
+ [0][0][1][0][RTW89_IC][1][47] = 22,
+ [0][0][1][0][RTW89_KCC][1][47] = 24,
+ [0][0][1][0][RTW89_KCC][0][47] = 127,
+ [0][0][1][0][RTW89_ACMA][1][47] = 127,
+ [0][0][1][0][RTW89_ACMA][0][47] = 127,
+ [0][0][1][0][RTW89_CHILE][1][47] = 22,
+ [0][0][1][0][RTW89_QATAR][1][47] = 127,
+ [0][0][1][0][RTW89_QATAR][0][47] = 127,
+ [0][0][1][0][RTW89_UK][1][47] = 127,
+ [0][0][1][0][RTW89_UK][0][47] = 127,
+ [0][0][1][0][RTW89_FCC][1][49] = 24,
+ [0][0][1][0][RTW89_FCC][2][49] = 127,
+ [0][0][1][0][RTW89_ETSI][1][49] = 127,
+ [0][0][1][0][RTW89_ETSI][0][49] = 127,
+ [0][0][1][0][RTW89_MKK][1][49] = 127,
+ [0][0][1][0][RTW89_MKK][0][49] = 127,
+ [0][0][1][0][RTW89_IC][1][49] = 24,
+ [0][0][1][0][RTW89_KCC][1][49] = 24,
+ [0][0][1][0][RTW89_KCC][0][49] = 127,
+ [0][0][1][0][RTW89_ACMA][1][49] = 127,
+ [0][0][1][0][RTW89_ACMA][0][49] = 127,
+ [0][0][1][0][RTW89_CHILE][1][49] = 24,
+ [0][0][1][0][RTW89_QATAR][1][49] = 127,
+ [0][0][1][0][RTW89_QATAR][0][49] = 127,
+ [0][0][1][0][RTW89_UK][1][49] = 127,
+ [0][0][1][0][RTW89_UK][0][49] = 127,
+ [0][0][1][0][RTW89_FCC][1][51] = 22,
+ [0][0][1][0][RTW89_FCC][2][51] = 127,
+ [0][0][1][0][RTW89_ETSI][1][51] = 127,
+ [0][0][1][0][RTW89_ETSI][0][51] = 127,
+ [0][0][1][0][RTW89_MKK][1][51] = 127,
+ [0][0][1][0][RTW89_MKK][0][51] = 127,
+ [0][0][1][0][RTW89_IC][1][51] = 22,
+ [0][0][1][0][RTW89_KCC][1][51] = 24,
+ [0][0][1][0][RTW89_KCC][0][51] = 127,
+ [0][0][1][0][RTW89_ACMA][1][51] = 127,
+ [0][0][1][0][RTW89_ACMA][0][51] = 127,
+ [0][0][1][0][RTW89_CHILE][1][51] = 22,
+ [0][0][1][0][RTW89_QATAR][1][51] = 127,
+ [0][0][1][0][RTW89_QATAR][0][51] = 127,
+ [0][0][1][0][RTW89_UK][1][51] = 127,
+ [0][0][1][0][RTW89_UK][0][51] = 127,
+ [0][0][1][0][RTW89_FCC][1][53] = 22,
+ [0][0][1][0][RTW89_FCC][2][53] = 127,
+ [0][0][1][0][RTW89_ETSI][1][53] = 127,
+ [0][0][1][0][RTW89_ETSI][0][53] = 127,
+ [0][0][1][0][RTW89_MKK][1][53] = 127,
+ [0][0][1][0][RTW89_MKK][0][53] = 127,
+ [0][0][1][0][RTW89_IC][1][53] = 22,
+ [0][0][1][0][RTW89_KCC][1][53] = 24,
+ [0][0][1][0][RTW89_KCC][0][53] = 127,
+ [0][0][1][0][RTW89_ACMA][1][53] = 127,
+ [0][0][1][0][RTW89_ACMA][0][53] = 127,
+ [0][0][1][0][RTW89_CHILE][1][53] = 22,
+ [0][0][1][0][RTW89_QATAR][1][53] = 127,
+ [0][0][1][0][RTW89_QATAR][0][53] = 127,
+ [0][0][1][0][RTW89_UK][1][53] = 127,
+ [0][0][1][0][RTW89_UK][0][53] = 127,
+ [0][0][1][0][RTW89_FCC][1][55] = 22,
+ [0][0][1][0][RTW89_FCC][2][55] = 68,
+ [0][0][1][0][RTW89_ETSI][1][55] = 127,
+ [0][0][1][0][RTW89_ETSI][0][55] = 127,
+ [0][0][1][0][RTW89_MKK][1][55] = 127,
+ [0][0][1][0][RTW89_MKK][0][55] = 127,
+ [0][0][1][0][RTW89_IC][1][55] = 22,
+ [0][0][1][0][RTW89_KCC][1][55] = 26,
+ [0][0][1][0][RTW89_KCC][0][55] = 127,
+ [0][0][1][0][RTW89_ACMA][1][55] = 127,
+ [0][0][1][0][RTW89_ACMA][0][55] = 127,
+ [0][0][1][0][RTW89_CHILE][1][55] = 22,
+ [0][0][1][0][RTW89_QATAR][1][55] = 127,
+ [0][0][1][0][RTW89_QATAR][0][55] = 127,
+ [0][0][1][0][RTW89_UK][1][55] = 127,
+ [0][0][1][0][RTW89_UK][0][55] = 127,
+ [0][0][1][0][RTW89_FCC][1][57] = 22,
+ [0][0][1][0][RTW89_FCC][2][57] = 68,
+ [0][0][1][0][RTW89_ETSI][1][57] = 127,
+ [0][0][1][0][RTW89_ETSI][0][57] = 127,
+ [0][0][1][0][RTW89_MKK][1][57] = 127,
+ [0][0][1][0][RTW89_MKK][0][57] = 127,
+ [0][0][1][0][RTW89_IC][1][57] = 22,
+ [0][0][1][0][RTW89_KCC][1][57] = 26,
+ [0][0][1][0][RTW89_KCC][0][57] = 127,
+ [0][0][1][0][RTW89_ACMA][1][57] = 127,
+ [0][0][1][0][RTW89_ACMA][0][57] = 127,
+ [0][0][1][0][RTW89_CHILE][1][57] = 22,
+ [0][0][1][0][RTW89_QATAR][1][57] = 127,
+ [0][0][1][0][RTW89_QATAR][0][57] = 127,
+ [0][0][1][0][RTW89_UK][1][57] = 127,
+ [0][0][1][0][RTW89_UK][0][57] = 127,
+ [0][0][1][0][RTW89_FCC][1][59] = 22,
+ [0][0][1][0][RTW89_FCC][2][59] = 68,
+ [0][0][1][0][RTW89_ETSI][1][59] = 127,
+ [0][0][1][0][RTW89_ETSI][0][59] = 127,
+ [0][0][1][0][RTW89_MKK][1][59] = 127,
+ [0][0][1][0][RTW89_MKK][0][59] = 127,
+ [0][0][1][0][RTW89_IC][1][59] = 22,
+ [0][0][1][0][RTW89_KCC][1][59] = 26,
+ [0][0][1][0][RTW89_KCC][0][59] = 127,
+ [0][0][1][0][RTW89_ACMA][1][59] = 127,
+ [0][0][1][0][RTW89_ACMA][0][59] = 127,
+ [0][0][1][0][RTW89_CHILE][1][59] = 22,
+ [0][0][1][0][RTW89_QATAR][1][59] = 127,
+ [0][0][1][0][RTW89_QATAR][0][59] = 127,
+ [0][0][1][0][RTW89_UK][1][59] = 127,
+ [0][0][1][0][RTW89_UK][0][59] = 127,
+ [0][0][1][0][RTW89_FCC][1][60] = 22,
+ [0][0][1][0][RTW89_FCC][2][60] = 68,
+ [0][0][1][0][RTW89_ETSI][1][60] = 127,
+ [0][0][1][0][RTW89_ETSI][0][60] = 127,
+ [0][0][1][0][RTW89_MKK][1][60] = 127,
+ [0][0][1][0][RTW89_MKK][0][60] = 127,
+ [0][0][1][0][RTW89_IC][1][60] = 22,
+ [0][0][1][0][RTW89_KCC][1][60] = 26,
+ [0][0][1][0][RTW89_KCC][0][60] = 127,
+ [0][0][1][0][RTW89_ACMA][1][60] = 127,
+ [0][0][1][0][RTW89_ACMA][0][60] = 127,
+ [0][0][1][0][RTW89_CHILE][1][60] = 22,
+ [0][0][1][0][RTW89_QATAR][1][60] = 127,
+ [0][0][1][0][RTW89_QATAR][0][60] = 127,
+ [0][0][1][0][RTW89_UK][1][60] = 127,
+ [0][0][1][0][RTW89_UK][0][60] = 127,
+ [0][0][1][0][RTW89_FCC][1][62] = 22,
+ [0][0][1][0][RTW89_FCC][2][62] = 68,
+ [0][0][1][0][RTW89_ETSI][1][62] = 127,
+ [0][0][1][0][RTW89_ETSI][0][62] = 127,
+ [0][0][1][0][RTW89_MKK][1][62] = 127,
+ [0][0][1][0][RTW89_MKK][0][62] = 127,
+ [0][0][1][0][RTW89_IC][1][62] = 22,
+ [0][0][1][0][RTW89_KCC][1][62] = 26,
+ [0][0][1][0][RTW89_KCC][0][62] = 127,
+ [0][0][1][0][RTW89_ACMA][1][62] = 127,
+ [0][0][1][0][RTW89_ACMA][0][62] = 127,
+ [0][0][1][0][RTW89_CHILE][1][62] = 22,
+ [0][0][1][0][RTW89_QATAR][1][62] = 127,
+ [0][0][1][0][RTW89_QATAR][0][62] = 127,
+ [0][0][1][0][RTW89_UK][1][62] = 127,
+ [0][0][1][0][RTW89_UK][0][62] = 127,
+ [0][0][1][0][RTW89_FCC][1][64] = 22,
+ [0][0][1][0][RTW89_FCC][2][64] = 68,
+ [0][0][1][0][RTW89_ETSI][1][64] = 127,
+ [0][0][1][0][RTW89_ETSI][0][64] = 127,
+ [0][0][1][0][RTW89_MKK][1][64] = 127,
+ [0][0][1][0][RTW89_MKK][0][64] = 127,
+ [0][0][1][0][RTW89_IC][1][64] = 22,
+ [0][0][1][0][RTW89_KCC][1][64] = 26,
+ [0][0][1][0][RTW89_KCC][0][64] = 127,
+ [0][0][1][0][RTW89_ACMA][1][64] = 127,
+ [0][0][1][0][RTW89_ACMA][0][64] = 127,
+ [0][0][1][0][RTW89_CHILE][1][64] = 22,
+ [0][0][1][0][RTW89_QATAR][1][64] = 127,
+ [0][0][1][0][RTW89_QATAR][0][64] = 127,
+ [0][0][1][0][RTW89_UK][1][64] = 127,
+ [0][0][1][0][RTW89_UK][0][64] = 127,
+ [0][0][1][0][RTW89_FCC][1][66] = 22,
+ [0][0][1][0][RTW89_FCC][2][66] = 68,
+ [0][0][1][0][RTW89_ETSI][1][66] = 127,
+ [0][0][1][0][RTW89_ETSI][0][66] = 127,
+ [0][0][1][0][RTW89_MKK][1][66] = 127,
+ [0][0][1][0][RTW89_MKK][0][66] = 127,
+ [0][0][1][0][RTW89_IC][1][66] = 22,
+ [0][0][1][0][RTW89_KCC][1][66] = 26,
+ [0][0][1][0][RTW89_KCC][0][66] = 127,
+ [0][0][1][0][RTW89_ACMA][1][66] = 127,
+ [0][0][1][0][RTW89_ACMA][0][66] = 127,
+ [0][0][1][0][RTW89_CHILE][1][66] = 22,
+ [0][0][1][0][RTW89_QATAR][1][66] = 127,
+ [0][0][1][0][RTW89_QATAR][0][66] = 127,
+ [0][0][1][0][RTW89_UK][1][66] = 127,
+ [0][0][1][0][RTW89_UK][0][66] = 127,
+ [0][0][1][0][RTW89_FCC][1][68] = 22,
+ [0][0][1][0][RTW89_FCC][2][68] = 68,
+ [0][0][1][0][RTW89_ETSI][1][68] = 127,
+ [0][0][1][0][RTW89_ETSI][0][68] = 127,
+ [0][0][1][0][RTW89_MKK][1][68] = 127,
+ [0][0][1][0][RTW89_MKK][0][68] = 127,
+ [0][0][1][0][RTW89_IC][1][68] = 22,
+ [0][0][1][0][RTW89_KCC][1][68] = 26,
+ [0][0][1][0][RTW89_KCC][0][68] = 127,
+ [0][0][1][0][RTW89_ACMA][1][68] = 127,
+ [0][0][1][0][RTW89_ACMA][0][68] = 127,
+ [0][0][1][0][RTW89_CHILE][1][68] = 22,
+ [0][0][1][0][RTW89_QATAR][1][68] = 127,
+ [0][0][1][0][RTW89_QATAR][0][68] = 127,
+ [0][0][1][0][RTW89_UK][1][68] = 127,
+ [0][0][1][0][RTW89_UK][0][68] = 127,
+ [0][0][1][0][RTW89_FCC][1][70] = 24,
+ [0][0][1][0][RTW89_FCC][2][70] = 68,
+ [0][0][1][0][RTW89_ETSI][1][70] = 127,
+ [0][0][1][0][RTW89_ETSI][0][70] = 127,
+ [0][0][1][0][RTW89_MKK][1][70] = 127,
+ [0][0][1][0][RTW89_MKK][0][70] = 127,
+ [0][0][1][0][RTW89_IC][1][70] = 24,
+ [0][0][1][0][RTW89_KCC][1][70] = 26,
+ [0][0][1][0][RTW89_KCC][0][70] = 127,
+ [0][0][1][0][RTW89_ACMA][1][70] = 127,
+ [0][0][1][0][RTW89_ACMA][0][70] = 127,
+ [0][0][1][0][RTW89_CHILE][1][70] = 24,
+ [0][0][1][0][RTW89_QATAR][1][70] = 127,
+ [0][0][1][0][RTW89_QATAR][0][70] = 127,
+ [0][0][1][0][RTW89_UK][1][70] = 127,
+ [0][0][1][0][RTW89_UK][0][70] = 127,
+ [0][0][1][0][RTW89_FCC][1][72] = 22,
+ [0][0][1][0][RTW89_FCC][2][72] = 68,
+ [0][0][1][0][RTW89_ETSI][1][72] = 127,
+ [0][0][1][0][RTW89_ETSI][0][72] = 127,
+ [0][0][1][0][RTW89_MKK][1][72] = 127,
+ [0][0][1][0][RTW89_MKK][0][72] = 127,
+ [0][0][1][0][RTW89_IC][1][72] = 22,
+ [0][0][1][0][RTW89_KCC][1][72] = 26,
+ [0][0][1][0][RTW89_KCC][0][72] = 127,
+ [0][0][1][0][RTW89_ACMA][1][72] = 127,
+ [0][0][1][0][RTW89_ACMA][0][72] = 127,
+ [0][0][1][0][RTW89_CHILE][1][72] = 22,
+ [0][0][1][0][RTW89_QATAR][1][72] = 127,
+ [0][0][1][0][RTW89_QATAR][0][72] = 127,
+ [0][0][1][0][RTW89_UK][1][72] = 127,
+ [0][0][1][0][RTW89_UK][0][72] = 127,
+ [0][0][1][0][RTW89_FCC][1][74] = 22,
+ [0][0][1][0][RTW89_FCC][2][74] = 68,
+ [0][0][1][0][RTW89_ETSI][1][74] = 127,
+ [0][0][1][0][RTW89_ETSI][0][74] = 127,
+ [0][0][1][0][RTW89_MKK][1][74] = 127,
+ [0][0][1][0][RTW89_MKK][0][74] = 127,
+ [0][0][1][0][RTW89_IC][1][74] = 22,
+ [0][0][1][0][RTW89_KCC][1][74] = 26,
+ [0][0][1][0][RTW89_KCC][0][74] = 127,
+ [0][0][1][0][RTW89_ACMA][1][74] = 127,
+ [0][0][1][0][RTW89_ACMA][0][74] = 127,
+ [0][0][1][0][RTW89_CHILE][1][74] = 22,
+ [0][0][1][0][RTW89_QATAR][1][74] = 127,
+ [0][0][1][0][RTW89_QATAR][0][74] = 127,
+ [0][0][1][0][RTW89_UK][1][74] = 127,
+ [0][0][1][0][RTW89_UK][0][74] = 127,
+ [0][0][1][0][RTW89_FCC][1][75] = 22,
+ [0][0][1][0][RTW89_FCC][2][75] = 68,
+ [0][0][1][0][RTW89_ETSI][1][75] = 127,
+ [0][0][1][0][RTW89_ETSI][0][75] = 127,
+ [0][0][1][0][RTW89_MKK][1][75] = 127,
+ [0][0][1][0][RTW89_MKK][0][75] = 127,
+ [0][0][1][0][RTW89_IC][1][75] = 22,
+ [0][0][1][0][RTW89_KCC][1][75] = 26,
+ [0][0][1][0][RTW89_KCC][0][75] = 127,
+ [0][0][1][0][RTW89_ACMA][1][75] = 127,
+ [0][0][1][0][RTW89_ACMA][0][75] = 127,
+ [0][0][1][0][RTW89_CHILE][1][75] = 22,
+ [0][0][1][0][RTW89_QATAR][1][75] = 127,
+ [0][0][1][0][RTW89_QATAR][0][75] = 127,
+ [0][0][1][0][RTW89_UK][1][75] = 127,
+ [0][0][1][0][RTW89_UK][0][75] = 127,
+ [0][0][1][0][RTW89_FCC][1][77] = 22,
+ [0][0][1][0][RTW89_FCC][2][77] = 68,
+ [0][0][1][0][RTW89_ETSI][1][77] = 127,
+ [0][0][1][0][RTW89_ETSI][0][77] = 127,
+ [0][0][1][0][RTW89_MKK][1][77] = 127,
+ [0][0][1][0][RTW89_MKK][0][77] = 127,
+ [0][0][1][0][RTW89_IC][1][77] = 22,
+ [0][0][1][0][RTW89_KCC][1][77] = 26,
+ [0][0][1][0][RTW89_KCC][0][77] = 127,
+ [0][0][1][0][RTW89_ACMA][1][77] = 127,
+ [0][0][1][0][RTW89_ACMA][0][77] = 127,
+ [0][0][1][0][RTW89_CHILE][1][77] = 22,
+ [0][0][1][0][RTW89_QATAR][1][77] = 127,
+ [0][0][1][0][RTW89_QATAR][0][77] = 127,
+ [0][0][1][0][RTW89_UK][1][77] = 127,
+ [0][0][1][0][RTW89_UK][0][77] = 127,
+ [0][0][1][0][RTW89_FCC][1][79] = 22,
+ [0][0][1][0][RTW89_FCC][2][79] = 68,
+ [0][0][1][0][RTW89_ETSI][1][79] = 127,
+ [0][0][1][0][RTW89_ETSI][0][79] = 127,
+ [0][0][1][0][RTW89_MKK][1][79] = 127,
+ [0][0][1][0][RTW89_MKK][0][79] = 127,
+ [0][0][1][0][RTW89_IC][1][79] = 22,
+ [0][0][1][0][RTW89_KCC][1][79] = 26,
+ [0][0][1][0][RTW89_KCC][0][79] = 127,
+ [0][0][1][0][RTW89_ACMA][1][79] = 127,
+ [0][0][1][0][RTW89_ACMA][0][79] = 127,
+ [0][0][1][0][RTW89_CHILE][1][79] = 22,
+ [0][0][1][0][RTW89_QATAR][1][79] = 127,
+ [0][0][1][0][RTW89_QATAR][0][79] = 127,
+ [0][0][1][0][RTW89_UK][1][79] = 127,
+ [0][0][1][0][RTW89_UK][0][79] = 127,
+ [0][0][1][0][RTW89_FCC][1][81] = 22,
+ [0][0][1][0][RTW89_FCC][2][81] = 68,
+ [0][0][1][0][RTW89_ETSI][1][81] = 127,
+ [0][0][1][0][RTW89_ETSI][0][81] = 127,
+ [0][0][1][0][RTW89_MKK][1][81] = 127,
+ [0][0][1][0][RTW89_MKK][0][81] = 127,
+ [0][0][1][0][RTW89_IC][1][81] = 22,
+ [0][0][1][0][RTW89_KCC][1][81] = 26,
+ [0][0][1][0][RTW89_KCC][0][81] = 127,
+ [0][0][1][0][RTW89_ACMA][1][81] = 127,
+ [0][0][1][0][RTW89_ACMA][0][81] = 127,
+ [0][0][1][0][RTW89_CHILE][1][81] = 22,
+ [0][0][1][0][RTW89_QATAR][1][81] = 127,
+ [0][0][1][0][RTW89_QATAR][0][81] = 127,
+ [0][0][1][0][RTW89_UK][1][81] = 127,
+ [0][0][1][0][RTW89_UK][0][81] = 127,
+ [0][0][1][0][RTW89_FCC][1][83] = 22,
+ [0][0][1][0][RTW89_FCC][2][83] = 68,
+ [0][0][1][0][RTW89_ETSI][1][83] = 127,
+ [0][0][1][0][RTW89_ETSI][0][83] = 127,
+ [0][0][1][0][RTW89_MKK][1][83] = 127,
+ [0][0][1][0][RTW89_MKK][0][83] = 127,
+ [0][0][1][0][RTW89_IC][1][83] = 22,
+ [0][0][1][0][RTW89_KCC][1][83] = 32,
+ [0][0][1][0][RTW89_KCC][0][83] = 127,
+ [0][0][1][0][RTW89_ACMA][1][83] = 127,
+ [0][0][1][0][RTW89_ACMA][0][83] = 127,
+ [0][0][1][0][RTW89_CHILE][1][83] = 22,
+ [0][0][1][0][RTW89_QATAR][1][83] = 127,
+ [0][0][1][0][RTW89_QATAR][0][83] = 127,
+ [0][0][1][0][RTW89_UK][1][83] = 127,
+ [0][0][1][0][RTW89_UK][0][83] = 127,
+ [0][0][1][0][RTW89_FCC][1][85] = 22,
+ [0][0][1][0][RTW89_FCC][2][85] = 68,
+ [0][0][1][0][RTW89_ETSI][1][85] = 127,
+ [0][0][1][0][RTW89_ETSI][0][85] = 127,
+ [0][0][1][0][RTW89_MKK][1][85] = 127,
+ [0][0][1][0][RTW89_MKK][0][85] = 127,
+ [0][0][1][0][RTW89_IC][1][85] = 22,
+ [0][0][1][0][RTW89_KCC][1][85] = 32,
+ [0][0][1][0][RTW89_KCC][0][85] = 127,
+ [0][0][1][0][RTW89_ACMA][1][85] = 127,
+ [0][0][1][0][RTW89_ACMA][0][85] = 127,
+ [0][0][1][0][RTW89_CHILE][1][85] = 22,
+ [0][0][1][0][RTW89_QATAR][1][85] = 127,
+ [0][0][1][0][RTW89_QATAR][0][85] = 127,
+ [0][0][1][0][RTW89_UK][1][85] = 127,
+ [0][0][1][0][RTW89_UK][0][85] = 127,
+ [0][0][1][0][RTW89_FCC][1][87] = 22,
+ [0][0][1][0][RTW89_FCC][2][87] = 127,
+ [0][0][1][0][RTW89_ETSI][1][87] = 127,
+ [0][0][1][0][RTW89_ETSI][0][87] = 127,
+ [0][0][1][0][RTW89_MKK][1][87] = 127,
+ [0][0][1][0][RTW89_MKK][0][87] = 127,
+ [0][0][1][0][RTW89_IC][1][87] = 22,
+ [0][0][1][0][RTW89_KCC][1][87] = 32,
+ [0][0][1][0][RTW89_KCC][0][87] = 127,
+ [0][0][1][0][RTW89_ACMA][1][87] = 127,
+ [0][0][1][0][RTW89_ACMA][0][87] = 127,
+ [0][0][1][0][RTW89_CHILE][1][87] = 22,
+ [0][0][1][0][RTW89_QATAR][1][87] = 127,
+ [0][0][1][0][RTW89_QATAR][0][87] = 127,
+ [0][0][1][0][RTW89_UK][1][87] = 127,
+ [0][0][1][0][RTW89_UK][0][87] = 127,
+ [0][0][1][0][RTW89_FCC][1][89] = 22,
+ [0][0][1][0][RTW89_FCC][2][89] = 127,
+ [0][0][1][0][RTW89_ETSI][1][89] = 127,
+ [0][0][1][0][RTW89_ETSI][0][89] = 127,
+ [0][0][1][0][RTW89_MKK][1][89] = 127,
+ [0][0][1][0][RTW89_MKK][0][89] = 127,
+ [0][0][1][0][RTW89_IC][1][89] = 22,
+ [0][0][1][0][RTW89_KCC][1][89] = 32,
+ [0][0][1][0][RTW89_KCC][0][89] = 127,
+ [0][0][1][0][RTW89_ACMA][1][89] = 127,
+ [0][0][1][0][RTW89_ACMA][0][89] = 127,
+ [0][0][1][0][RTW89_CHILE][1][89] = 22,
+ [0][0][1][0][RTW89_QATAR][1][89] = 127,
+ [0][0][1][0][RTW89_QATAR][0][89] = 127,
+ [0][0][1][0][RTW89_UK][1][89] = 127,
+ [0][0][1][0][RTW89_UK][0][89] = 127,
+ [0][0][1][0][RTW89_FCC][1][90] = 22,
+ [0][0][1][0][RTW89_FCC][2][90] = 127,
+ [0][0][1][0][RTW89_ETSI][1][90] = 127,
+ [0][0][1][0][RTW89_ETSI][0][90] = 127,
+ [0][0][1][0][RTW89_MKK][1][90] = 127,
+ [0][0][1][0][RTW89_MKK][0][90] = 127,
+ [0][0][1][0][RTW89_IC][1][90] = 22,
+ [0][0][1][0][RTW89_KCC][1][90] = 32,
+ [0][0][1][0][RTW89_KCC][0][90] = 127,
+ [0][0][1][0][RTW89_ACMA][1][90] = 127,
+ [0][0][1][0][RTW89_ACMA][0][90] = 127,
+ [0][0][1][0][RTW89_CHILE][1][90] = 22,
+ [0][0][1][0][RTW89_QATAR][1][90] = 127,
+ [0][0][1][0][RTW89_QATAR][0][90] = 127,
+ [0][0][1][0][RTW89_UK][1][90] = 127,
+ [0][0][1][0][RTW89_UK][0][90] = 127,
+ [0][0][1][0][RTW89_FCC][1][92] = 22,
+ [0][0][1][0][RTW89_FCC][2][92] = 127,
+ [0][0][1][0][RTW89_ETSI][1][92] = 127,
+ [0][0][1][0][RTW89_ETSI][0][92] = 127,
+ [0][0][1][0][RTW89_MKK][1][92] = 127,
+ [0][0][1][0][RTW89_MKK][0][92] = 127,
+ [0][0][1][0][RTW89_IC][1][92] = 22,
+ [0][0][1][0][RTW89_KCC][1][92] = 32,
+ [0][0][1][0][RTW89_KCC][0][92] = 127,
+ [0][0][1][0][RTW89_ACMA][1][92] = 127,
+ [0][0][1][0][RTW89_ACMA][0][92] = 127,
+ [0][0][1][0][RTW89_CHILE][1][92] = 22,
+ [0][0][1][0][RTW89_QATAR][1][92] = 127,
+ [0][0][1][0][RTW89_QATAR][0][92] = 127,
+ [0][0][1][0][RTW89_UK][1][92] = 127,
+ [0][0][1][0][RTW89_UK][0][92] = 127,
+ [0][0][1][0][RTW89_FCC][1][94] = 22,
+ [0][0][1][0][RTW89_FCC][2][94] = 127,
+ [0][0][1][0][RTW89_ETSI][1][94] = 127,
+ [0][0][1][0][RTW89_ETSI][0][94] = 127,
+ [0][0][1][0][RTW89_MKK][1][94] = 127,
+ [0][0][1][0][RTW89_MKK][0][94] = 127,
+ [0][0][1][0][RTW89_IC][1][94] = 22,
+ [0][0][1][0][RTW89_KCC][1][94] = 32,
+ [0][0][1][0][RTW89_KCC][0][94] = 127,
+ [0][0][1][0][RTW89_ACMA][1][94] = 127,
+ [0][0][1][0][RTW89_ACMA][0][94] = 127,
+ [0][0][1][0][RTW89_CHILE][1][94] = 22,
+ [0][0][1][0][RTW89_QATAR][1][94] = 127,
+ [0][0][1][0][RTW89_QATAR][0][94] = 127,
+ [0][0][1][0][RTW89_UK][1][94] = 127,
+ [0][0][1][0][RTW89_UK][0][94] = 127,
+ [0][0][1][0][RTW89_FCC][1][96] = 22,
+ [0][0][1][0][RTW89_FCC][2][96] = 127,
+ [0][0][1][0][RTW89_ETSI][1][96] = 127,
+ [0][0][1][0][RTW89_ETSI][0][96] = 127,
+ [0][0][1][0][RTW89_MKK][1][96] = 127,
+ [0][0][1][0][RTW89_MKK][0][96] = 127,
+ [0][0][1][0][RTW89_IC][1][96] = 22,
+ [0][0][1][0][RTW89_KCC][1][96] = 32,
+ [0][0][1][0][RTW89_KCC][0][96] = 127,
+ [0][0][1][0][RTW89_ACMA][1][96] = 127,
+ [0][0][1][0][RTW89_ACMA][0][96] = 127,
+ [0][0][1][0][RTW89_CHILE][1][96] = 22,
+ [0][0][1][0][RTW89_QATAR][1][96] = 127,
+ [0][0][1][0][RTW89_QATAR][0][96] = 127,
+ [0][0][1][0][RTW89_UK][1][96] = 127,
+ [0][0][1][0][RTW89_UK][0][96] = 127,
+ [0][0][1][0][RTW89_FCC][1][98] = 22,
+ [0][0][1][0][RTW89_FCC][2][98] = 127,
+ [0][0][1][0][RTW89_ETSI][1][98] = 127,
+ [0][0][1][0][RTW89_ETSI][0][98] = 127,
+ [0][0][1][0][RTW89_MKK][1][98] = 127,
+ [0][0][1][0][RTW89_MKK][0][98] = 127,
+ [0][0][1][0][RTW89_IC][1][98] = 22,
+ [0][0][1][0][RTW89_KCC][1][98] = 32,
+ [0][0][1][0][RTW89_KCC][0][98] = 127,
+ [0][0][1][0][RTW89_ACMA][1][98] = 127,
+ [0][0][1][0][RTW89_ACMA][0][98] = 127,
+ [0][0][1][0][RTW89_CHILE][1][98] = 22,
+ [0][0][1][0][RTW89_QATAR][1][98] = 127,
+ [0][0][1][0][RTW89_QATAR][0][98] = 127,
+ [0][0][1][0][RTW89_UK][1][98] = 127,
+ [0][0][1][0][RTW89_UK][0][98] = 127,
+ [0][0][1][0][RTW89_FCC][1][100] = 22,
+ [0][0][1][0][RTW89_FCC][2][100] = 127,
+ [0][0][1][0][RTW89_ETSI][1][100] = 127,
+ [0][0][1][0][RTW89_ETSI][0][100] = 127,
+ [0][0][1][0][RTW89_MKK][1][100] = 127,
+ [0][0][1][0][RTW89_MKK][0][100] = 127,
+ [0][0][1][0][RTW89_IC][1][100] = 22,
+ [0][0][1][0][RTW89_KCC][1][100] = 32,
+ [0][0][1][0][RTW89_KCC][0][100] = 127,
+ [0][0][1][0][RTW89_ACMA][1][100] = 127,
+ [0][0][1][0][RTW89_ACMA][0][100] = 127,
+ [0][0][1][0][RTW89_CHILE][1][100] = 22,
+ [0][0][1][0][RTW89_QATAR][1][100] = 127,
+ [0][0][1][0][RTW89_QATAR][0][100] = 127,
+ [0][0][1][0][RTW89_UK][1][100] = 127,
+ [0][0][1][0][RTW89_UK][0][100] = 127,
+ [0][0][1][0][RTW89_FCC][1][102] = 22,
+ [0][0][1][0][RTW89_FCC][2][102] = 127,
+ [0][0][1][0][RTW89_ETSI][1][102] = 127,
+ [0][0][1][0][RTW89_ETSI][0][102] = 127,
+ [0][0][1][0][RTW89_MKK][1][102] = 127,
+ [0][0][1][0][RTW89_MKK][0][102] = 127,
+ [0][0][1][0][RTW89_IC][1][102] = 22,
+ [0][0][1][0][RTW89_KCC][1][102] = 32,
+ [0][0][1][0][RTW89_KCC][0][102] = 127,
+ [0][0][1][0][RTW89_ACMA][1][102] = 127,
+ [0][0][1][0][RTW89_ACMA][0][102] = 127,
+ [0][0][1][0][RTW89_CHILE][1][102] = 22,
+ [0][0][1][0][RTW89_QATAR][1][102] = 127,
+ [0][0][1][0][RTW89_QATAR][0][102] = 127,
+ [0][0][1][0][RTW89_UK][1][102] = 127,
+ [0][0][1][0][RTW89_UK][0][102] = 127,
+ [0][0][1][0][RTW89_FCC][1][104] = 22,
+ [0][0][1][0][RTW89_FCC][2][104] = 127,
+ [0][0][1][0][RTW89_ETSI][1][104] = 127,
+ [0][0][1][0][RTW89_ETSI][0][104] = 127,
+ [0][0][1][0][RTW89_MKK][1][104] = 127,
+ [0][0][1][0][RTW89_MKK][0][104] = 127,
+ [0][0][1][0][RTW89_IC][1][104] = 22,
+ [0][0][1][0][RTW89_KCC][1][104] = 32,
+ [0][0][1][0][RTW89_KCC][0][104] = 127,
+ [0][0][1][0][RTW89_ACMA][1][104] = 127,
+ [0][0][1][0][RTW89_ACMA][0][104] = 127,
+ [0][0][1][0][RTW89_CHILE][1][104] = 22,
+ [0][0][1][0][RTW89_QATAR][1][104] = 127,
+ [0][0][1][0][RTW89_QATAR][0][104] = 127,
+ [0][0][1][0][RTW89_UK][1][104] = 127,
+ [0][0][1][0][RTW89_UK][0][104] = 127,
+ [0][0][1][0][RTW89_FCC][1][105] = 22,
+ [0][0][1][0][RTW89_FCC][2][105] = 127,
+ [0][0][1][0][RTW89_ETSI][1][105] = 127,
+ [0][0][1][0][RTW89_ETSI][0][105] = 127,
+ [0][0][1][0][RTW89_MKK][1][105] = 127,
+ [0][0][1][0][RTW89_MKK][0][105] = 127,
+ [0][0][1][0][RTW89_IC][1][105] = 22,
+ [0][0][1][0][RTW89_KCC][1][105] = 32,
+ [0][0][1][0][RTW89_KCC][0][105] = 127,
+ [0][0][1][0][RTW89_ACMA][1][105] = 127,
+ [0][0][1][0][RTW89_ACMA][0][105] = 127,
+ [0][0][1][0][RTW89_CHILE][1][105] = 22,
+ [0][0][1][0][RTW89_QATAR][1][105] = 127,
+ [0][0][1][0][RTW89_QATAR][0][105] = 127,
+ [0][0][1][0][RTW89_UK][1][105] = 127,
+ [0][0][1][0][RTW89_UK][0][105] = 127,
+ [0][0][1][0][RTW89_FCC][1][107] = 24,
+ [0][0][1][0][RTW89_FCC][2][107] = 127,
+ [0][0][1][0][RTW89_ETSI][1][107] = 127,
+ [0][0][1][0][RTW89_ETSI][0][107] = 127,
+ [0][0][1][0][RTW89_MKK][1][107] = 127,
+ [0][0][1][0][RTW89_MKK][0][107] = 127,
+ [0][0][1][0][RTW89_IC][1][107] = 24,
+ [0][0][1][0][RTW89_KCC][1][107] = 32,
+ [0][0][1][0][RTW89_KCC][0][107] = 127,
+ [0][0][1][0][RTW89_ACMA][1][107] = 127,
+ [0][0][1][0][RTW89_ACMA][0][107] = 127,
+ [0][0][1][0][RTW89_CHILE][1][107] = 24,
+ [0][0][1][0][RTW89_QATAR][1][107] = 127,
+ [0][0][1][0][RTW89_QATAR][0][107] = 127,
+ [0][0][1][0][RTW89_UK][1][107] = 127,
+ [0][0][1][0][RTW89_UK][0][107] = 127,
+ [0][0][1][0][RTW89_FCC][1][109] = 24,
+ [0][0][1][0][RTW89_FCC][2][109] = 127,
+ [0][0][1][0][RTW89_ETSI][1][109] = 127,
+ [0][0][1][0][RTW89_ETSI][0][109] = 127,
+ [0][0][1][0][RTW89_MKK][1][109] = 127,
+ [0][0][1][0][RTW89_MKK][0][109] = 127,
+ [0][0][1][0][RTW89_IC][1][109] = 24,
+ [0][0][1][0][RTW89_KCC][1][109] = 32,
+ [0][0][1][0][RTW89_KCC][0][109] = 127,
+ [0][0][1][0][RTW89_ACMA][1][109] = 127,
+ [0][0][1][0][RTW89_ACMA][0][109] = 127,
+ [0][0][1][0][RTW89_CHILE][1][109] = 24,
+ [0][0][1][0][RTW89_QATAR][1][109] = 127,
+ [0][0][1][0][RTW89_QATAR][0][109] = 127,
+ [0][0][1][0][RTW89_UK][1][109] = 127,
+ [0][0][1][0][RTW89_UK][0][109] = 127,
+ [0][0][1][0][RTW89_FCC][1][111] = 127,
+ [0][0][1][0][RTW89_FCC][2][111] = 127,
+ [0][0][1][0][RTW89_ETSI][1][111] = 127,
+ [0][0][1][0][RTW89_ETSI][0][111] = 127,
+ [0][0][1][0][RTW89_MKK][1][111] = 127,
+ [0][0][1][0][RTW89_MKK][0][111] = 127,
+ [0][0][1][0][RTW89_IC][1][111] = 127,
+ [0][0][1][0][RTW89_KCC][1][111] = 127,
+ [0][0][1][0][RTW89_KCC][0][111] = 127,
+ [0][0][1][0][RTW89_ACMA][1][111] = 127,
+ [0][0][1][0][RTW89_ACMA][0][111] = 127,
+ [0][0][1][0][RTW89_CHILE][1][111] = 127,
+ [0][0][1][0][RTW89_QATAR][1][111] = 127,
+ [0][0][1][0][RTW89_QATAR][0][111] = 127,
+ [0][0][1][0][RTW89_UK][1][111] = 127,
+ [0][0][1][0][RTW89_UK][0][111] = 127,
+ [0][0][1][0][RTW89_FCC][1][113] = 127,
+ [0][0][1][0][RTW89_FCC][2][113] = 127,
+ [0][0][1][0][RTW89_ETSI][1][113] = 127,
+ [0][0][1][0][RTW89_ETSI][0][113] = 127,
+ [0][0][1][0][RTW89_MKK][1][113] = 127,
+ [0][0][1][0][RTW89_MKK][0][113] = 127,
+ [0][0][1][0][RTW89_IC][1][113] = 127,
+ [0][0][1][0][RTW89_KCC][1][113] = 127,
+ [0][0][1][0][RTW89_KCC][0][113] = 127,
+ [0][0][1][0][RTW89_ACMA][1][113] = 127,
+ [0][0][1][0][RTW89_ACMA][0][113] = 127,
+ [0][0][1][0][RTW89_CHILE][1][113] = 127,
+ [0][0][1][0][RTW89_QATAR][1][113] = 127,
+ [0][0][1][0][RTW89_QATAR][0][113] = 127,
+ [0][0][1][0][RTW89_UK][1][113] = 127,
+ [0][0][1][0][RTW89_UK][0][113] = 127,
+ [0][0][1][0][RTW89_FCC][1][115] = 127,
+ [0][0][1][0][RTW89_FCC][2][115] = 127,
+ [0][0][1][0][RTW89_ETSI][1][115] = 127,
+ [0][0][1][0][RTW89_ETSI][0][115] = 127,
+ [0][0][1][0][RTW89_MKK][1][115] = 127,
+ [0][0][1][0][RTW89_MKK][0][115] = 127,
+ [0][0][1][0][RTW89_IC][1][115] = 127,
+ [0][0][1][0][RTW89_KCC][1][115] = 127,
+ [0][0][1][0][RTW89_KCC][0][115] = 127,
+ [0][0][1][0][RTW89_ACMA][1][115] = 127,
+ [0][0][1][0][RTW89_ACMA][0][115] = 127,
+ [0][0][1][0][RTW89_CHILE][1][115] = 127,
+ [0][0][1][0][RTW89_QATAR][1][115] = 127,
+ [0][0][1][0][RTW89_QATAR][0][115] = 127,
+ [0][0][1][0][RTW89_UK][1][115] = 127,
+ [0][0][1][0][RTW89_UK][0][115] = 127,
+ [0][0][1][0][RTW89_FCC][1][117] = 127,
+ [0][0][1][0][RTW89_FCC][2][117] = 127,
+ [0][0][1][0][RTW89_ETSI][1][117] = 127,
+ [0][0][1][0][RTW89_ETSI][0][117] = 127,
+ [0][0][1][0][RTW89_MKK][1][117] = 127,
+ [0][0][1][0][RTW89_MKK][0][117] = 127,
+ [0][0][1][0][RTW89_IC][1][117] = 127,
+ [0][0][1][0][RTW89_KCC][1][117] = 127,
+ [0][0][1][0][RTW89_KCC][0][117] = 127,
+ [0][0][1][0][RTW89_ACMA][1][117] = 127,
+ [0][0][1][0][RTW89_ACMA][0][117] = 127,
+ [0][0][1][0][RTW89_CHILE][1][117] = 127,
+ [0][0][1][0][RTW89_QATAR][1][117] = 127,
+ [0][0][1][0][RTW89_QATAR][0][117] = 127,
+ [0][0][1][0][RTW89_UK][1][117] = 127,
+ [0][0][1][0][RTW89_UK][0][117] = 127,
+ [0][0][1][0][RTW89_FCC][1][119] = 127,
+ [0][0][1][0][RTW89_FCC][2][119] = 127,
+ [0][0][1][0][RTW89_ETSI][1][119] = 127,
+ [0][0][1][0][RTW89_ETSI][0][119] = 127,
+ [0][0][1][0][RTW89_MKK][1][119] = 127,
+ [0][0][1][0][RTW89_MKK][0][119] = 127,
+ [0][0][1][0][RTW89_IC][1][119] = 127,
+ [0][0][1][0][RTW89_KCC][1][119] = 127,
+ [0][0][1][0][RTW89_KCC][0][119] = 127,
+ [0][0][1][0][RTW89_ACMA][1][119] = 127,
+ [0][0][1][0][RTW89_ACMA][0][119] = 127,
+ [0][0][1][0][RTW89_CHILE][1][119] = 127,
+ [0][0][1][0][RTW89_QATAR][1][119] = 127,
+ [0][0][1][0][RTW89_QATAR][0][119] = 127,
+ [0][0][1][0][RTW89_UK][1][119] = 127,
+ [0][0][1][0][RTW89_UK][0][119] = 127,
+ [0][1][1][0][RTW89_FCC][1][0] = -2,
+ [0][1][1][0][RTW89_FCC][2][0] = 54,
+ [0][1][1][0][RTW89_ETSI][1][0] = 54,
+ [0][1][1][0][RTW89_ETSI][0][0] = 18,
+ [0][1][1][0][RTW89_MKK][1][0] = 56,
+ [0][1][1][0][RTW89_MKK][0][0] = 16,
+ [0][1][1][0][RTW89_IC][1][0] = -2,
+ [0][1][1][0][RTW89_KCC][1][0] = 12,
+ [0][1][1][0][RTW89_KCC][0][0] = 10,
+ [0][1][1][0][RTW89_ACMA][1][0] = 54,
+ [0][1][1][0][RTW89_ACMA][0][0] = 18,
+ [0][1][1][0][RTW89_CHILE][1][0] = -2,
+ [0][1][1][0][RTW89_QATAR][1][0] = 54,
+ [0][1][1][0][RTW89_QATAR][0][0] = 18,
+ [0][1][1][0][RTW89_UK][1][0] = 54,
+ [0][1][1][0][RTW89_UK][0][0] = 18,
+ [0][1][1][0][RTW89_FCC][1][2] = -4,
+ [0][1][1][0][RTW89_FCC][2][2] = 54,
+ [0][1][1][0][RTW89_ETSI][1][2] = 54,
+ [0][1][1][0][RTW89_ETSI][0][2] = 18,
+ [0][1][1][0][RTW89_MKK][1][2] = 54,
+ [0][1][1][0][RTW89_MKK][0][2] = 16,
+ [0][1][1][0][RTW89_IC][1][2] = -4,
+ [0][1][1][0][RTW89_KCC][1][2] = 12,
+ [0][1][1][0][RTW89_KCC][0][2] = 12,
+ [0][1][1][0][RTW89_ACMA][1][2] = 54,
+ [0][1][1][0][RTW89_ACMA][0][2] = 18,
+ [0][1][1][0][RTW89_CHILE][1][2] = -4,
+ [0][1][1][0][RTW89_QATAR][1][2] = 54,
+ [0][1][1][0][RTW89_QATAR][0][2] = 18,
+ [0][1][1][0][RTW89_UK][1][2] = 54,
+ [0][1][1][0][RTW89_UK][0][2] = 18,
+ [0][1][1][0][RTW89_FCC][1][4] = -4,
+ [0][1][1][0][RTW89_FCC][2][4] = 54,
+ [0][1][1][0][RTW89_ETSI][1][4] = 54,
+ [0][1][1][0][RTW89_ETSI][0][4] = 18,
+ [0][1][1][0][RTW89_MKK][1][4] = 54,
+ [0][1][1][0][RTW89_MKK][0][4] = 16,
+ [0][1][1][0][RTW89_IC][1][4] = -4,
+ [0][1][1][0][RTW89_KCC][1][4] = 12,
+ [0][1][1][0][RTW89_KCC][0][4] = 12,
+ [0][1][1][0][RTW89_ACMA][1][4] = 54,
+ [0][1][1][0][RTW89_ACMA][0][4] = 18,
+ [0][1][1][0][RTW89_CHILE][1][4] = -4,
+ [0][1][1][0][RTW89_QATAR][1][4] = 54,
+ [0][1][1][0][RTW89_QATAR][0][4] = 18,
+ [0][1][1][0][RTW89_UK][1][4] = 54,
+ [0][1][1][0][RTW89_UK][0][4] = 18,
+ [0][1][1][0][RTW89_FCC][1][6] = -4,
+ [0][1][1][0][RTW89_FCC][2][6] = 54,
+ [0][1][1][0][RTW89_ETSI][1][6] = 54,
+ [0][1][1][0][RTW89_ETSI][0][6] = 18,
+ [0][1][1][0][RTW89_MKK][1][6] = 54,
+ [0][1][1][0][RTW89_MKK][0][6] = 16,
+ [0][1][1][0][RTW89_IC][1][6] = -4,
+ [0][1][1][0][RTW89_KCC][1][6] = 12,
+ [0][1][1][0][RTW89_KCC][0][6] = 12,
+ [0][1][1][0][RTW89_ACMA][1][6] = 54,
+ [0][1][1][0][RTW89_ACMA][0][6] = 18,
+ [0][1][1][0][RTW89_CHILE][1][6] = -4,
+ [0][1][1][0][RTW89_QATAR][1][6] = 54,
+ [0][1][1][0][RTW89_QATAR][0][6] = 18,
+ [0][1][1][0][RTW89_UK][1][6] = 54,
+ [0][1][1][0][RTW89_UK][0][6] = 18,
+ [0][1][1][0][RTW89_FCC][1][8] = -4,
+ [0][1][1][0][RTW89_FCC][2][8] = 54,
+ [0][1][1][0][RTW89_ETSI][1][8] = 54,
+ [0][1][1][0][RTW89_ETSI][0][8] = 18,
+ [0][1][1][0][RTW89_MKK][1][8] = 54,
+ [0][1][1][0][RTW89_MKK][0][8] = 16,
+ [0][1][1][0][RTW89_IC][1][8] = -4,
+ [0][1][1][0][RTW89_KCC][1][8] = 12,
+ [0][1][1][0][RTW89_KCC][0][8] = 12,
+ [0][1][1][0][RTW89_ACMA][1][8] = 54,
+ [0][1][1][0][RTW89_ACMA][0][8] = 18,
+ [0][1][1][0][RTW89_CHILE][1][8] = -4,
+ [0][1][1][0][RTW89_QATAR][1][8] = 54,
+ [0][1][1][0][RTW89_QATAR][0][8] = 18,
+ [0][1][1][0][RTW89_UK][1][8] = 54,
+ [0][1][1][0][RTW89_UK][0][8] = 18,
+ [0][1][1][0][RTW89_FCC][1][10] = -4,
+ [0][1][1][0][RTW89_FCC][2][10] = 54,
+ [0][1][1][0][RTW89_ETSI][1][10] = 54,
+ [0][1][1][0][RTW89_ETSI][0][10] = 18,
+ [0][1][1][0][RTW89_MKK][1][10] = 54,
+ [0][1][1][0][RTW89_MKK][0][10] = 16,
+ [0][1][1][0][RTW89_IC][1][10] = -4,
+ [0][1][1][0][RTW89_KCC][1][10] = 12,
+ [0][1][1][0][RTW89_KCC][0][10] = 12,
+ [0][1][1][0][RTW89_ACMA][1][10] = 54,
+ [0][1][1][0][RTW89_ACMA][0][10] = 18,
+ [0][1][1][0][RTW89_CHILE][1][10] = -4,
+ [0][1][1][0][RTW89_QATAR][1][10] = 54,
+ [0][1][1][0][RTW89_QATAR][0][10] = 18,
+ [0][1][1][0][RTW89_UK][1][10] = 54,
+ [0][1][1][0][RTW89_UK][0][10] = 18,
+ [0][1][1][0][RTW89_FCC][1][12] = -4,
+ [0][1][1][0][RTW89_FCC][2][12] = 54,
+ [0][1][1][0][RTW89_ETSI][1][12] = 54,
+ [0][1][1][0][RTW89_ETSI][0][12] = 18,
+ [0][1][1][0][RTW89_MKK][1][12] = 54,
+ [0][1][1][0][RTW89_MKK][0][12] = 16,
+ [0][1][1][0][RTW89_IC][1][12] = -4,
+ [0][1][1][0][RTW89_KCC][1][12] = 12,
+ [0][1][1][0][RTW89_KCC][0][12] = 12,
+ [0][1][1][0][RTW89_ACMA][1][12] = 54,
+ [0][1][1][0][RTW89_ACMA][0][12] = 18,
+ [0][1][1][0][RTW89_CHILE][1][12] = -4,
+ [0][1][1][0][RTW89_QATAR][1][12] = 54,
+ [0][1][1][0][RTW89_QATAR][0][12] = 18,
+ [0][1][1][0][RTW89_UK][1][12] = 54,
+ [0][1][1][0][RTW89_UK][0][12] = 18,
+ [0][1][1][0][RTW89_FCC][1][14] = -4,
+ [0][1][1][0][RTW89_FCC][2][14] = 54,
+ [0][1][1][0][RTW89_ETSI][1][14] = 54,
+ [0][1][1][0][RTW89_ETSI][0][14] = 18,
+ [0][1][1][0][RTW89_MKK][1][14] = 54,
+ [0][1][1][0][RTW89_MKK][0][14] = 16,
+ [0][1][1][0][RTW89_IC][1][14] = -4,
+ [0][1][1][0][RTW89_KCC][1][14] = 12,
+ [0][1][1][0][RTW89_KCC][0][14] = 12,
+ [0][1][1][0][RTW89_ACMA][1][14] = 54,
+ [0][1][1][0][RTW89_ACMA][0][14] = 18,
+ [0][1][1][0][RTW89_CHILE][1][14] = -4,
+ [0][1][1][0][RTW89_QATAR][1][14] = 54,
+ [0][1][1][0][RTW89_QATAR][0][14] = 18,
+ [0][1][1][0][RTW89_UK][1][14] = 54,
+ [0][1][1][0][RTW89_UK][0][14] = 18,
+ [0][1][1][0][RTW89_FCC][1][15] = -4,
+ [0][1][1][0][RTW89_FCC][2][15] = 54,
+ [0][1][1][0][RTW89_ETSI][1][15] = 54,
+ [0][1][1][0][RTW89_ETSI][0][15] = 18,
+ [0][1][1][0][RTW89_MKK][1][15] = 54,
+ [0][1][1][0][RTW89_MKK][0][15] = 16,
+ [0][1][1][0][RTW89_IC][1][15] = -4,
+ [0][1][1][0][RTW89_KCC][1][15] = 12,
+ [0][1][1][0][RTW89_KCC][0][15] = 12,
+ [0][1][1][0][RTW89_ACMA][1][15] = 54,
+ [0][1][1][0][RTW89_ACMA][0][15] = 18,
+ [0][1][1][0][RTW89_CHILE][1][15] = -4,
+ [0][1][1][0][RTW89_QATAR][1][15] = 54,
+ [0][1][1][0][RTW89_QATAR][0][15] = 18,
+ [0][1][1][0][RTW89_UK][1][15] = 54,
+ [0][1][1][0][RTW89_UK][0][15] = 18,
+ [0][1][1][0][RTW89_FCC][1][17] = -4,
+ [0][1][1][0][RTW89_FCC][2][17] = 54,
+ [0][1][1][0][RTW89_ETSI][1][17] = 54,
+ [0][1][1][0][RTW89_ETSI][0][17] = 18,
+ [0][1][1][0][RTW89_MKK][1][17] = 54,
+ [0][1][1][0][RTW89_MKK][0][17] = 16,
+ [0][1][1][0][RTW89_IC][1][17] = -4,
+ [0][1][1][0][RTW89_KCC][1][17] = 12,
+ [0][1][1][0][RTW89_KCC][0][17] = 12,
+ [0][1][1][0][RTW89_ACMA][1][17] = 54,
+ [0][1][1][0][RTW89_ACMA][0][17] = 18,
+ [0][1][1][0][RTW89_CHILE][1][17] = -4,
+ [0][1][1][0][RTW89_QATAR][1][17] = 54,
+ [0][1][1][0][RTW89_QATAR][0][17] = 18,
+ [0][1][1][0][RTW89_UK][1][17] = 54,
+ [0][1][1][0][RTW89_UK][0][17] = 18,
+ [0][1][1][0][RTW89_FCC][1][19] = -4,
+ [0][1][1][0][RTW89_FCC][2][19] = 54,
+ [0][1][1][0][RTW89_ETSI][1][19] = 54,
+ [0][1][1][0][RTW89_ETSI][0][19] = 18,
+ [0][1][1][0][RTW89_MKK][1][19] = 54,
+ [0][1][1][0][RTW89_MKK][0][19] = 16,
+ [0][1][1][0][RTW89_IC][1][19] = -4,
+ [0][1][1][0][RTW89_KCC][1][19] = 12,
+ [0][1][1][0][RTW89_KCC][0][19] = 12,
+ [0][1][1][0][RTW89_ACMA][1][19] = 54,
+ [0][1][1][0][RTW89_ACMA][0][19] = 18,
+ [0][1][1][0][RTW89_CHILE][1][19] = -4,
+ [0][1][1][0][RTW89_QATAR][1][19] = 54,
+ [0][1][1][0][RTW89_QATAR][0][19] = 18,
+ [0][1][1][0][RTW89_UK][1][19] = 54,
+ [0][1][1][0][RTW89_UK][0][19] = 18,
+ [0][1][1][0][RTW89_FCC][1][21] = -4,
+ [0][1][1][0][RTW89_FCC][2][21] = 54,
+ [0][1][1][0][RTW89_ETSI][1][21] = 54,
+ [0][1][1][0][RTW89_ETSI][0][21] = 18,
+ [0][1][1][0][RTW89_MKK][1][21] = 54,
+ [0][1][1][0][RTW89_MKK][0][21] = 16,
+ [0][1][1][0][RTW89_IC][1][21] = -4,
+ [0][1][1][0][RTW89_KCC][1][21] = 12,
+ [0][1][1][0][RTW89_KCC][0][21] = 12,
+ [0][1][1][0][RTW89_ACMA][1][21] = 54,
+ [0][1][1][0][RTW89_ACMA][0][21] = 18,
+ [0][1][1][0][RTW89_CHILE][1][21] = -4,
+ [0][1][1][0][RTW89_QATAR][1][21] = 54,
+ [0][1][1][0][RTW89_QATAR][0][21] = 18,
+ [0][1][1][0][RTW89_UK][1][21] = 54,
+ [0][1][1][0][RTW89_UK][0][21] = 18,
+ [0][1][1][0][RTW89_FCC][1][23] = -4,
+ [0][1][1][0][RTW89_FCC][2][23] = 68,
+ [0][1][1][0][RTW89_ETSI][1][23] = 54,
+ [0][1][1][0][RTW89_ETSI][0][23] = 18,
+ [0][1][1][0][RTW89_MKK][1][23] = 54,
+ [0][1][1][0][RTW89_MKK][0][23] = 16,
+ [0][1][1][0][RTW89_IC][1][23] = -4,
+ [0][1][1][0][RTW89_KCC][1][23] = 12,
+ [0][1][1][0][RTW89_KCC][0][23] = 10,
+ [0][1][1][0][RTW89_ACMA][1][23] = 54,
+ [0][1][1][0][RTW89_ACMA][0][23] = 18,
+ [0][1][1][0][RTW89_CHILE][1][23] = -4,
+ [0][1][1][0][RTW89_QATAR][1][23] = 54,
+ [0][1][1][0][RTW89_QATAR][0][23] = 18,
+ [0][1][1][0][RTW89_UK][1][23] = 54,
+ [0][1][1][0][RTW89_UK][0][23] = 18,
+ [0][1][1][0][RTW89_FCC][1][25] = -4,
+ [0][1][1][0][RTW89_FCC][2][25] = 68,
+ [0][1][1][0][RTW89_ETSI][1][25] = 54,
+ [0][1][1][0][RTW89_ETSI][0][25] = 18,
+ [0][1][1][0][RTW89_MKK][1][25] = 54,
+ [0][1][1][0][RTW89_MKK][0][25] = 16,
+ [0][1][1][0][RTW89_IC][1][25] = -4,
+ [0][1][1][0][RTW89_KCC][1][25] = 12,
+ [0][1][1][0][RTW89_KCC][0][25] = 14,
+ [0][1][1][0][RTW89_ACMA][1][25] = 54,
+ [0][1][1][0][RTW89_ACMA][0][25] = 18,
+ [0][1][1][0][RTW89_CHILE][1][25] = -4,
+ [0][1][1][0][RTW89_QATAR][1][25] = 54,
+ [0][1][1][0][RTW89_QATAR][0][25] = 18,
+ [0][1][1][0][RTW89_UK][1][25] = 54,
+ [0][1][1][0][RTW89_UK][0][25] = 18,
+ [0][1][1][0][RTW89_FCC][1][27] = -4,
+ [0][1][1][0][RTW89_FCC][2][27] = 68,
+ [0][1][1][0][RTW89_ETSI][1][27] = 54,
+ [0][1][1][0][RTW89_ETSI][0][27] = 18,
+ [0][1][1][0][RTW89_MKK][1][27] = 54,
+ [0][1][1][0][RTW89_MKK][0][27] = 16,
+ [0][1][1][0][RTW89_IC][1][27] = -4,
+ [0][1][1][0][RTW89_KCC][1][27] = 12,
+ [0][1][1][0][RTW89_KCC][0][27] = 14,
+ [0][1][1][0][RTW89_ACMA][1][27] = 54,
+ [0][1][1][0][RTW89_ACMA][0][27] = 18,
+ [0][1][1][0][RTW89_CHILE][1][27] = -4,
+ [0][1][1][0][RTW89_QATAR][1][27] = 54,
+ [0][1][1][0][RTW89_QATAR][0][27] = 18,
+ [0][1][1][0][RTW89_UK][1][27] = 54,
+ [0][1][1][0][RTW89_UK][0][27] = 18,
+ [0][1][1][0][RTW89_FCC][1][29] = -4,
+ [0][1][1][0][RTW89_FCC][2][29] = 68,
+ [0][1][1][0][RTW89_ETSI][1][29] = 54,
+ [0][1][1][0][RTW89_ETSI][0][29] = 18,
+ [0][1][1][0][RTW89_MKK][1][29] = 54,
+ [0][1][1][0][RTW89_MKK][0][29] = 16,
+ [0][1][1][0][RTW89_IC][1][29] = -4,
+ [0][1][1][0][RTW89_KCC][1][29] = 12,
+ [0][1][1][0][RTW89_KCC][0][29] = 14,
+ [0][1][1][0][RTW89_ACMA][1][29] = 54,
+ [0][1][1][0][RTW89_ACMA][0][29] = 18,
+ [0][1][1][0][RTW89_CHILE][1][29] = -4,
+ [0][1][1][0][RTW89_QATAR][1][29] = 54,
+ [0][1][1][0][RTW89_QATAR][0][29] = 18,
+ [0][1][1][0][RTW89_UK][1][29] = 54,
+ [0][1][1][0][RTW89_UK][0][29] = 18,
+ [0][1][1][0][RTW89_FCC][1][30] = -4,
+ [0][1][1][0][RTW89_FCC][2][30] = 68,
+ [0][1][1][0][RTW89_ETSI][1][30] = 54,
+ [0][1][1][0][RTW89_ETSI][0][30] = 18,
+ [0][1][1][0][RTW89_MKK][1][30] = 54,
+ [0][1][1][0][RTW89_MKK][0][30] = 16,
+ [0][1][1][0][RTW89_IC][1][30] = -4,
+ [0][1][1][0][RTW89_KCC][1][30] = 12,
+ [0][1][1][0][RTW89_KCC][0][30] = 14,
+ [0][1][1][0][RTW89_ACMA][1][30] = 54,
+ [0][1][1][0][RTW89_ACMA][0][30] = 18,
+ [0][1][1][0][RTW89_CHILE][1][30] = -4,
+ [0][1][1][0][RTW89_QATAR][1][30] = 54,
+ [0][1][1][0][RTW89_QATAR][0][30] = 18,
+ [0][1][1][0][RTW89_UK][1][30] = 54,
+ [0][1][1][0][RTW89_UK][0][30] = 18,
+ [0][1][1][0][RTW89_FCC][1][32] = -4,
+ [0][1][1][0][RTW89_FCC][2][32] = 68,
+ [0][1][1][0][RTW89_ETSI][1][32] = 54,
+ [0][1][1][0][RTW89_ETSI][0][32] = 18,
+ [0][1][1][0][RTW89_MKK][1][32] = 54,
+ [0][1][1][0][RTW89_MKK][0][32] = 16,
+ [0][1][1][0][RTW89_IC][1][32] = -4,
+ [0][1][1][0][RTW89_KCC][1][32] = 12,
+ [0][1][1][0][RTW89_KCC][0][32] = 14,
+ [0][1][1][0][RTW89_ACMA][1][32] = 54,
+ [0][1][1][0][RTW89_ACMA][0][32] = 18,
+ [0][1][1][0][RTW89_CHILE][1][32] = -4,
+ [0][1][1][0][RTW89_QATAR][1][32] = 54,
+ [0][1][1][0][RTW89_QATAR][0][32] = 18,
+ [0][1][1][0][RTW89_UK][1][32] = 54,
+ [0][1][1][0][RTW89_UK][0][32] = 18,
+ [0][1][1][0][RTW89_FCC][1][34] = -4,
+ [0][1][1][0][RTW89_FCC][2][34] = 68,
+ [0][1][1][0][RTW89_ETSI][1][34] = 54,
+ [0][1][1][0][RTW89_ETSI][0][34] = 18,
+ [0][1][1][0][RTW89_MKK][1][34] = 54,
+ [0][1][1][0][RTW89_MKK][0][34] = 16,
+ [0][1][1][0][RTW89_IC][1][34] = -4,
+ [0][1][1][0][RTW89_KCC][1][34] = 12,
+ [0][1][1][0][RTW89_KCC][0][34] = 14,
+ [0][1][1][0][RTW89_ACMA][1][34] = 54,
+ [0][1][1][0][RTW89_ACMA][0][34] = 18,
+ [0][1][1][0][RTW89_CHILE][1][34] = -4,
+ [0][1][1][0][RTW89_QATAR][1][34] = 54,
+ [0][1][1][0][RTW89_QATAR][0][34] = 18,
+ [0][1][1][0][RTW89_UK][1][34] = 54,
+ [0][1][1][0][RTW89_UK][0][34] = 18,
+ [0][1][1][0][RTW89_FCC][1][36] = -4,
+ [0][1][1][0][RTW89_FCC][2][36] = 68,
+ [0][1][1][0][RTW89_ETSI][1][36] = 54,
+ [0][1][1][0][RTW89_ETSI][0][36] = 18,
+ [0][1][1][0][RTW89_MKK][1][36] = 54,
+ [0][1][1][0][RTW89_MKK][0][36] = 16,
+ [0][1][1][0][RTW89_IC][1][36] = -4,
+ [0][1][1][0][RTW89_KCC][1][36] = 12,
+ [0][1][1][0][RTW89_KCC][0][36] = 14,
+ [0][1][1][0][RTW89_ACMA][1][36] = 54,
+ [0][1][1][0][RTW89_ACMA][0][36] = 18,
+ [0][1][1][0][RTW89_CHILE][1][36] = -4,
+ [0][1][1][0][RTW89_QATAR][1][36] = 54,
+ [0][1][1][0][RTW89_QATAR][0][36] = 18,
+ [0][1][1][0][RTW89_UK][1][36] = 54,
+ [0][1][1][0][RTW89_UK][0][36] = 18,
+ [0][1][1][0][RTW89_FCC][1][38] = -4,
+ [0][1][1][0][RTW89_FCC][2][38] = 68,
+ [0][1][1][0][RTW89_ETSI][1][38] = 54,
+ [0][1][1][0][RTW89_ETSI][0][38] = 18,
+ [0][1][1][0][RTW89_MKK][1][38] = 54,
+ [0][1][1][0][RTW89_MKK][0][38] = 16,
+ [0][1][1][0][RTW89_IC][1][38] = -4,
+ [0][1][1][0][RTW89_KCC][1][38] = 12,
+ [0][1][1][0][RTW89_KCC][0][38] = 14,
+ [0][1][1][0][RTW89_ACMA][1][38] = 54,
+ [0][1][1][0][RTW89_ACMA][0][38] = 18,
+ [0][1][1][0][RTW89_CHILE][1][38] = -4,
+ [0][1][1][0][RTW89_QATAR][1][38] = 54,
+ [0][1][1][0][RTW89_QATAR][0][38] = 18,
+ [0][1][1][0][RTW89_UK][1][38] = 54,
+ [0][1][1][0][RTW89_UK][0][38] = 18,
+ [0][1][1][0][RTW89_FCC][1][40] = -4,
+ [0][1][1][0][RTW89_FCC][2][40] = 68,
+ [0][1][1][0][RTW89_ETSI][1][40] = 54,
+ [0][1][1][0][RTW89_ETSI][0][40] = 18,
+ [0][1][1][0][RTW89_MKK][1][40] = 54,
+ [0][1][1][0][RTW89_MKK][0][40] = 16,
+ [0][1][1][0][RTW89_IC][1][40] = -4,
+ [0][1][1][0][RTW89_KCC][1][40] = 12,
+ [0][1][1][0][RTW89_KCC][0][40] = 14,
+ [0][1][1][0][RTW89_ACMA][1][40] = 54,
+ [0][1][1][0][RTW89_ACMA][0][40] = 18,
+ [0][1][1][0][RTW89_CHILE][1][40] = -4,
+ [0][1][1][0][RTW89_QATAR][1][40] = 54,
+ [0][1][1][0][RTW89_QATAR][0][40] = 18,
+ [0][1][1][0][RTW89_UK][1][40] = 54,
+ [0][1][1][0][RTW89_UK][0][40] = 18,
+ [0][1][1][0][RTW89_FCC][1][42] = -4,
+ [0][1][1][0][RTW89_FCC][2][42] = 68,
+ [0][1][1][0][RTW89_ETSI][1][42] = 54,
+ [0][1][1][0][RTW89_ETSI][0][42] = 18,
+ [0][1][1][0][RTW89_MKK][1][42] = 54,
+ [0][1][1][0][RTW89_MKK][0][42] = 16,
+ [0][1][1][0][RTW89_IC][1][42] = -4,
+ [0][1][1][0][RTW89_KCC][1][42] = 12,
+ [0][1][1][0][RTW89_KCC][0][42] = 14,
+ [0][1][1][0][RTW89_ACMA][1][42] = 54,
+ [0][1][1][0][RTW89_ACMA][0][42] = 18,
+ [0][1][1][0][RTW89_CHILE][1][42] = -4,
+ [0][1][1][0][RTW89_QATAR][1][42] = 54,
+ [0][1][1][0][RTW89_QATAR][0][42] = 18,
+ [0][1][1][0][RTW89_UK][1][42] = 54,
+ [0][1][1][0][RTW89_UK][0][42] = 18,
+ [0][1][1][0][RTW89_FCC][1][44] = -2,
+ [0][1][1][0][RTW89_FCC][2][44] = 68,
+ [0][1][1][0][RTW89_ETSI][1][44] = 54,
+ [0][1][1][0][RTW89_ETSI][0][44] = 18,
+ [0][1][1][0][RTW89_MKK][1][44] = 34,
+ [0][1][1][0][RTW89_MKK][0][44] = 16,
+ [0][1][1][0][RTW89_IC][1][44] = -2,
+ [0][1][1][0][RTW89_KCC][1][44] = 12,
+ [0][1][1][0][RTW89_KCC][0][44] = 12,
+ [0][1][1][0][RTW89_ACMA][1][44] = 54,
+ [0][1][1][0][RTW89_ACMA][0][44] = 18,
+ [0][1][1][0][RTW89_CHILE][1][44] = -2,
+ [0][1][1][0][RTW89_QATAR][1][44] = 54,
+ [0][1][1][0][RTW89_QATAR][0][44] = 18,
+ [0][1][1][0][RTW89_UK][1][44] = 54,
+ [0][1][1][0][RTW89_UK][0][44] = 18,
+ [0][1][1][0][RTW89_FCC][1][45] = -2,
+ [0][1][1][0][RTW89_FCC][2][45] = 127,
+ [0][1][1][0][RTW89_ETSI][1][45] = 127,
+ [0][1][1][0][RTW89_ETSI][0][45] = 127,
+ [0][1][1][0][RTW89_MKK][1][45] = 127,
+ [0][1][1][0][RTW89_MKK][0][45] = 127,
+ [0][1][1][0][RTW89_IC][1][45] = -2,
+ [0][1][1][0][RTW89_KCC][1][45] = 12,
+ [0][1][1][0][RTW89_KCC][0][45] = 127,
+ [0][1][1][0][RTW89_ACMA][1][45] = 127,
+ [0][1][1][0][RTW89_ACMA][0][45] = 127,
+ [0][1][1][0][RTW89_CHILE][1][45] = -2,
+ [0][1][1][0][RTW89_QATAR][1][45] = 127,
+ [0][1][1][0][RTW89_QATAR][0][45] = 127,
+ [0][1][1][0][RTW89_UK][1][45] = 127,
+ [0][1][1][0][RTW89_UK][0][45] = 127,
+ [0][1][1][0][RTW89_FCC][1][47] = -2,
+ [0][1][1][0][RTW89_FCC][2][47] = 127,
+ [0][1][1][0][RTW89_ETSI][1][47] = 127,
+ [0][1][1][0][RTW89_ETSI][0][47] = 127,
+ [0][1][1][0][RTW89_MKK][1][47] = 127,
+ [0][1][1][0][RTW89_MKK][0][47] = 127,
+ [0][1][1][0][RTW89_IC][1][47] = -2,
+ [0][1][1][0][RTW89_KCC][1][47] = 12,
+ [0][1][1][0][RTW89_KCC][0][47] = 127,
+ [0][1][1][0][RTW89_ACMA][1][47] = 127,
+ [0][1][1][0][RTW89_ACMA][0][47] = 127,
+ [0][1][1][0][RTW89_CHILE][1][47] = -2,
+ [0][1][1][0][RTW89_QATAR][1][47] = 127,
+ [0][1][1][0][RTW89_QATAR][0][47] = 127,
+ [0][1][1][0][RTW89_UK][1][47] = 127,
+ [0][1][1][0][RTW89_UK][0][47] = 127,
+ [0][1][1][0][RTW89_FCC][1][49] = -2,
+ [0][1][1][0][RTW89_FCC][2][49] = 127,
+ [0][1][1][0][RTW89_ETSI][1][49] = 127,
+ [0][1][1][0][RTW89_ETSI][0][49] = 127,
+ [0][1][1][0][RTW89_MKK][1][49] = 127,
+ [0][1][1][0][RTW89_MKK][0][49] = 127,
+ [0][1][1][0][RTW89_IC][1][49] = -2,
+ [0][1][1][0][RTW89_KCC][1][49] = 12,
+ [0][1][1][0][RTW89_KCC][0][49] = 127,
+ [0][1][1][0][RTW89_ACMA][1][49] = 127,
+ [0][1][1][0][RTW89_ACMA][0][49] = 127,
+ [0][1][1][0][RTW89_CHILE][1][49] = -2,
+ [0][1][1][0][RTW89_QATAR][1][49] = 127,
+ [0][1][1][0][RTW89_QATAR][0][49] = 127,
+ [0][1][1][0][RTW89_UK][1][49] = 127,
+ [0][1][1][0][RTW89_UK][0][49] = 127,
+ [0][1][1][0][RTW89_FCC][1][51] = -2,
+ [0][1][1][0][RTW89_FCC][2][51] = 127,
+ [0][1][1][0][RTW89_ETSI][1][51] = 127,
+ [0][1][1][0][RTW89_ETSI][0][51] = 127,
+ [0][1][1][0][RTW89_MKK][1][51] = 127,
+ [0][1][1][0][RTW89_MKK][0][51] = 127,
+ [0][1][1][0][RTW89_IC][1][51] = -2,
+ [0][1][1][0][RTW89_KCC][1][51] = 12,
+ [0][1][1][0][RTW89_KCC][0][51] = 127,
+ [0][1][1][0][RTW89_ACMA][1][51] = 127,
+ [0][1][1][0][RTW89_ACMA][0][51] = 127,
+ [0][1][1][0][RTW89_CHILE][1][51] = -2,
+ [0][1][1][0][RTW89_QATAR][1][51] = 127,
+ [0][1][1][0][RTW89_QATAR][0][51] = 127,
+ [0][1][1][0][RTW89_UK][1][51] = 127,
+ [0][1][1][0][RTW89_UK][0][51] = 127,
+ [0][1][1][0][RTW89_FCC][1][53] = -2,
+ [0][1][1][0][RTW89_FCC][2][53] = 127,
+ [0][1][1][0][RTW89_ETSI][1][53] = 127,
+ [0][1][1][0][RTW89_ETSI][0][53] = 127,
+ [0][1][1][0][RTW89_MKK][1][53] = 127,
+ [0][1][1][0][RTW89_MKK][0][53] = 127,
+ [0][1][1][0][RTW89_IC][1][53] = -2,
+ [0][1][1][0][RTW89_KCC][1][53] = 12,
+ [0][1][1][0][RTW89_KCC][0][53] = 127,
+ [0][1][1][0][RTW89_ACMA][1][53] = 127,
+ [0][1][1][0][RTW89_ACMA][0][53] = 127,
+ [0][1][1][0][RTW89_CHILE][1][53] = -2,
+ [0][1][1][0][RTW89_QATAR][1][53] = 127,
+ [0][1][1][0][RTW89_QATAR][0][53] = 127,
+ [0][1][1][0][RTW89_UK][1][53] = 127,
+ [0][1][1][0][RTW89_UK][0][53] = 127,
+ [0][1][1][0][RTW89_FCC][1][55] = -2,
+ [0][1][1][0][RTW89_FCC][2][55] = 68,
+ [0][1][1][0][RTW89_ETSI][1][55] = 127,
+ [0][1][1][0][RTW89_ETSI][0][55] = 127,
+ [0][1][1][0][RTW89_MKK][1][55] = 127,
+ [0][1][1][0][RTW89_MKK][0][55] = 127,
+ [0][1][1][0][RTW89_IC][1][55] = -2,
+ [0][1][1][0][RTW89_KCC][1][55] = 12,
+ [0][1][1][0][RTW89_KCC][0][55] = 127,
+ [0][1][1][0][RTW89_ACMA][1][55] = 127,
+ [0][1][1][0][RTW89_ACMA][0][55] = 127,
+ [0][1][1][0][RTW89_CHILE][1][55] = -2,
+ [0][1][1][0][RTW89_QATAR][1][55] = 127,
+ [0][1][1][0][RTW89_QATAR][0][55] = 127,
+ [0][1][1][0][RTW89_UK][1][55] = 127,
+ [0][1][1][0][RTW89_UK][0][55] = 127,
+ [0][1][1][0][RTW89_FCC][1][57] = -2,
+ [0][1][1][0][RTW89_FCC][2][57] = 68,
+ [0][1][1][0][RTW89_ETSI][1][57] = 127,
+ [0][1][1][0][RTW89_ETSI][0][57] = 127,
+ [0][1][1][0][RTW89_MKK][1][57] = 127,
+ [0][1][1][0][RTW89_MKK][0][57] = 127,
+ [0][1][1][0][RTW89_IC][1][57] = -2,
+ [0][1][1][0][RTW89_KCC][1][57] = 12,
+ [0][1][1][0][RTW89_KCC][0][57] = 127,
+ [0][1][1][0][RTW89_ACMA][1][57] = 127,
+ [0][1][1][0][RTW89_ACMA][0][57] = 127,
+ [0][1][1][0][RTW89_CHILE][1][57] = -2,
+ [0][1][1][0][RTW89_QATAR][1][57] = 127,
+ [0][1][1][0][RTW89_QATAR][0][57] = 127,
+ [0][1][1][0][RTW89_UK][1][57] = 127,
+ [0][1][1][0][RTW89_UK][0][57] = 127,
+ [0][1][1][0][RTW89_FCC][1][59] = -2,
+ [0][1][1][0][RTW89_FCC][2][59] = 68,
+ [0][1][1][0][RTW89_ETSI][1][59] = 127,
+ [0][1][1][0][RTW89_ETSI][0][59] = 127,
+ [0][1][1][0][RTW89_MKK][1][59] = 127,
+ [0][1][1][0][RTW89_MKK][0][59] = 127,
+ [0][1][1][0][RTW89_IC][1][59] = -2,
+ [0][1][1][0][RTW89_KCC][1][59] = 12,
+ [0][1][1][0][RTW89_KCC][0][59] = 127,
+ [0][1][1][0][RTW89_ACMA][1][59] = 127,
+ [0][1][1][0][RTW89_ACMA][0][59] = 127,
+ [0][1][1][0][RTW89_CHILE][1][59] = -2,
+ [0][1][1][0][RTW89_QATAR][1][59] = 127,
+ [0][1][1][0][RTW89_QATAR][0][59] = 127,
+ [0][1][1][0][RTW89_UK][1][59] = 127,
+ [0][1][1][0][RTW89_UK][0][59] = 127,
+ [0][1][1][0][RTW89_FCC][1][60] = -2,
+ [0][1][1][0][RTW89_FCC][2][60] = 68,
+ [0][1][1][0][RTW89_ETSI][1][60] = 127,
+ [0][1][1][0][RTW89_ETSI][0][60] = 127,
+ [0][1][1][0][RTW89_MKK][1][60] = 127,
+ [0][1][1][0][RTW89_MKK][0][60] = 127,
+ [0][1][1][0][RTW89_IC][1][60] = -2,
+ [0][1][1][0][RTW89_KCC][1][60] = 12,
+ [0][1][1][0][RTW89_KCC][0][60] = 127,
+ [0][1][1][0][RTW89_ACMA][1][60] = 127,
+ [0][1][1][0][RTW89_ACMA][0][60] = 127,
+ [0][1][1][0][RTW89_CHILE][1][60] = -2,
+ [0][1][1][0][RTW89_QATAR][1][60] = 127,
+ [0][1][1][0][RTW89_QATAR][0][60] = 127,
+ [0][1][1][0][RTW89_UK][1][60] = 127,
+ [0][1][1][0][RTW89_UK][0][60] = 127,
+ [0][1][1][0][RTW89_FCC][1][62] = -2,
+ [0][1][1][0][RTW89_FCC][2][62] = 68,
+ [0][1][1][0][RTW89_ETSI][1][62] = 127,
+ [0][1][1][0][RTW89_ETSI][0][62] = 127,
+ [0][1][1][0][RTW89_MKK][1][62] = 127,
+ [0][1][1][0][RTW89_MKK][0][62] = 127,
+ [0][1][1][0][RTW89_IC][1][62] = -2,
+ [0][1][1][0][RTW89_KCC][1][62] = 12,
+ [0][1][1][0][RTW89_KCC][0][62] = 127,
+ [0][1][1][0][RTW89_ACMA][1][62] = 127,
+ [0][1][1][0][RTW89_ACMA][0][62] = 127,
+ [0][1][1][0][RTW89_CHILE][1][62] = -2,
+ [0][1][1][0][RTW89_QATAR][1][62] = 127,
+ [0][1][1][0][RTW89_QATAR][0][62] = 127,
+ [0][1][1][0][RTW89_UK][1][62] = 127,
+ [0][1][1][0][RTW89_UK][0][62] = 127,
+ [0][1][1][0][RTW89_FCC][1][64] = -2,
+ [0][1][1][0][RTW89_FCC][2][64] = 68,
+ [0][1][1][0][RTW89_ETSI][1][64] = 127,
+ [0][1][1][0][RTW89_ETSI][0][64] = 127,
+ [0][1][1][0][RTW89_MKK][1][64] = 127,
+ [0][1][1][0][RTW89_MKK][0][64] = 127,
+ [0][1][1][0][RTW89_IC][1][64] = -2,
+ [0][1][1][0][RTW89_KCC][1][64] = 12,
+ [0][1][1][0][RTW89_KCC][0][64] = 127,
+ [0][1][1][0][RTW89_ACMA][1][64] = 127,
+ [0][1][1][0][RTW89_ACMA][0][64] = 127,
+ [0][1][1][0][RTW89_CHILE][1][64] = -2,
+ [0][1][1][0][RTW89_QATAR][1][64] = 127,
+ [0][1][1][0][RTW89_QATAR][0][64] = 127,
+ [0][1][1][0][RTW89_UK][1][64] = 127,
+ [0][1][1][0][RTW89_UK][0][64] = 127,
+ [0][1][1][0][RTW89_FCC][1][66] = -2,
+ [0][1][1][0][RTW89_FCC][2][66] = 68,
+ [0][1][1][0][RTW89_ETSI][1][66] = 127,
+ [0][1][1][0][RTW89_ETSI][0][66] = 127,
+ [0][1][1][0][RTW89_MKK][1][66] = 127,
+ [0][1][1][0][RTW89_MKK][0][66] = 127,
+ [0][1][1][0][RTW89_IC][1][66] = -2,
+ [0][1][1][0][RTW89_KCC][1][66] = 12,
+ [0][1][1][0][RTW89_KCC][0][66] = 127,
+ [0][1][1][0][RTW89_ACMA][1][66] = 127,
+ [0][1][1][0][RTW89_ACMA][0][66] = 127,
+ [0][1][1][0][RTW89_CHILE][1][66] = -2,
+ [0][1][1][0][RTW89_QATAR][1][66] = 127,
+ [0][1][1][0][RTW89_QATAR][0][66] = 127,
+ [0][1][1][0][RTW89_UK][1][66] = 127,
+ [0][1][1][0][RTW89_UK][0][66] = 127,
+ [0][1][1][0][RTW89_FCC][1][68] = -2,
+ [0][1][1][0][RTW89_FCC][2][68] = 68,
+ [0][1][1][0][RTW89_ETSI][1][68] = 127,
+ [0][1][1][0][RTW89_ETSI][0][68] = 127,
+ [0][1][1][0][RTW89_MKK][1][68] = 127,
+ [0][1][1][0][RTW89_MKK][0][68] = 127,
+ [0][1][1][0][RTW89_IC][1][68] = -2,
+ [0][1][1][0][RTW89_KCC][1][68] = 12,
+ [0][1][1][0][RTW89_KCC][0][68] = 127,
+ [0][1][1][0][RTW89_ACMA][1][68] = 127,
+ [0][1][1][0][RTW89_ACMA][0][68] = 127,
+ [0][1][1][0][RTW89_CHILE][1][68] = -2,
+ [0][1][1][0][RTW89_QATAR][1][68] = 127,
+ [0][1][1][0][RTW89_QATAR][0][68] = 127,
+ [0][1][1][0][RTW89_UK][1][68] = 127,
+ [0][1][1][0][RTW89_UK][0][68] = 127,
+ [0][1][1][0][RTW89_FCC][1][70] = -2,
+ [0][1][1][0][RTW89_FCC][2][70] = 68,
+ [0][1][1][0][RTW89_ETSI][1][70] = 127,
+ [0][1][1][0][RTW89_ETSI][0][70] = 127,
+ [0][1][1][0][RTW89_MKK][1][70] = 127,
+ [0][1][1][0][RTW89_MKK][0][70] = 127,
+ [0][1][1][0][RTW89_IC][1][70] = -2,
+ [0][1][1][0][RTW89_KCC][1][70] = 12,
+ [0][1][1][0][RTW89_KCC][0][70] = 127,
+ [0][1][1][0][RTW89_ACMA][1][70] = 127,
+ [0][1][1][0][RTW89_ACMA][0][70] = 127,
+ [0][1][1][0][RTW89_CHILE][1][70] = -2,
+ [0][1][1][0][RTW89_QATAR][1][70] = 127,
+ [0][1][1][0][RTW89_QATAR][0][70] = 127,
+ [0][1][1][0][RTW89_UK][1][70] = 127,
+ [0][1][1][0][RTW89_UK][0][70] = 127,
+ [0][1][1][0][RTW89_FCC][1][72] = -2,
+ [0][1][1][0][RTW89_FCC][2][72] = 68,
+ [0][1][1][0][RTW89_ETSI][1][72] = 127,
+ [0][1][1][0][RTW89_ETSI][0][72] = 127,
+ [0][1][1][0][RTW89_MKK][1][72] = 127,
+ [0][1][1][0][RTW89_MKK][0][72] = 127,
+ [0][1][1][0][RTW89_IC][1][72] = -2,
+ [0][1][1][0][RTW89_KCC][1][72] = 12,
+ [0][1][1][0][RTW89_KCC][0][72] = 127,
+ [0][1][1][0][RTW89_ACMA][1][72] = 127,
+ [0][1][1][0][RTW89_ACMA][0][72] = 127,
+ [0][1][1][0][RTW89_CHILE][1][72] = -2,
+ [0][1][1][0][RTW89_QATAR][1][72] = 127,
+ [0][1][1][0][RTW89_QATAR][0][72] = 127,
+ [0][1][1][0][RTW89_UK][1][72] = 127,
+ [0][1][1][0][RTW89_UK][0][72] = 127,
+ [0][1][1][0][RTW89_FCC][1][74] = -2,
+ [0][1][1][0][RTW89_FCC][2][74] = 68,
+ [0][1][1][0][RTW89_ETSI][1][74] = 127,
+ [0][1][1][0][RTW89_ETSI][0][74] = 127,
+ [0][1][1][0][RTW89_MKK][1][74] = 127,
+ [0][1][1][0][RTW89_MKK][0][74] = 127,
+ [0][1][1][0][RTW89_IC][1][74] = -2,
+ [0][1][1][0][RTW89_KCC][1][74] = 12,
+ [0][1][1][0][RTW89_KCC][0][74] = 127,
+ [0][1][1][0][RTW89_ACMA][1][74] = 127,
+ [0][1][1][0][RTW89_ACMA][0][74] = 127,
+ [0][1][1][0][RTW89_CHILE][1][74] = -2,
+ [0][1][1][0][RTW89_QATAR][1][74] = 127,
+ [0][1][1][0][RTW89_QATAR][0][74] = 127,
+ [0][1][1][0][RTW89_UK][1][74] = 127,
+ [0][1][1][0][RTW89_UK][0][74] = 127,
+ [0][1][1][0][RTW89_FCC][1][75] = -2,
+ [0][1][1][0][RTW89_FCC][2][75] = 68,
+ [0][1][1][0][RTW89_ETSI][1][75] = 127,
+ [0][1][1][0][RTW89_ETSI][0][75] = 127,
+ [0][1][1][0][RTW89_MKK][1][75] = 127,
+ [0][1][1][0][RTW89_MKK][0][75] = 127,
+ [0][1][1][0][RTW89_IC][1][75] = -2,
+ [0][1][1][0][RTW89_KCC][1][75] = 12,
+ [0][1][1][0][RTW89_KCC][0][75] = 127,
+ [0][1][1][0][RTW89_ACMA][1][75] = 127,
+ [0][1][1][0][RTW89_ACMA][0][75] = 127,
+ [0][1][1][0][RTW89_CHILE][1][75] = -2,
+ [0][1][1][0][RTW89_QATAR][1][75] = 127,
+ [0][1][1][0][RTW89_QATAR][0][75] = 127,
+ [0][1][1][0][RTW89_UK][1][75] = 127,
+ [0][1][1][0][RTW89_UK][0][75] = 127,
+ [0][1][1][0][RTW89_FCC][1][77] = -2,
+ [0][1][1][0][RTW89_FCC][2][77] = 68,
+ [0][1][1][0][RTW89_ETSI][1][77] = 127,
+ [0][1][1][0][RTW89_ETSI][0][77] = 127,
+ [0][1][1][0][RTW89_MKK][1][77] = 127,
+ [0][1][1][0][RTW89_MKK][0][77] = 127,
+ [0][1][1][0][RTW89_IC][1][77] = -2,
+ [0][1][1][0][RTW89_KCC][1][77] = 12,
+ [0][1][1][0][RTW89_KCC][0][77] = 127,
+ [0][1][1][0][RTW89_ACMA][1][77] = 127,
+ [0][1][1][0][RTW89_ACMA][0][77] = 127,
+ [0][1][1][0][RTW89_CHILE][1][77] = -2,
+ [0][1][1][0][RTW89_QATAR][1][77] = 127,
+ [0][1][1][0][RTW89_QATAR][0][77] = 127,
+ [0][1][1][0][RTW89_UK][1][77] = 127,
+ [0][1][1][0][RTW89_UK][0][77] = 127,
+ [0][1][1][0][RTW89_FCC][1][79] = -2,
+ [0][1][1][0][RTW89_FCC][2][79] = 68,
+ [0][1][1][0][RTW89_ETSI][1][79] = 127,
+ [0][1][1][0][RTW89_ETSI][0][79] = 127,
+ [0][1][1][0][RTW89_MKK][1][79] = 127,
+ [0][1][1][0][RTW89_MKK][0][79] = 127,
+ [0][1][1][0][RTW89_IC][1][79] = -2,
+ [0][1][1][0][RTW89_KCC][1][79] = 12,
+ [0][1][1][0][RTW89_KCC][0][79] = 127,
+ [0][1][1][0][RTW89_ACMA][1][79] = 127,
+ [0][1][1][0][RTW89_ACMA][0][79] = 127,
+ [0][1][1][0][RTW89_CHILE][1][79] = -2,
+ [0][1][1][0][RTW89_QATAR][1][79] = 127,
+ [0][1][1][0][RTW89_QATAR][0][79] = 127,
+ [0][1][1][0][RTW89_UK][1][79] = 127,
+ [0][1][1][0][RTW89_UK][0][79] = 127,
+ [0][1][1][0][RTW89_FCC][1][81] = -2,
+ [0][1][1][0][RTW89_FCC][2][81] = 68,
+ [0][1][1][0][RTW89_ETSI][1][81] = 127,
+ [0][1][1][0][RTW89_ETSI][0][81] = 127,
+ [0][1][1][0][RTW89_MKK][1][81] = 127,
+ [0][1][1][0][RTW89_MKK][0][81] = 127,
+ [0][1][1][0][RTW89_IC][1][81] = -2,
+ [0][1][1][0][RTW89_KCC][1][81] = 12,
+ [0][1][1][0][RTW89_KCC][0][81] = 127,
+ [0][1][1][0][RTW89_ACMA][1][81] = 127,
+ [0][1][1][0][RTW89_ACMA][0][81] = 127,
+ [0][1][1][0][RTW89_CHILE][1][81] = -2,
+ [0][1][1][0][RTW89_QATAR][1][81] = 127,
+ [0][1][1][0][RTW89_QATAR][0][81] = 127,
+ [0][1][1][0][RTW89_UK][1][81] = 127,
+ [0][1][1][0][RTW89_UK][0][81] = 127,
+ [0][1][1][0][RTW89_FCC][1][83] = -2,
+ [0][1][1][0][RTW89_FCC][2][83] = 68,
+ [0][1][1][0][RTW89_ETSI][1][83] = 127,
+ [0][1][1][0][RTW89_ETSI][0][83] = 127,
+ [0][1][1][0][RTW89_MKK][1][83] = 127,
+ [0][1][1][0][RTW89_MKK][0][83] = 127,
+ [0][1][1][0][RTW89_IC][1][83] = -2,
+ [0][1][1][0][RTW89_KCC][1][83] = 20,
+ [0][1][1][0][RTW89_KCC][0][83] = 127,
+ [0][1][1][0][RTW89_ACMA][1][83] = 127,
+ [0][1][1][0][RTW89_ACMA][0][83] = 127,
+ [0][1][1][0][RTW89_CHILE][1][83] = -2,
+ [0][1][1][0][RTW89_QATAR][1][83] = 127,
+ [0][1][1][0][RTW89_QATAR][0][83] = 127,
+ [0][1][1][0][RTW89_UK][1][83] = 127,
+ [0][1][1][0][RTW89_UK][0][83] = 127,
+ [0][1][1][0][RTW89_FCC][1][85] = -2,
+ [0][1][1][0][RTW89_FCC][2][85] = 68,
+ [0][1][1][0][RTW89_ETSI][1][85] = 127,
+ [0][1][1][0][RTW89_ETSI][0][85] = 127,
+ [0][1][1][0][RTW89_MKK][1][85] = 127,
+ [0][1][1][0][RTW89_MKK][0][85] = 127,
+ [0][1][1][0][RTW89_IC][1][85] = -2,
+ [0][1][1][0][RTW89_KCC][1][85] = 20,
+ [0][1][1][0][RTW89_KCC][0][85] = 127,
+ [0][1][1][0][RTW89_ACMA][1][85] = 127,
+ [0][1][1][0][RTW89_ACMA][0][85] = 127,
+ [0][1][1][0][RTW89_CHILE][1][85] = -2,
+ [0][1][1][0][RTW89_QATAR][1][85] = 127,
+ [0][1][1][0][RTW89_QATAR][0][85] = 127,
+ [0][1][1][0][RTW89_UK][1][85] = 127,
+ [0][1][1][0][RTW89_UK][0][85] = 127,
+ [0][1][1][0][RTW89_FCC][1][87] = -2,
+ [0][1][1][0][RTW89_FCC][2][87] = 127,
+ [0][1][1][0][RTW89_ETSI][1][87] = 127,
+ [0][1][1][0][RTW89_ETSI][0][87] = 127,
+ [0][1][1][0][RTW89_MKK][1][87] = 127,
+ [0][1][1][0][RTW89_MKK][0][87] = 127,
+ [0][1][1][0][RTW89_IC][1][87] = -2,
+ [0][1][1][0][RTW89_KCC][1][87] = 20,
+ [0][1][1][0][RTW89_KCC][0][87] = 127,
+ [0][1][1][0][RTW89_ACMA][1][87] = 127,
+ [0][1][1][0][RTW89_ACMA][0][87] = 127,
+ [0][1][1][0][RTW89_CHILE][1][87] = -2,
+ [0][1][1][0][RTW89_QATAR][1][87] = 127,
+ [0][1][1][0][RTW89_QATAR][0][87] = 127,
+ [0][1][1][0][RTW89_UK][1][87] = 127,
+ [0][1][1][0][RTW89_UK][0][87] = 127,
+ [0][1][1][0][RTW89_FCC][1][89] = -2,
+ [0][1][1][0][RTW89_FCC][2][89] = 127,
+ [0][1][1][0][RTW89_ETSI][1][89] = 127,
+ [0][1][1][0][RTW89_ETSI][0][89] = 127,
+ [0][1][1][0][RTW89_MKK][1][89] = 127,
+ [0][1][1][0][RTW89_MKK][0][89] = 127,
+ [0][1][1][0][RTW89_IC][1][89] = -2,
+ [0][1][1][0][RTW89_KCC][1][89] = 20,
+ [0][1][1][0][RTW89_KCC][0][89] = 127,
+ [0][1][1][0][RTW89_ACMA][1][89] = 127,
+ [0][1][1][0][RTW89_ACMA][0][89] = 127,
+ [0][1][1][0][RTW89_CHILE][1][89] = -2,
+ [0][1][1][0][RTW89_QATAR][1][89] = 127,
+ [0][1][1][0][RTW89_QATAR][0][89] = 127,
+ [0][1][1][0][RTW89_UK][1][89] = 127,
+ [0][1][1][0][RTW89_UK][0][89] = 127,
+ [0][1][1][0][RTW89_FCC][1][90] = -2,
+ [0][1][1][0][RTW89_FCC][2][90] = 127,
+ [0][1][1][0][RTW89_ETSI][1][90] = 127,
+ [0][1][1][0][RTW89_ETSI][0][90] = 127,
+ [0][1][1][0][RTW89_MKK][1][90] = 127,
+ [0][1][1][0][RTW89_MKK][0][90] = 127,
+ [0][1][1][0][RTW89_IC][1][90] = -2,
+ [0][1][1][0][RTW89_KCC][1][90] = 20,
+ [0][1][1][0][RTW89_KCC][0][90] = 127,
+ [0][1][1][0][RTW89_ACMA][1][90] = 127,
+ [0][1][1][0][RTW89_ACMA][0][90] = 127,
+ [0][1][1][0][RTW89_CHILE][1][90] = -2,
+ [0][1][1][0][RTW89_QATAR][1][90] = 127,
+ [0][1][1][0][RTW89_QATAR][0][90] = 127,
+ [0][1][1][0][RTW89_UK][1][90] = 127,
+ [0][1][1][0][RTW89_UK][0][90] = 127,
+ [0][1][1][0][RTW89_FCC][1][92] = -2,
+ [0][1][1][0][RTW89_FCC][2][92] = 127,
+ [0][1][1][0][RTW89_ETSI][1][92] = 127,
+ [0][1][1][0][RTW89_ETSI][0][92] = 127,
+ [0][1][1][0][RTW89_MKK][1][92] = 127,
+ [0][1][1][0][RTW89_MKK][0][92] = 127,
+ [0][1][1][0][RTW89_IC][1][92] = -2,
+ [0][1][1][0][RTW89_KCC][1][92] = 20,
+ [0][1][1][0][RTW89_KCC][0][92] = 127,
+ [0][1][1][0][RTW89_ACMA][1][92] = 127,
+ [0][1][1][0][RTW89_ACMA][0][92] = 127,
+ [0][1][1][0][RTW89_CHILE][1][92] = -2,
+ [0][1][1][0][RTW89_QATAR][1][92] = 127,
+ [0][1][1][0][RTW89_QATAR][0][92] = 127,
+ [0][1][1][0][RTW89_UK][1][92] = 127,
+ [0][1][1][0][RTW89_UK][0][92] = 127,
+ [0][1][1][0][RTW89_FCC][1][94] = -2,
+ [0][1][1][0][RTW89_FCC][2][94] = 127,
+ [0][1][1][0][RTW89_ETSI][1][94] = 127,
+ [0][1][1][0][RTW89_ETSI][0][94] = 127,
+ [0][1][1][0][RTW89_MKK][1][94] = 127,
+ [0][1][1][0][RTW89_MKK][0][94] = 127,
+ [0][1][1][0][RTW89_IC][1][94] = -2,
+ [0][1][1][0][RTW89_KCC][1][94] = 20,
+ [0][1][1][0][RTW89_KCC][0][94] = 127,
+ [0][1][1][0][RTW89_ACMA][1][94] = 127,
+ [0][1][1][0][RTW89_ACMA][0][94] = 127,
+ [0][1][1][0][RTW89_CHILE][1][94] = -2,
+ [0][1][1][0][RTW89_QATAR][1][94] = 127,
+ [0][1][1][0][RTW89_QATAR][0][94] = 127,
+ [0][1][1][0][RTW89_UK][1][94] = 127,
+ [0][1][1][0][RTW89_UK][0][94] = 127,
+ [0][1][1][0][RTW89_FCC][1][96] = -2,
+ [0][1][1][0][RTW89_FCC][2][96] = 127,
+ [0][1][1][0][RTW89_ETSI][1][96] = 127,
+ [0][1][1][0][RTW89_ETSI][0][96] = 127,
+ [0][1][1][0][RTW89_MKK][1][96] = 127,
+ [0][1][1][0][RTW89_MKK][0][96] = 127,
+ [0][1][1][0][RTW89_IC][1][96] = -2,
+ [0][1][1][0][RTW89_KCC][1][96] = 20,
+ [0][1][1][0][RTW89_KCC][0][96] = 127,
+ [0][1][1][0][RTW89_ACMA][1][96] = 127,
+ [0][1][1][0][RTW89_ACMA][0][96] = 127,
+ [0][1][1][0][RTW89_CHILE][1][96] = -2,
+ [0][1][1][0][RTW89_QATAR][1][96] = 127,
+ [0][1][1][0][RTW89_QATAR][0][96] = 127,
+ [0][1][1][0][RTW89_UK][1][96] = 127,
+ [0][1][1][0][RTW89_UK][0][96] = 127,
+ [0][1][1][0][RTW89_FCC][1][98] = -2,
+ [0][1][1][0][RTW89_FCC][2][98] = 127,
+ [0][1][1][0][RTW89_ETSI][1][98] = 127,
+ [0][1][1][0][RTW89_ETSI][0][98] = 127,
+ [0][1][1][0][RTW89_MKK][1][98] = 127,
+ [0][1][1][0][RTW89_MKK][0][98] = 127,
+ [0][1][1][0][RTW89_IC][1][98] = -2,
+ [0][1][1][0][RTW89_KCC][1][98] = 20,
+ [0][1][1][0][RTW89_KCC][0][98] = 127,
+ [0][1][1][0][RTW89_ACMA][1][98] = 127,
+ [0][1][1][0][RTW89_ACMA][0][98] = 127,
+ [0][1][1][0][RTW89_CHILE][1][98] = -2,
+ [0][1][1][0][RTW89_QATAR][1][98] = 127,
+ [0][1][1][0][RTW89_QATAR][0][98] = 127,
+ [0][1][1][0][RTW89_UK][1][98] = 127,
+ [0][1][1][0][RTW89_UK][0][98] = 127,
+ [0][1][1][0][RTW89_FCC][1][100] = -2,
+ [0][1][1][0][RTW89_FCC][2][100] = 127,
+ [0][1][1][0][RTW89_ETSI][1][100] = 127,
+ [0][1][1][0][RTW89_ETSI][0][100] = 127,
+ [0][1][1][0][RTW89_MKK][1][100] = 127,
+ [0][1][1][0][RTW89_MKK][0][100] = 127,
+ [0][1][1][0][RTW89_IC][1][100] = -2,
+ [0][1][1][0][RTW89_KCC][1][100] = 20,
+ [0][1][1][0][RTW89_KCC][0][100] = 127,
+ [0][1][1][0][RTW89_ACMA][1][100] = 127,
+ [0][1][1][0][RTW89_ACMA][0][100] = 127,
+ [0][1][1][0][RTW89_CHILE][1][100] = -2,
+ [0][1][1][0][RTW89_QATAR][1][100] = 127,
+ [0][1][1][0][RTW89_QATAR][0][100] = 127,
+ [0][1][1][0][RTW89_UK][1][100] = 127,
+ [0][1][1][0][RTW89_UK][0][100] = 127,
+ [0][1][1][0][RTW89_FCC][1][102] = -2,
+ [0][1][1][0][RTW89_FCC][2][102] = 127,
+ [0][1][1][0][RTW89_ETSI][1][102] = 127,
+ [0][1][1][0][RTW89_ETSI][0][102] = 127,
+ [0][1][1][0][RTW89_MKK][1][102] = 127,
+ [0][1][1][0][RTW89_MKK][0][102] = 127,
+ [0][1][1][0][RTW89_IC][1][102] = -2,
+ [0][1][1][0][RTW89_KCC][1][102] = 20,
+ [0][1][1][0][RTW89_KCC][0][102] = 127,
+ [0][1][1][0][RTW89_ACMA][1][102] = 127,
+ [0][1][1][0][RTW89_ACMA][0][102] = 127,
+ [0][1][1][0][RTW89_CHILE][1][102] = -2,
+ [0][1][1][0][RTW89_QATAR][1][102] = 127,
+ [0][1][1][0][RTW89_QATAR][0][102] = 127,
+ [0][1][1][0][RTW89_UK][1][102] = 127,
+ [0][1][1][0][RTW89_UK][0][102] = 127,
+ [0][1][1][0][RTW89_FCC][1][104] = -2,
+ [0][1][1][0][RTW89_FCC][2][104] = 127,
+ [0][1][1][0][RTW89_ETSI][1][104] = 127,
+ [0][1][1][0][RTW89_ETSI][0][104] = 127,
+ [0][1][1][0][RTW89_MKK][1][104] = 127,
+ [0][1][1][0][RTW89_MKK][0][104] = 127,
+ [0][1][1][0][RTW89_IC][1][104] = -2,
+ [0][1][1][0][RTW89_KCC][1][104] = 20,
+ [0][1][1][0][RTW89_KCC][0][104] = 127,
+ [0][1][1][0][RTW89_ACMA][1][104] = 127,
+ [0][1][1][0][RTW89_ACMA][0][104] = 127,
+ [0][1][1][0][RTW89_CHILE][1][104] = -2,
+ [0][1][1][0][RTW89_QATAR][1][104] = 127,
+ [0][1][1][0][RTW89_QATAR][0][104] = 127,
+ [0][1][1][0][RTW89_UK][1][104] = 127,
+ [0][1][1][0][RTW89_UK][0][104] = 127,
+ [0][1][1][0][RTW89_FCC][1][105] = -2,
+ [0][1][1][0][RTW89_FCC][2][105] = 127,
+ [0][1][1][0][RTW89_ETSI][1][105] = 127,
+ [0][1][1][0][RTW89_ETSI][0][105] = 127,
+ [0][1][1][0][RTW89_MKK][1][105] = 127,
+ [0][1][1][0][RTW89_MKK][0][105] = 127,
+ [0][1][1][0][RTW89_IC][1][105] = -2,
+ [0][1][1][0][RTW89_KCC][1][105] = 20,
+ [0][1][1][0][RTW89_KCC][0][105] = 127,
+ [0][1][1][0][RTW89_ACMA][1][105] = 127,
+ [0][1][1][0][RTW89_ACMA][0][105] = 127,
+ [0][1][1][0][RTW89_CHILE][1][105] = -2,
+ [0][1][1][0][RTW89_QATAR][1][105] = 127,
+ [0][1][1][0][RTW89_QATAR][0][105] = 127,
+ [0][1][1][0][RTW89_UK][1][105] = 127,
+ [0][1][1][0][RTW89_UK][0][105] = 127,
+ [0][1][1][0][RTW89_FCC][1][107] = 1,
+ [0][1][1][0][RTW89_FCC][2][107] = 127,
+ [0][1][1][0][RTW89_ETSI][1][107] = 127,
+ [0][1][1][0][RTW89_ETSI][0][107] = 127,
+ [0][1][1][0][RTW89_MKK][1][107] = 127,
+ [0][1][1][0][RTW89_MKK][0][107] = 127,
+ [0][1][1][0][RTW89_IC][1][107] = 1,
+ [0][1][1][0][RTW89_KCC][1][107] = 20,
+ [0][1][1][0][RTW89_KCC][0][107] = 127,
+ [0][1][1][0][RTW89_ACMA][1][107] = 127,
+ [0][1][1][0][RTW89_ACMA][0][107] = 127,
+ [0][1][1][0][RTW89_CHILE][1][107] = 1,
+ [0][1][1][0][RTW89_QATAR][1][107] = 127,
+ [0][1][1][0][RTW89_QATAR][0][107] = 127,
+ [0][1][1][0][RTW89_UK][1][107] = 127,
+ [0][1][1][0][RTW89_UK][0][107] = 127,
+ [0][1][1][0][RTW89_FCC][1][109] = 1,
+ [0][1][1][0][RTW89_FCC][2][109] = 127,
+ [0][1][1][0][RTW89_ETSI][1][109] = 127,
+ [0][1][1][0][RTW89_ETSI][0][109] = 127,
+ [0][1][1][0][RTW89_MKK][1][109] = 127,
+ [0][1][1][0][RTW89_MKK][0][109] = 127,
+ [0][1][1][0][RTW89_IC][1][109] = 1,
+ [0][1][1][0][RTW89_KCC][1][109] = 20,
+ [0][1][1][0][RTW89_KCC][0][109] = 127,
+ [0][1][1][0][RTW89_ACMA][1][109] = 127,
+ [0][1][1][0][RTW89_ACMA][0][109] = 127,
+ [0][1][1][0][RTW89_CHILE][1][109] = 1,
+ [0][1][1][0][RTW89_QATAR][1][109] = 127,
+ [0][1][1][0][RTW89_QATAR][0][109] = 127,
+ [0][1][1][0][RTW89_UK][1][109] = 127,
+ [0][1][1][0][RTW89_UK][0][109] = 127,
+ [0][1][1][0][RTW89_FCC][1][111] = 127,
+ [0][1][1][0][RTW89_FCC][2][111] = 127,
+ [0][1][1][0][RTW89_ETSI][1][111] = 127,
+ [0][1][1][0][RTW89_ETSI][0][111] = 127,
+ [0][1][1][0][RTW89_MKK][1][111] = 127,
+ [0][1][1][0][RTW89_MKK][0][111] = 127,
+ [0][1][1][0][RTW89_IC][1][111] = 127,
+ [0][1][1][0][RTW89_KCC][1][111] = 127,
+ [0][1][1][0][RTW89_KCC][0][111] = 127,
+ [0][1][1][0][RTW89_ACMA][1][111] = 127,
+ [0][1][1][0][RTW89_ACMA][0][111] = 127,
+ [0][1][1][0][RTW89_CHILE][1][111] = 127,
+ [0][1][1][0][RTW89_QATAR][1][111] = 127,
+ [0][1][1][0][RTW89_QATAR][0][111] = 127,
+ [0][1][1][0][RTW89_UK][1][111] = 127,
+ [0][1][1][0][RTW89_UK][0][111] = 127,
+ [0][1][1][0][RTW89_FCC][1][113] = 127,
+ [0][1][1][0][RTW89_FCC][2][113] = 127,
+ [0][1][1][0][RTW89_ETSI][1][113] = 127,
+ [0][1][1][0][RTW89_ETSI][0][113] = 127,
+ [0][1][1][0][RTW89_MKK][1][113] = 127,
+ [0][1][1][0][RTW89_MKK][0][113] = 127,
+ [0][1][1][0][RTW89_IC][1][113] = 127,
+ [0][1][1][0][RTW89_KCC][1][113] = 127,
+ [0][1][1][0][RTW89_KCC][0][113] = 127,
+ [0][1][1][0][RTW89_ACMA][1][113] = 127,
+ [0][1][1][0][RTW89_ACMA][0][113] = 127,
+ [0][1][1][0][RTW89_CHILE][1][113] = 127,
+ [0][1][1][0][RTW89_QATAR][1][113] = 127,
+ [0][1][1][0][RTW89_QATAR][0][113] = 127,
+ [0][1][1][0][RTW89_UK][1][113] = 127,
+ [0][1][1][0][RTW89_UK][0][113] = 127,
+ [0][1][1][0][RTW89_FCC][1][115] = 127,
+ [0][1][1][0][RTW89_FCC][2][115] = 127,
+ [0][1][1][0][RTW89_ETSI][1][115] = 127,
+ [0][1][1][0][RTW89_ETSI][0][115] = 127,
+ [0][1][1][0][RTW89_MKK][1][115] = 127,
+ [0][1][1][0][RTW89_MKK][0][115] = 127,
+ [0][1][1][0][RTW89_IC][1][115] = 127,
+ [0][1][1][0][RTW89_KCC][1][115] = 127,
+ [0][1][1][0][RTW89_KCC][0][115] = 127,
+ [0][1][1][0][RTW89_ACMA][1][115] = 127,
+ [0][1][1][0][RTW89_ACMA][0][115] = 127,
+ [0][1][1][0][RTW89_CHILE][1][115] = 127,
+ [0][1][1][0][RTW89_QATAR][1][115] = 127,
+ [0][1][1][0][RTW89_QATAR][0][115] = 127,
+ [0][1][1][0][RTW89_UK][1][115] = 127,
+ [0][1][1][0][RTW89_UK][0][115] = 127,
+ [0][1][1][0][RTW89_FCC][1][117] = 127,
+ [0][1][1][0][RTW89_FCC][2][117] = 127,
+ [0][1][1][0][RTW89_ETSI][1][117] = 127,
+ [0][1][1][0][RTW89_ETSI][0][117] = 127,
+ [0][1][1][0][RTW89_MKK][1][117] = 127,
+ [0][1][1][0][RTW89_MKK][0][117] = 127,
+ [0][1][1][0][RTW89_IC][1][117] = 127,
+ [0][1][1][0][RTW89_KCC][1][117] = 127,
+ [0][1][1][0][RTW89_KCC][0][117] = 127,
+ [0][1][1][0][RTW89_ACMA][1][117] = 127,
+ [0][1][1][0][RTW89_ACMA][0][117] = 127,
+ [0][1][1][0][RTW89_CHILE][1][117] = 127,
+ [0][1][1][0][RTW89_QATAR][1][117] = 127,
+ [0][1][1][0][RTW89_QATAR][0][117] = 127,
+ [0][1][1][0][RTW89_UK][1][117] = 127,
+ [0][1][1][0][RTW89_UK][0][117] = 127,
+ [0][1][1][0][RTW89_FCC][1][119] = 127,
+ [0][1][1][0][RTW89_FCC][2][119] = 127,
+ [0][1][1][0][RTW89_ETSI][1][119] = 127,
+ [0][1][1][0][RTW89_ETSI][0][119] = 127,
+ [0][1][1][0][RTW89_MKK][1][119] = 127,
+ [0][1][1][0][RTW89_MKK][0][119] = 127,
+ [0][1][1][0][RTW89_IC][1][119] = 127,
+ [0][1][1][0][RTW89_KCC][1][119] = 127,
+ [0][1][1][0][RTW89_KCC][0][119] = 127,
+ [0][1][1][0][RTW89_ACMA][1][119] = 127,
+ [0][1][1][0][RTW89_ACMA][0][119] = 127,
+ [0][1][1][0][RTW89_CHILE][1][119] = 127,
+ [0][1][1][0][RTW89_QATAR][1][119] = 127,
+ [0][1][1][0][RTW89_QATAR][0][119] = 127,
+ [0][1][1][0][RTW89_UK][1][119] = 127,
+ [0][1][1][0][RTW89_UK][0][119] = 127,
+ [0][0][2][0][RTW89_FCC][1][0] = 24,
+ [0][0][2][0][RTW89_FCC][2][0] = 56,
+ [0][0][2][0][RTW89_ETSI][1][0] = 66,
+ [0][0][2][0][RTW89_ETSI][0][0] = 28,
+ [0][0][2][0][RTW89_MKK][1][0] = 66,
+ [0][0][2][0][RTW89_MKK][0][0] = 26,
+ [0][0][2][0][RTW89_IC][1][0] = 24,
+ [0][0][2][0][RTW89_KCC][1][0] = 24,
+ [0][0][2][0][RTW89_KCC][0][0] = 24,
+ [0][0][2][0][RTW89_ACMA][1][0] = 66,
+ [0][0][2][0][RTW89_ACMA][0][0] = 28,
+ [0][0][2][0][RTW89_CHILE][1][0] = 24,
+ [0][0][2][0][RTW89_QATAR][1][0] = 66,
+ [0][0][2][0][RTW89_QATAR][0][0] = 28,
+ [0][0][2][0][RTW89_UK][1][0] = 66,
+ [0][0][2][0][RTW89_UK][0][0] = 28,
+ [0][0][2][0][RTW89_FCC][1][2] = 22,
+ [0][0][2][0][RTW89_FCC][2][2] = 56,
+ [0][0][2][0][RTW89_ETSI][1][2] = 66,
+ [0][0][2][0][RTW89_ETSI][0][2] = 28,
+ [0][0][2][0][RTW89_MKK][1][2] = 66,
+ [0][0][2][0][RTW89_MKK][0][2] = 26,
+ [0][0][2][0][RTW89_IC][1][2] = 22,
+ [0][0][2][0][RTW89_KCC][1][2] = 24,
+ [0][0][2][0][RTW89_KCC][0][2] = 24,
+ [0][0][2][0][RTW89_ACMA][1][2] = 66,
+ [0][0][2][0][RTW89_ACMA][0][2] = 28,
+ [0][0][2][0][RTW89_CHILE][1][2] = 22,
+ [0][0][2][0][RTW89_QATAR][1][2] = 66,
+ [0][0][2][0][RTW89_QATAR][0][2] = 28,
+ [0][0][2][0][RTW89_UK][1][2] = 66,
+ [0][0][2][0][RTW89_UK][0][2] = 28,
+ [0][0][2][0][RTW89_FCC][1][4] = 22,
+ [0][0][2][0][RTW89_FCC][2][4] = 56,
+ [0][0][2][0][RTW89_ETSI][1][4] = 66,
+ [0][0][2][0][RTW89_ETSI][0][4] = 28,
+ [0][0][2][0][RTW89_MKK][1][4] = 66,
+ [0][0][2][0][RTW89_MKK][0][4] = 26,
+ [0][0][2][0][RTW89_IC][1][4] = 22,
+ [0][0][2][0][RTW89_KCC][1][4] = 24,
+ [0][0][2][0][RTW89_KCC][0][4] = 24,
+ [0][0][2][0][RTW89_ACMA][1][4] = 66,
+ [0][0][2][0][RTW89_ACMA][0][4] = 28,
+ [0][0][2][0][RTW89_CHILE][1][4] = 22,
+ [0][0][2][0][RTW89_QATAR][1][4] = 66,
+ [0][0][2][0][RTW89_QATAR][0][4] = 28,
+ [0][0][2][0][RTW89_UK][1][4] = 66,
+ [0][0][2][0][RTW89_UK][0][4] = 28,
+ [0][0][2][0][RTW89_FCC][1][6] = 22,
+ [0][0][2][0][RTW89_FCC][2][6] = 56,
+ [0][0][2][0][RTW89_ETSI][1][6] = 66,
+ [0][0][2][0][RTW89_ETSI][0][6] = 28,
+ [0][0][2][0][RTW89_MKK][1][6] = 66,
+ [0][0][2][0][RTW89_MKK][0][6] = 26,
+ [0][0][2][0][RTW89_IC][1][6] = 22,
+ [0][0][2][0][RTW89_KCC][1][6] = 24,
+ [0][0][2][0][RTW89_KCC][0][6] = 24,
+ [0][0][2][0][RTW89_ACMA][1][6] = 66,
+ [0][0][2][0][RTW89_ACMA][0][6] = 28,
+ [0][0][2][0][RTW89_CHILE][1][6] = 22,
+ [0][0][2][0][RTW89_QATAR][1][6] = 66,
+ [0][0][2][0][RTW89_QATAR][0][6] = 28,
+ [0][0][2][0][RTW89_UK][1][6] = 66,
+ [0][0][2][0][RTW89_UK][0][6] = 28,
+ [0][0][2][0][RTW89_FCC][1][8] = 22,
+ [0][0][2][0][RTW89_FCC][2][8] = 56,
+ [0][0][2][0][RTW89_ETSI][1][8] = 66,
+ [0][0][2][0][RTW89_ETSI][0][8] = 28,
+ [0][0][2][0][RTW89_MKK][1][8] = 66,
+ [0][0][2][0][RTW89_MKK][0][8] = 26,
+ [0][0][2][0][RTW89_IC][1][8] = 22,
+ [0][0][2][0][RTW89_KCC][1][8] = 24,
+ [0][0][2][0][RTW89_KCC][0][8] = 24,
+ [0][0][2][0][RTW89_ACMA][1][8] = 66,
+ [0][0][2][0][RTW89_ACMA][0][8] = 28,
+ [0][0][2][0][RTW89_CHILE][1][8] = 22,
+ [0][0][2][0][RTW89_QATAR][1][8] = 66,
+ [0][0][2][0][RTW89_QATAR][0][8] = 28,
+ [0][0][2][0][RTW89_UK][1][8] = 66,
+ [0][0][2][0][RTW89_UK][0][8] = 28,
+ [0][0][2][0][RTW89_FCC][1][10] = 22,
+ [0][0][2][0][RTW89_FCC][2][10] = 56,
+ [0][0][2][0][RTW89_ETSI][1][10] = 66,
+ [0][0][2][0][RTW89_ETSI][0][10] = 28,
+ [0][0][2][0][RTW89_MKK][1][10] = 66,
+ [0][0][2][0][RTW89_MKK][0][10] = 26,
+ [0][0][2][0][RTW89_IC][1][10] = 22,
+ [0][0][2][0][RTW89_KCC][1][10] = 24,
+ [0][0][2][0][RTW89_KCC][0][10] = 24,
+ [0][0][2][0][RTW89_ACMA][1][10] = 66,
+ [0][0][2][0][RTW89_ACMA][0][10] = 28,
+ [0][0][2][0][RTW89_CHILE][1][10] = 22,
+ [0][0][2][0][RTW89_QATAR][1][10] = 66,
+ [0][0][2][0][RTW89_QATAR][0][10] = 28,
+ [0][0][2][0][RTW89_UK][1][10] = 66,
+ [0][0][2][0][RTW89_UK][0][10] = 28,
+ [0][0][2][0][RTW89_FCC][1][12] = 22,
+ [0][0][2][0][RTW89_FCC][2][12] = 56,
+ [0][0][2][0][RTW89_ETSI][1][12] = 66,
+ [0][0][2][0][RTW89_ETSI][0][12] = 28,
+ [0][0][2][0][RTW89_MKK][1][12] = 66,
+ [0][0][2][0][RTW89_MKK][0][12] = 26,
+ [0][0][2][0][RTW89_IC][1][12] = 22,
+ [0][0][2][0][RTW89_KCC][1][12] = 24,
+ [0][0][2][0][RTW89_KCC][0][12] = 24,
+ [0][0][2][0][RTW89_ACMA][1][12] = 66,
+ [0][0][2][0][RTW89_ACMA][0][12] = 28,
+ [0][0][2][0][RTW89_CHILE][1][12] = 22,
+ [0][0][2][0][RTW89_QATAR][1][12] = 66,
+ [0][0][2][0][RTW89_QATAR][0][12] = 28,
+ [0][0][2][0][RTW89_UK][1][12] = 66,
+ [0][0][2][0][RTW89_UK][0][12] = 28,
+ [0][0][2][0][RTW89_FCC][1][14] = 22,
+ [0][0][2][0][RTW89_FCC][2][14] = 56,
+ [0][0][2][0][RTW89_ETSI][1][14] = 66,
+ [0][0][2][0][RTW89_ETSI][0][14] = 28,
+ [0][0][2][0][RTW89_MKK][1][14] = 66,
+ [0][0][2][0][RTW89_MKK][0][14] = 26,
+ [0][0][2][0][RTW89_IC][1][14] = 22,
+ [0][0][2][0][RTW89_KCC][1][14] = 24,
+ [0][0][2][0][RTW89_KCC][0][14] = 24,
+ [0][0][2][0][RTW89_ACMA][1][14] = 66,
+ [0][0][2][0][RTW89_ACMA][0][14] = 28,
+ [0][0][2][0][RTW89_CHILE][1][14] = 22,
+ [0][0][2][0][RTW89_QATAR][1][14] = 66,
+ [0][0][2][0][RTW89_QATAR][0][14] = 28,
+ [0][0][2][0][RTW89_UK][1][14] = 66,
+ [0][0][2][0][RTW89_UK][0][14] = 28,
+ [0][0][2][0][RTW89_FCC][1][15] = 22,
+ [0][0][2][0][RTW89_FCC][2][15] = 56,
+ [0][0][2][0][RTW89_ETSI][1][15] = 66,
+ [0][0][2][0][RTW89_ETSI][0][15] = 28,
+ [0][0][2][0][RTW89_MKK][1][15] = 66,
+ [0][0][2][0][RTW89_MKK][0][15] = 26,
+ [0][0][2][0][RTW89_IC][1][15] = 22,
+ [0][0][2][0][RTW89_KCC][1][15] = 24,
+ [0][0][2][0][RTW89_KCC][0][15] = 24,
+ [0][0][2][0][RTW89_ACMA][1][15] = 66,
+ [0][0][2][0][RTW89_ACMA][0][15] = 28,
+ [0][0][2][0][RTW89_CHILE][1][15] = 22,
+ [0][0][2][0][RTW89_QATAR][1][15] = 66,
+ [0][0][2][0][RTW89_QATAR][0][15] = 28,
+ [0][0][2][0][RTW89_UK][1][15] = 66,
+ [0][0][2][0][RTW89_UK][0][15] = 28,
+ [0][0][2][0][RTW89_FCC][1][17] = 22,
+ [0][0][2][0][RTW89_FCC][2][17] = 56,
+ [0][0][2][0][RTW89_ETSI][1][17] = 66,
+ [0][0][2][0][RTW89_ETSI][0][17] = 28,
+ [0][0][2][0][RTW89_MKK][1][17] = 66,
+ [0][0][2][0][RTW89_MKK][0][17] = 26,
+ [0][0][2][0][RTW89_IC][1][17] = 22,
+ [0][0][2][0][RTW89_KCC][1][17] = 24,
+ [0][0][2][0][RTW89_KCC][0][17] = 24,
+ [0][0][2][0][RTW89_ACMA][1][17] = 66,
+ [0][0][2][0][RTW89_ACMA][0][17] = 28,
+ [0][0][2][0][RTW89_CHILE][1][17] = 22,
+ [0][0][2][0][RTW89_QATAR][1][17] = 66,
+ [0][0][2][0][RTW89_QATAR][0][17] = 28,
+ [0][0][2][0][RTW89_UK][1][17] = 66,
+ [0][0][2][0][RTW89_UK][0][17] = 28,
+ [0][0][2][0][RTW89_FCC][1][19] = 22,
+ [0][0][2][0][RTW89_FCC][2][19] = 56,
+ [0][0][2][0][RTW89_ETSI][1][19] = 66,
+ [0][0][2][0][RTW89_ETSI][0][19] = 28,
+ [0][0][2][0][RTW89_MKK][1][19] = 66,
+ [0][0][2][0][RTW89_MKK][0][19] = 26,
+ [0][0][2][0][RTW89_IC][1][19] = 22,
+ [0][0][2][0][RTW89_KCC][1][19] = 24,
+ [0][0][2][0][RTW89_KCC][0][19] = 24,
+ [0][0][2][0][RTW89_ACMA][1][19] = 66,
+ [0][0][2][0][RTW89_ACMA][0][19] = 28,
+ [0][0][2][0][RTW89_CHILE][1][19] = 22,
+ [0][0][2][0][RTW89_QATAR][1][19] = 66,
+ [0][0][2][0][RTW89_QATAR][0][19] = 28,
+ [0][0][2][0][RTW89_UK][1][19] = 66,
+ [0][0][2][0][RTW89_UK][0][19] = 28,
+ [0][0][2][0][RTW89_FCC][1][21] = 22,
+ [0][0][2][0][RTW89_FCC][2][21] = 56,
+ [0][0][2][0][RTW89_ETSI][1][21] = 66,
+ [0][0][2][0][RTW89_ETSI][0][21] = 28,
+ [0][0][2][0][RTW89_MKK][1][21] = 66,
+ [0][0][2][0][RTW89_MKK][0][21] = 26,
+ [0][0][2][0][RTW89_IC][1][21] = 22,
+ [0][0][2][0][RTW89_KCC][1][21] = 24,
+ [0][0][2][0][RTW89_KCC][0][21] = 24,
+ [0][0][2][0][RTW89_ACMA][1][21] = 66,
+ [0][0][2][0][RTW89_ACMA][0][21] = 28,
+ [0][0][2][0][RTW89_CHILE][1][21] = 22,
+ [0][0][2][0][RTW89_QATAR][1][21] = 66,
+ [0][0][2][0][RTW89_QATAR][0][21] = 28,
+ [0][0][2][0][RTW89_UK][1][21] = 66,
+ [0][0][2][0][RTW89_UK][0][21] = 28,
+ [0][0][2][0][RTW89_FCC][1][23] = 22,
+ [0][0][2][0][RTW89_FCC][2][23] = 70,
+ [0][0][2][0][RTW89_ETSI][1][23] = 66,
+ [0][0][2][0][RTW89_ETSI][0][23] = 28,
+ [0][0][2][0][RTW89_MKK][1][23] = 66,
+ [0][0][2][0][RTW89_MKK][0][23] = 26,
+ [0][0][2][0][RTW89_IC][1][23] = 22,
+ [0][0][2][0][RTW89_KCC][1][23] = 24,
+ [0][0][2][0][RTW89_KCC][0][23] = 26,
+ [0][0][2][0][RTW89_ACMA][1][23] = 66,
+ [0][0][2][0][RTW89_ACMA][0][23] = 28,
+ [0][0][2][0][RTW89_CHILE][1][23] = 22,
+ [0][0][2][0][RTW89_QATAR][1][23] = 66,
+ [0][0][2][0][RTW89_QATAR][0][23] = 28,
+ [0][0][2][0][RTW89_UK][1][23] = 66,
+ [0][0][2][0][RTW89_UK][0][23] = 28,
+ [0][0][2][0][RTW89_FCC][1][25] = 22,
+ [0][0][2][0][RTW89_FCC][2][25] = 70,
+ [0][0][2][0][RTW89_ETSI][1][25] = 66,
+ [0][0][2][0][RTW89_ETSI][0][25] = 28,
+ [0][0][2][0][RTW89_MKK][1][25] = 66,
+ [0][0][2][0][RTW89_MKK][0][25] = 26,
+ [0][0][2][0][RTW89_IC][1][25] = 22,
+ [0][0][2][0][RTW89_KCC][1][25] = 24,
+ [0][0][2][0][RTW89_KCC][0][25] = 26,
+ [0][0][2][0][RTW89_ACMA][1][25] = 66,
+ [0][0][2][0][RTW89_ACMA][0][25] = 28,
+ [0][0][2][0][RTW89_CHILE][1][25] = 22,
+ [0][0][2][0][RTW89_QATAR][1][25] = 66,
+ [0][0][2][0][RTW89_QATAR][0][25] = 28,
+ [0][0][2][0][RTW89_UK][1][25] = 66,
+ [0][0][2][0][RTW89_UK][0][25] = 28,
+ [0][0][2][0][RTW89_FCC][1][27] = 22,
+ [0][0][2][0][RTW89_FCC][2][27] = 70,
+ [0][0][2][0][RTW89_ETSI][1][27] = 66,
+ [0][0][2][0][RTW89_ETSI][0][27] = 28,
+ [0][0][2][0][RTW89_MKK][1][27] = 66,
+ [0][0][2][0][RTW89_MKK][0][27] = 26,
+ [0][0][2][0][RTW89_IC][1][27] = 22,
+ [0][0][2][0][RTW89_KCC][1][27] = 24,
+ [0][0][2][0][RTW89_KCC][0][27] = 26,
+ [0][0][2][0][RTW89_ACMA][1][27] = 66,
+ [0][0][2][0][RTW89_ACMA][0][27] = 28,
+ [0][0][2][0][RTW89_CHILE][1][27] = 22,
+ [0][0][2][0][RTW89_QATAR][1][27] = 66,
+ [0][0][2][0][RTW89_QATAR][0][27] = 28,
+ [0][0][2][0][RTW89_UK][1][27] = 66,
+ [0][0][2][0][RTW89_UK][0][27] = 28,
+ [0][0][2][0][RTW89_FCC][1][29] = 22,
+ [0][0][2][0][RTW89_FCC][2][29] = 70,
+ [0][0][2][0][RTW89_ETSI][1][29] = 66,
+ [0][0][2][0][RTW89_ETSI][0][29] = 28,
+ [0][0][2][0][RTW89_MKK][1][29] = 66,
+ [0][0][2][0][RTW89_MKK][0][29] = 26,
+ [0][0][2][0][RTW89_IC][1][29] = 22,
+ [0][0][2][0][RTW89_KCC][1][29] = 24,
+ [0][0][2][0][RTW89_KCC][0][29] = 26,
+ [0][0][2][0][RTW89_ACMA][1][29] = 66,
+ [0][0][2][0][RTW89_ACMA][0][29] = 28,
+ [0][0][2][0][RTW89_CHILE][1][29] = 22,
+ [0][0][2][0][RTW89_QATAR][1][29] = 66,
+ [0][0][2][0][RTW89_QATAR][0][29] = 28,
+ [0][0][2][0][RTW89_UK][1][29] = 66,
+ [0][0][2][0][RTW89_UK][0][29] = 28,
+ [0][0][2][0][RTW89_FCC][1][30] = 22,
+ [0][0][2][0][RTW89_FCC][2][30] = 70,
+ [0][0][2][0][RTW89_ETSI][1][30] = 66,
+ [0][0][2][0][RTW89_ETSI][0][30] = 28,
+ [0][0][2][0][RTW89_MKK][1][30] = 66,
+ [0][0][2][0][RTW89_MKK][0][30] = 26,
+ [0][0][2][0][RTW89_IC][1][30] = 22,
+ [0][0][2][0][RTW89_KCC][1][30] = 24,
+ [0][0][2][0][RTW89_KCC][0][30] = 26,
+ [0][0][2][0][RTW89_ACMA][1][30] = 66,
+ [0][0][2][0][RTW89_ACMA][0][30] = 28,
+ [0][0][2][0][RTW89_CHILE][1][30] = 22,
+ [0][0][2][0][RTW89_QATAR][1][30] = 66,
+ [0][0][2][0][RTW89_QATAR][0][30] = 28,
+ [0][0][2][0][RTW89_UK][1][30] = 66,
+ [0][0][2][0][RTW89_UK][0][30] = 28,
+ [0][0][2][0][RTW89_FCC][1][32] = 22,
+ [0][0][2][0][RTW89_FCC][2][32] = 70,
+ [0][0][2][0][RTW89_ETSI][1][32] = 66,
+ [0][0][2][0][RTW89_ETSI][0][32] = 28,
+ [0][0][2][0][RTW89_MKK][1][32] = 66,
+ [0][0][2][0][RTW89_MKK][0][32] = 26,
+ [0][0][2][0][RTW89_IC][1][32] = 22,
+ [0][0][2][0][RTW89_KCC][1][32] = 24,
+ [0][0][2][0][RTW89_KCC][0][32] = 26,
+ [0][0][2][0][RTW89_ACMA][1][32] = 66,
+ [0][0][2][0][RTW89_ACMA][0][32] = 28,
+ [0][0][2][0][RTW89_CHILE][1][32] = 22,
+ [0][0][2][0][RTW89_QATAR][1][32] = 66,
+ [0][0][2][0][RTW89_QATAR][0][32] = 28,
+ [0][0][2][0][RTW89_UK][1][32] = 66,
+ [0][0][2][0][RTW89_UK][0][32] = 28,
+ [0][0][2][0][RTW89_FCC][1][34] = 22,
+ [0][0][2][0][RTW89_FCC][2][34] = 70,
+ [0][0][2][0][RTW89_ETSI][1][34] = 66,
+ [0][0][2][0][RTW89_ETSI][0][34] = 28,
+ [0][0][2][0][RTW89_MKK][1][34] = 66,
+ [0][0][2][0][RTW89_MKK][0][34] = 26,
+ [0][0][2][0][RTW89_IC][1][34] = 22,
+ [0][0][2][0][RTW89_KCC][1][34] = 24,
+ [0][0][2][0][RTW89_KCC][0][34] = 26,
+ [0][0][2][0][RTW89_ACMA][1][34] = 66,
+ [0][0][2][0][RTW89_ACMA][0][34] = 28,
+ [0][0][2][0][RTW89_CHILE][1][34] = 22,
+ [0][0][2][0][RTW89_QATAR][1][34] = 66,
+ [0][0][2][0][RTW89_QATAR][0][34] = 28,
+ [0][0][2][0][RTW89_UK][1][34] = 66,
+ [0][0][2][0][RTW89_UK][0][34] = 28,
+ [0][0][2][0][RTW89_FCC][1][36] = 22,
+ [0][0][2][0][RTW89_FCC][2][36] = 70,
+ [0][0][2][0][RTW89_ETSI][1][36] = 66,
+ [0][0][2][0][RTW89_ETSI][0][36] = 28,
+ [0][0][2][0][RTW89_MKK][1][36] = 66,
+ [0][0][2][0][RTW89_MKK][0][36] = 26,
+ [0][0][2][0][RTW89_IC][1][36] = 22,
+ [0][0][2][0][RTW89_KCC][1][36] = 24,
+ [0][0][2][0][RTW89_KCC][0][36] = 26,
+ [0][0][2][0][RTW89_ACMA][1][36] = 66,
+ [0][0][2][0][RTW89_ACMA][0][36] = 28,
+ [0][0][2][0][RTW89_CHILE][1][36] = 22,
+ [0][0][2][0][RTW89_QATAR][1][36] = 66,
+ [0][0][2][0][RTW89_QATAR][0][36] = 28,
+ [0][0][2][0][RTW89_UK][1][36] = 66,
+ [0][0][2][0][RTW89_UK][0][36] = 28,
+ [0][0][2][0][RTW89_FCC][1][38] = 22,
+ [0][0][2][0][RTW89_FCC][2][38] = 70,
+ [0][0][2][0][RTW89_ETSI][1][38] = 66,
+ [0][0][2][0][RTW89_ETSI][0][38] = 28,
+ [0][0][2][0][RTW89_MKK][1][38] = 66,
+ [0][0][2][0][RTW89_MKK][0][38] = 26,
+ [0][0][2][0][RTW89_IC][1][38] = 22,
+ [0][0][2][0][RTW89_KCC][1][38] = 24,
+ [0][0][2][0][RTW89_KCC][0][38] = 26,
+ [0][0][2][0][RTW89_ACMA][1][38] = 66,
+ [0][0][2][0][RTW89_ACMA][0][38] = 28,
+ [0][0][2][0][RTW89_CHILE][1][38] = 22,
+ [0][0][2][0][RTW89_QATAR][1][38] = 66,
+ [0][0][2][0][RTW89_QATAR][0][38] = 28,
+ [0][0][2][0][RTW89_UK][1][38] = 66,
+ [0][0][2][0][RTW89_UK][0][38] = 28,
+ [0][0][2][0][RTW89_FCC][1][40] = 22,
+ [0][0][2][0][RTW89_FCC][2][40] = 70,
+ [0][0][2][0][RTW89_ETSI][1][40] = 66,
+ [0][0][2][0][RTW89_ETSI][0][40] = 28,
+ [0][0][2][0][RTW89_MKK][1][40] = 66,
+ [0][0][2][0][RTW89_MKK][0][40] = 26,
+ [0][0][2][0][RTW89_IC][1][40] = 22,
+ [0][0][2][0][RTW89_KCC][1][40] = 24,
+ [0][0][2][0][RTW89_KCC][0][40] = 26,
+ [0][0][2][0][RTW89_ACMA][1][40] = 66,
+ [0][0][2][0][RTW89_ACMA][0][40] = 28,
+ [0][0][2][0][RTW89_CHILE][1][40] = 22,
+ [0][0][2][0][RTW89_QATAR][1][40] = 66,
+ [0][0][2][0][RTW89_QATAR][0][40] = 28,
+ [0][0][2][0][RTW89_UK][1][40] = 66,
+ [0][0][2][0][RTW89_UK][0][40] = 28,
+ [0][0][2][0][RTW89_FCC][1][42] = 22,
+ [0][0][2][0][RTW89_FCC][2][42] = 70,
+ [0][0][2][0][RTW89_ETSI][1][42] = 66,
+ [0][0][2][0][RTW89_ETSI][0][42] = 28,
+ [0][0][2][0][RTW89_MKK][1][42] = 66,
+ [0][0][2][0][RTW89_MKK][0][42] = 26,
+ [0][0][2][0][RTW89_IC][1][42] = 22,
+ [0][0][2][0][RTW89_KCC][1][42] = 24,
+ [0][0][2][0][RTW89_KCC][0][42] = 26,
+ [0][0][2][0][RTW89_ACMA][1][42] = 66,
+ [0][0][2][0][RTW89_ACMA][0][42] = 28,
+ [0][0][2][0][RTW89_CHILE][1][42] = 22,
+ [0][0][2][0][RTW89_QATAR][1][42] = 66,
+ [0][0][2][0][RTW89_QATAR][0][42] = 28,
+ [0][0][2][0][RTW89_UK][1][42] = 66,
+ [0][0][2][0][RTW89_UK][0][42] = 28,
+ [0][0][2][0][RTW89_FCC][1][44] = 22,
+ [0][0][2][0][RTW89_FCC][2][44] = 70,
+ [0][0][2][0][RTW89_ETSI][1][44] = 66,
+ [0][0][2][0][RTW89_ETSI][0][44] = 30,
+ [0][0][2][0][RTW89_MKK][1][44] = 44,
+ [0][0][2][0][RTW89_MKK][0][44] = 28,
+ [0][0][2][0][RTW89_IC][1][44] = 22,
+ [0][0][2][0][RTW89_KCC][1][44] = 24,
+ [0][0][2][0][RTW89_KCC][0][44] = 26,
+ [0][0][2][0][RTW89_ACMA][1][44] = 66,
+ [0][0][2][0][RTW89_ACMA][0][44] = 30,
+ [0][0][2][0][RTW89_CHILE][1][44] = 22,
+ [0][0][2][0][RTW89_QATAR][1][44] = 66,
+ [0][0][2][0][RTW89_QATAR][0][44] = 30,
+ [0][0][2][0][RTW89_UK][1][44] = 66,
+ [0][0][2][0][RTW89_UK][0][44] = 30,
+ [0][0][2][0][RTW89_FCC][1][45] = 22,
+ [0][0][2][0][RTW89_FCC][2][45] = 127,
+ [0][0][2][0][RTW89_ETSI][1][45] = 127,
+ [0][0][2][0][RTW89_ETSI][0][45] = 127,
+ [0][0][2][0][RTW89_MKK][1][45] = 127,
+ [0][0][2][0][RTW89_MKK][0][45] = 127,
+ [0][0][2][0][RTW89_IC][1][45] = 22,
+ [0][0][2][0][RTW89_KCC][1][45] = 24,
+ [0][0][2][0][RTW89_KCC][0][45] = 127,
+ [0][0][2][0][RTW89_ACMA][1][45] = 127,
+ [0][0][2][0][RTW89_ACMA][0][45] = 127,
+ [0][0][2][0][RTW89_CHILE][1][45] = 22,
+ [0][0][2][0][RTW89_QATAR][1][45] = 127,
+ [0][0][2][0][RTW89_QATAR][0][45] = 127,
+ [0][0][2][0][RTW89_UK][1][45] = 127,
+ [0][0][2][0][RTW89_UK][0][45] = 127,
+ [0][0][2][0][RTW89_FCC][1][47] = 22,
+ [0][0][2][0][RTW89_FCC][2][47] = 127,
+ [0][0][2][0][RTW89_ETSI][1][47] = 127,
+ [0][0][2][0][RTW89_ETSI][0][47] = 127,
+ [0][0][2][0][RTW89_MKK][1][47] = 127,
+ [0][0][2][0][RTW89_MKK][0][47] = 127,
+ [0][0][2][0][RTW89_IC][1][47] = 22,
+ [0][0][2][0][RTW89_KCC][1][47] = 24,
+ [0][0][2][0][RTW89_KCC][0][47] = 127,
+ [0][0][2][0][RTW89_ACMA][1][47] = 127,
+ [0][0][2][0][RTW89_ACMA][0][47] = 127,
+ [0][0][2][0][RTW89_CHILE][1][47] = 22,
+ [0][0][2][0][RTW89_QATAR][1][47] = 127,
+ [0][0][2][0][RTW89_QATAR][0][47] = 127,
+ [0][0][2][0][RTW89_UK][1][47] = 127,
+ [0][0][2][0][RTW89_UK][0][47] = 127,
+ [0][0][2][0][RTW89_FCC][1][49] = 24,
+ [0][0][2][0][RTW89_FCC][2][49] = 127,
+ [0][0][2][0][RTW89_ETSI][1][49] = 127,
+ [0][0][2][0][RTW89_ETSI][0][49] = 127,
+ [0][0][2][0][RTW89_MKK][1][49] = 127,
+ [0][0][2][0][RTW89_MKK][0][49] = 127,
+ [0][0][2][0][RTW89_IC][1][49] = 24,
+ [0][0][2][0][RTW89_KCC][1][49] = 24,
+ [0][0][2][0][RTW89_KCC][0][49] = 127,
+ [0][0][2][0][RTW89_ACMA][1][49] = 127,
+ [0][0][2][0][RTW89_ACMA][0][49] = 127,
+ [0][0][2][0][RTW89_CHILE][1][49] = 24,
+ [0][0][2][0][RTW89_QATAR][1][49] = 127,
+ [0][0][2][0][RTW89_QATAR][0][49] = 127,
+ [0][0][2][0][RTW89_UK][1][49] = 127,
+ [0][0][2][0][RTW89_UK][0][49] = 127,
+ [0][0][2][0][RTW89_FCC][1][51] = 22,
+ [0][0][2][0][RTW89_FCC][2][51] = 127,
+ [0][0][2][0][RTW89_ETSI][1][51] = 127,
+ [0][0][2][0][RTW89_ETSI][0][51] = 127,
+ [0][0][2][0][RTW89_MKK][1][51] = 127,
+ [0][0][2][0][RTW89_MKK][0][51] = 127,
+ [0][0][2][0][RTW89_IC][1][51] = 22,
+ [0][0][2][0][RTW89_KCC][1][51] = 24,
+ [0][0][2][0][RTW89_KCC][0][51] = 127,
+ [0][0][2][0][RTW89_ACMA][1][51] = 127,
+ [0][0][2][0][RTW89_ACMA][0][51] = 127,
+ [0][0][2][0][RTW89_CHILE][1][51] = 22,
+ [0][0][2][0][RTW89_QATAR][1][51] = 127,
+ [0][0][2][0][RTW89_QATAR][0][51] = 127,
+ [0][0][2][0][RTW89_UK][1][51] = 127,
+ [0][0][2][0][RTW89_UK][0][51] = 127,
+ [0][0][2][0][RTW89_FCC][1][53] = 22,
+ [0][0][2][0][RTW89_FCC][2][53] = 127,
+ [0][0][2][0][RTW89_ETSI][1][53] = 127,
+ [0][0][2][0][RTW89_ETSI][0][53] = 127,
+ [0][0][2][0][RTW89_MKK][1][53] = 127,
+ [0][0][2][0][RTW89_MKK][0][53] = 127,
+ [0][0][2][0][RTW89_IC][1][53] = 22,
+ [0][0][2][0][RTW89_KCC][1][53] = 24,
+ [0][0][2][0][RTW89_KCC][0][53] = 127,
+ [0][0][2][0][RTW89_ACMA][1][53] = 127,
+ [0][0][2][0][RTW89_ACMA][0][53] = 127,
+ [0][0][2][0][RTW89_CHILE][1][53] = 22,
+ [0][0][2][0][RTW89_QATAR][1][53] = 127,
+ [0][0][2][0][RTW89_QATAR][0][53] = 127,
+ [0][0][2][0][RTW89_UK][1][53] = 127,
+ [0][0][2][0][RTW89_UK][0][53] = 127,
+ [0][0][2][0][RTW89_FCC][1][55] = 22,
+ [0][0][2][0][RTW89_FCC][2][55] = 68,
+ [0][0][2][0][RTW89_ETSI][1][55] = 127,
+ [0][0][2][0][RTW89_ETSI][0][55] = 127,
+ [0][0][2][0][RTW89_MKK][1][55] = 127,
+ [0][0][2][0][RTW89_MKK][0][55] = 127,
+ [0][0][2][0][RTW89_IC][1][55] = 22,
+ [0][0][2][0][RTW89_KCC][1][55] = 26,
+ [0][0][2][0][RTW89_KCC][0][55] = 127,
+ [0][0][2][0][RTW89_ACMA][1][55] = 127,
+ [0][0][2][0][RTW89_ACMA][0][55] = 127,
+ [0][0][2][0][RTW89_CHILE][1][55] = 22,
+ [0][0][2][0][RTW89_QATAR][1][55] = 127,
+ [0][0][2][0][RTW89_QATAR][0][55] = 127,
+ [0][0][2][0][RTW89_UK][1][55] = 127,
+ [0][0][2][0][RTW89_UK][0][55] = 127,
+ [0][0][2][0][RTW89_FCC][1][57] = 22,
+ [0][0][2][0][RTW89_FCC][2][57] = 68,
+ [0][0][2][0][RTW89_ETSI][1][57] = 127,
+ [0][0][2][0][RTW89_ETSI][0][57] = 127,
+ [0][0][2][0][RTW89_MKK][1][57] = 127,
+ [0][0][2][0][RTW89_MKK][0][57] = 127,
+ [0][0][2][0][RTW89_IC][1][57] = 22,
+ [0][0][2][0][RTW89_KCC][1][57] = 26,
+ [0][0][2][0][RTW89_KCC][0][57] = 127,
+ [0][0][2][0][RTW89_ACMA][1][57] = 127,
+ [0][0][2][0][RTW89_ACMA][0][57] = 127,
+ [0][0][2][0][RTW89_CHILE][1][57] = 22,
+ [0][0][2][0][RTW89_QATAR][1][57] = 127,
+ [0][0][2][0][RTW89_QATAR][0][57] = 127,
+ [0][0][2][0][RTW89_UK][1][57] = 127,
+ [0][0][2][0][RTW89_UK][0][57] = 127,
+ [0][0][2][0][RTW89_FCC][1][59] = 22,
+ [0][0][2][0][RTW89_FCC][2][59] = 68,
+ [0][0][2][0][RTW89_ETSI][1][59] = 127,
+ [0][0][2][0][RTW89_ETSI][0][59] = 127,
+ [0][0][2][0][RTW89_MKK][1][59] = 127,
+ [0][0][2][0][RTW89_MKK][0][59] = 127,
+ [0][0][2][0][RTW89_IC][1][59] = 22,
+ [0][0][2][0][RTW89_KCC][1][59] = 26,
+ [0][0][2][0][RTW89_KCC][0][59] = 127,
+ [0][0][2][0][RTW89_ACMA][1][59] = 127,
+ [0][0][2][0][RTW89_ACMA][0][59] = 127,
+ [0][0][2][0][RTW89_CHILE][1][59] = 22,
+ [0][0][2][0][RTW89_QATAR][1][59] = 127,
+ [0][0][2][0][RTW89_QATAR][0][59] = 127,
+ [0][0][2][0][RTW89_UK][1][59] = 127,
+ [0][0][2][0][RTW89_UK][0][59] = 127,
+ [0][0][2][0][RTW89_FCC][1][60] = 22,
+ [0][0][2][0][RTW89_FCC][2][60] = 68,
+ [0][0][2][0][RTW89_ETSI][1][60] = 127,
+ [0][0][2][0][RTW89_ETSI][0][60] = 127,
+ [0][0][2][0][RTW89_MKK][1][60] = 127,
+ [0][0][2][0][RTW89_MKK][0][60] = 127,
+ [0][0][2][0][RTW89_IC][1][60] = 22,
+ [0][0][2][0][RTW89_KCC][1][60] = 26,
+ [0][0][2][0][RTW89_KCC][0][60] = 127,
+ [0][0][2][0][RTW89_ACMA][1][60] = 127,
+ [0][0][2][0][RTW89_ACMA][0][60] = 127,
+ [0][0][2][0][RTW89_CHILE][1][60] = 22,
+ [0][0][2][0][RTW89_QATAR][1][60] = 127,
+ [0][0][2][0][RTW89_QATAR][0][60] = 127,
+ [0][0][2][0][RTW89_UK][1][60] = 127,
+ [0][0][2][0][RTW89_UK][0][60] = 127,
+ [0][0][2][0][RTW89_FCC][1][62] = 22,
+ [0][0][2][0][RTW89_FCC][2][62] = 68,
+ [0][0][2][0][RTW89_ETSI][1][62] = 127,
+ [0][0][2][0][RTW89_ETSI][0][62] = 127,
+ [0][0][2][0][RTW89_MKK][1][62] = 127,
+ [0][0][2][0][RTW89_MKK][0][62] = 127,
+ [0][0][2][0][RTW89_IC][1][62] = 22,
+ [0][0][2][0][RTW89_KCC][1][62] = 26,
+ [0][0][2][0][RTW89_KCC][0][62] = 127,
+ [0][0][2][0][RTW89_ACMA][1][62] = 127,
+ [0][0][2][0][RTW89_ACMA][0][62] = 127,
+ [0][0][2][0][RTW89_CHILE][1][62] = 22,
+ [0][0][2][0][RTW89_QATAR][1][62] = 127,
+ [0][0][2][0][RTW89_QATAR][0][62] = 127,
+ [0][0][2][0][RTW89_UK][1][62] = 127,
+ [0][0][2][0][RTW89_UK][0][62] = 127,
+ [0][0][2][0][RTW89_FCC][1][64] = 22,
+ [0][0][2][0][RTW89_FCC][2][64] = 68,
+ [0][0][2][0][RTW89_ETSI][1][64] = 127,
+ [0][0][2][0][RTW89_ETSI][0][64] = 127,
+ [0][0][2][0][RTW89_MKK][1][64] = 127,
+ [0][0][2][0][RTW89_MKK][0][64] = 127,
+ [0][0][2][0][RTW89_IC][1][64] = 22,
+ [0][0][2][0][RTW89_KCC][1][64] = 26,
+ [0][0][2][0][RTW89_KCC][0][64] = 127,
+ [0][0][2][0][RTW89_ACMA][1][64] = 127,
+ [0][0][2][0][RTW89_ACMA][0][64] = 127,
+ [0][0][2][0][RTW89_CHILE][1][64] = 22,
+ [0][0][2][0][RTW89_QATAR][1][64] = 127,
+ [0][0][2][0][RTW89_QATAR][0][64] = 127,
+ [0][0][2][0][RTW89_UK][1][64] = 127,
+ [0][0][2][0][RTW89_UK][0][64] = 127,
+ [0][0][2][0][RTW89_FCC][1][66] = 22,
+ [0][0][2][0][RTW89_FCC][2][66] = 68,
+ [0][0][2][0][RTW89_ETSI][1][66] = 127,
+ [0][0][2][0][RTW89_ETSI][0][66] = 127,
+ [0][0][2][0][RTW89_MKK][1][66] = 127,
+ [0][0][2][0][RTW89_MKK][0][66] = 127,
+ [0][0][2][0][RTW89_IC][1][66] = 22,
+ [0][0][2][0][RTW89_KCC][1][66] = 26,
+ [0][0][2][0][RTW89_KCC][0][66] = 127,
+ [0][0][2][0][RTW89_ACMA][1][66] = 127,
+ [0][0][2][0][RTW89_ACMA][0][66] = 127,
+ [0][0][2][0][RTW89_CHILE][1][66] = 22,
+ [0][0][2][0][RTW89_QATAR][1][66] = 127,
+ [0][0][2][0][RTW89_QATAR][0][66] = 127,
+ [0][0][2][0][RTW89_UK][1][66] = 127,
+ [0][0][2][0][RTW89_UK][0][66] = 127,
+ [0][0][2][0][RTW89_FCC][1][68] = 22,
+ [0][0][2][0][RTW89_FCC][2][68] = 68,
+ [0][0][2][0][RTW89_ETSI][1][68] = 127,
+ [0][0][2][0][RTW89_ETSI][0][68] = 127,
+ [0][0][2][0][RTW89_MKK][1][68] = 127,
+ [0][0][2][0][RTW89_MKK][0][68] = 127,
+ [0][0][2][0][RTW89_IC][1][68] = 22,
+ [0][0][2][0][RTW89_KCC][1][68] = 26,
+ [0][0][2][0][RTW89_KCC][0][68] = 127,
+ [0][0][2][0][RTW89_ACMA][1][68] = 127,
+ [0][0][2][0][RTW89_ACMA][0][68] = 127,
+ [0][0][2][0][RTW89_CHILE][1][68] = 22,
+ [0][0][2][0][RTW89_QATAR][1][68] = 127,
+ [0][0][2][0][RTW89_QATAR][0][68] = 127,
+ [0][0][2][0][RTW89_UK][1][68] = 127,
+ [0][0][2][0][RTW89_UK][0][68] = 127,
+ [0][0][2][0][RTW89_FCC][1][70] = 24,
+ [0][0][2][0][RTW89_FCC][2][70] = 68,
+ [0][0][2][0][RTW89_ETSI][1][70] = 127,
+ [0][0][2][0][RTW89_ETSI][0][70] = 127,
+ [0][0][2][0][RTW89_MKK][1][70] = 127,
+ [0][0][2][0][RTW89_MKK][0][70] = 127,
+ [0][0][2][0][RTW89_IC][1][70] = 24,
+ [0][0][2][0][RTW89_KCC][1][70] = 26,
+ [0][0][2][0][RTW89_KCC][0][70] = 127,
+ [0][0][2][0][RTW89_ACMA][1][70] = 127,
+ [0][0][2][0][RTW89_ACMA][0][70] = 127,
+ [0][0][2][0][RTW89_CHILE][1][70] = 24,
+ [0][0][2][0][RTW89_QATAR][1][70] = 127,
+ [0][0][2][0][RTW89_QATAR][0][70] = 127,
+ [0][0][2][0][RTW89_UK][1][70] = 127,
+ [0][0][2][0][RTW89_UK][0][70] = 127,
+ [0][0][2][0][RTW89_FCC][1][72] = 22,
+ [0][0][2][0][RTW89_FCC][2][72] = 68,
+ [0][0][2][0][RTW89_ETSI][1][72] = 127,
+ [0][0][2][0][RTW89_ETSI][0][72] = 127,
+ [0][0][2][0][RTW89_MKK][1][72] = 127,
+ [0][0][2][0][RTW89_MKK][0][72] = 127,
+ [0][0][2][0][RTW89_IC][1][72] = 22,
+ [0][0][2][0][RTW89_KCC][1][72] = 26,
+ [0][0][2][0][RTW89_KCC][0][72] = 127,
+ [0][0][2][0][RTW89_ACMA][1][72] = 127,
+ [0][0][2][0][RTW89_ACMA][0][72] = 127,
+ [0][0][2][0][RTW89_CHILE][1][72] = 22,
+ [0][0][2][0][RTW89_QATAR][1][72] = 127,
+ [0][0][2][0][RTW89_QATAR][0][72] = 127,
+ [0][0][2][0][RTW89_UK][1][72] = 127,
+ [0][0][2][0][RTW89_UK][0][72] = 127,
+ [0][0][2][0][RTW89_FCC][1][74] = 22,
+ [0][0][2][0][RTW89_FCC][2][74] = 68,
+ [0][0][2][0][RTW89_ETSI][1][74] = 127,
+ [0][0][2][0][RTW89_ETSI][0][74] = 127,
+ [0][0][2][0][RTW89_MKK][1][74] = 127,
+ [0][0][2][0][RTW89_MKK][0][74] = 127,
+ [0][0][2][0][RTW89_IC][1][74] = 22,
+ [0][0][2][0][RTW89_KCC][1][74] = 26,
+ [0][0][2][0][RTW89_KCC][0][74] = 127,
+ [0][0][2][0][RTW89_ACMA][1][74] = 127,
+ [0][0][2][0][RTW89_ACMA][0][74] = 127,
+ [0][0][2][0][RTW89_CHILE][1][74] = 22,
+ [0][0][2][0][RTW89_QATAR][1][74] = 127,
+ [0][0][2][0][RTW89_QATAR][0][74] = 127,
+ [0][0][2][0][RTW89_UK][1][74] = 127,
+ [0][0][2][0][RTW89_UK][0][74] = 127,
+ [0][0][2][0][RTW89_FCC][1][75] = 22,
+ [0][0][2][0][RTW89_FCC][2][75] = 68,
+ [0][0][2][0][RTW89_ETSI][1][75] = 127,
+ [0][0][2][0][RTW89_ETSI][0][75] = 127,
+ [0][0][2][0][RTW89_MKK][1][75] = 127,
+ [0][0][2][0][RTW89_MKK][0][75] = 127,
+ [0][0][2][0][RTW89_IC][1][75] = 22,
+ [0][0][2][0][RTW89_KCC][1][75] = 26,
+ [0][0][2][0][RTW89_KCC][0][75] = 127,
+ [0][0][2][0][RTW89_ACMA][1][75] = 127,
+ [0][0][2][0][RTW89_ACMA][0][75] = 127,
+ [0][0][2][0][RTW89_CHILE][1][75] = 22,
+ [0][0][2][0][RTW89_QATAR][1][75] = 127,
+ [0][0][2][0][RTW89_QATAR][0][75] = 127,
+ [0][0][2][0][RTW89_UK][1][75] = 127,
+ [0][0][2][0][RTW89_UK][0][75] = 127,
+ [0][0][2][0][RTW89_FCC][1][77] = 22,
+ [0][0][2][0][RTW89_FCC][2][77] = 68,
+ [0][0][2][0][RTW89_ETSI][1][77] = 127,
+ [0][0][2][0][RTW89_ETSI][0][77] = 127,
+ [0][0][2][0][RTW89_MKK][1][77] = 127,
+ [0][0][2][0][RTW89_MKK][0][77] = 127,
+ [0][0][2][0][RTW89_IC][1][77] = 22,
+ [0][0][2][0][RTW89_KCC][1][77] = 26,
+ [0][0][2][0][RTW89_KCC][0][77] = 127,
+ [0][0][2][0][RTW89_ACMA][1][77] = 127,
+ [0][0][2][0][RTW89_ACMA][0][77] = 127,
+ [0][0][2][0][RTW89_CHILE][1][77] = 22,
+ [0][0][2][0][RTW89_QATAR][1][77] = 127,
+ [0][0][2][0][RTW89_QATAR][0][77] = 127,
+ [0][0][2][0][RTW89_UK][1][77] = 127,
+ [0][0][2][0][RTW89_UK][0][77] = 127,
+ [0][0][2][0][RTW89_FCC][1][79] = 22,
+ [0][0][2][0][RTW89_FCC][2][79] = 68,
+ [0][0][2][0][RTW89_ETSI][1][79] = 127,
+ [0][0][2][0][RTW89_ETSI][0][79] = 127,
+ [0][0][2][0][RTW89_MKK][1][79] = 127,
+ [0][0][2][0][RTW89_MKK][0][79] = 127,
+ [0][0][2][0][RTW89_IC][1][79] = 22,
+ [0][0][2][0][RTW89_KCC][1][79] = 26,
+ [0][0][2][0][RTW89_KCC][0][79] = 127,
+ [0][0][2][0][RTW89_ACMA][1][79] = 127,
+ [0][0][2][0][RTW89_ACMA][0][79] = 127,
+ [0][0][2][0][RTW89_CHILE][1][79] = 22,
+ [0][0][2][0][RTW89_QATAR][1][79] = 127,
+ [0][0][2][0][RTW89_QATAR][0][79] = 127,
+ [0][0][2][0][RTW89_UK][1][79] = 127,
+ [0][0][2][0][RTW89_UK][0][79] = 127,
+ [0][0][2][0][RTW89_FCC][1][81] = 22,
+ [0][0][2][0][RTW89_FCC][2][81] = 68,
+ [0][0][2][0][RTW89_ETSI][1][81] = 127,
+ [0][0][2][0][RTW89_ETSI][0][81] = 127,
+ [0][0][2][0][RTW89_MKK][1][81] = 127,
+ [0][0][2][0][RTW89_MKK][0][81] = 127,
+ [0][0][2][0][RTW89_IC][1][81] = 22,
+ [0][0][2][0][RTW89_KCC][1][81] = 26,
+ [0][0][2][0][RTW89_KCC][0][81] = 127,
+ [0][0][2][0][RTW89_ACMA][1][81] = 127,
+ [0][0][2][0][RTW89_ACMA][0][81] = 127,
+ [0][0][2][0][RTW89_CHILE][1][81] = 22,
+ [0][0][2][0][RTW89_QATAR][1][81] = 127,
+ [0][0][2][0][RTW89_QATAR][0][81] = 127,
+ [0][0][2][0][RTW89_UK][1][81] = 127,
+ [0][0][2][0][RTW89_UK][0][81] = 127,
+ [0][0][2][0][RTW89_FCC][1][83] = 22,
+ [0][0][2][0][RTW89_FCC][2][83] = 68,
+ [0][0][2][0][RTW89_ETSI][1][83] = 127,
+ [0][0][2][0][RTW89_ETSI][0][83] = 127,
+ [0][0][2][0][RTW89_MKK][1][83] = 127,
+ [0][0][2][0][RTW89_MKK][0][83] = 127,
+ [0][0][2][0][RTW89_IC][1][83] = 22,
+ [0][0][2][0][RTW89_KCC][1][83] = 32,
+ [0][0][2][0][RTW89_KCC][0][83] = 127,
+ [0][0][2][0][RTW89_ACMA][1][83] = 127,
+ [0][0][2][0][RTW89_ACMA][0][83] = 127,
+ [0][0][2][0][RTW89_CHILE][1][83] = 22,
+ [0][0][2][0][RTW89_QATAR][1][83] = 127,
+ [0][0][2][0][RTW89_QATAR][0][83] = 127,
+ [0][0][2][0][RTW89_UK][1][83] = 127,
+ [0][0][2][0][RTW89_UK][0][83] = 127,
+ [0][0][2][0][RTW89_FCC][1][85] = 22,
+ [0][0][2][0][RTW89_FCC][2][85] = 68,
+ [0][0][2][0][RTW89_ETSI][1][85] = 127,
+ [0][0][2][0][RTW89_ETSI][0][85] = 127,
+ [0][0][2][0][RTW89_MKK][1][85] = 127,
+ [0][0][2][0][RTW89_MKK][0][85] = 127,
+ [0][0][2][0][RTW89_IC][1][85] = 22,
+ [0][0][2][0][RTW89_KCC][1][85] = 32,
+ [0][0][2][0][RTW89_KCC][0][85] = 127,
+ [0][0][2][0][RTW89_ACMA][1][85] = 127,
+ [0][0][2][0][RTW89_ACMA][0][85] = 127,
+ [0][0][2][0][RTW89_CHILE][1][85] = 22,
+ [0][0][2][0][RTW89_QATAR][1][85] = 127,
+ [0][0][2][0][RTW89_QATAR][0][85] = 127,
+ [0][0][2][0][RTW89_UK][1][85] = 127,
+ [0][0][2][0][RTW89_UK][0][85] = 127,
+ [0][0][2][0][RTW89_FCC][1][87] = 22,
+ [0][0][2][0][RTW89_FCC][2][87] = 127,
+ [0][0][2][0][RTW89_ETSI][1][87] = 127,
+ [0][0][2][0][RTW89_ETSI][0][87] = 127,
+ [0][0][2][0][RTW89_MKK][1][87] = 127,
+ [0][0][2][0][RTW89_MKK][0][87] = 127,
+ [0][0][2][0][RTW89_IC][1][87] = 22,
+ [0][0][2][0][RTW89_KCC][1][87] = 32,
+ [0][0][2][0][RTW89_KCC][0][87] = 127,
+ [0][0][2][0][RTW89_ACMA][1][87] = 127,
+ [0][0][2][0][RTW89_ACMA][0][87] = 127,
+ [0][0][2][0][RTW89_CHILE][1][87] = 22,
+ [0][0][2][0][RTW89_QATAR][1][87] = 127,
+ [0][0][2][0][RTW89_QATAR][0][87] = 127,
+ [0][0][2][0][RTW89_UK][1][87] = 127,
+ [0][0][2][0][RTW89_UK][0][87] = 127,
+ [0][0][2][0][RTW89_FCC][1][89] = 22,
+ [0][0][2][0][RTW89_FCC][2][89] = 127,
+ [0][0][2][0][RTW89_ETSI][1][89] = 127,
+ [0][0][2][0][RTW89_ETSI][0][89] = 127,
+ [0][0][2][0][RTW89_MKK][1][89] = 127,
+ [0][0][2][0][RTW89_MKK][0][89] = 127,
+ [0][0][2][0][RTW89_IC][1][89] = 22,
+ [0][0][2][0][RTW89_KCC][1][89] = 32,
+ [0][0][2][0][RTW89_KCC][0][89] = 127,
+ [0][0][2][0][RTW89_ACMA][1][89] = 127,
+ [0][0][2][0][RTW89_ACMA][0][89] = 127,
+ [0][0][2][0][RTW89_CHILE][1][89] = 22,
+ [0][0][2][0][RTW89_QATAR][1][89] = 127,
+ [0][0][2][0][RTW89_QATAR][0][89] = 127,
+ [0][0][2][0][RTW89_UK][1][89] = 127,
+ [0][0][2][0][RTW89_UK][0][89] = 127,
+ [0][0][2][0][RTW89_FCC][1][90] = 22,
+ [0][0][2][0][RTW89_FCC][2][90] = 127,
+ [0][0][2][0][RTW89_ETSI][1][90] = 127,
+ [0][0][2][0][RTW89_ETSI][0][90] = 127,
+ [0][0][2][0][RTW89_MKK][1][90] = 127,
+ [0][0][2][0][RTW89_MKK][0][90] = 127,
+ [0][0][2][0][RTW89_IC][1][90] = 22,
+ [0][0][2][0][RTW89_KCC][1][90] = 32,
+ [0][0][2][0][RTW89_KCC][0][90] = 127,
+ [0][0][2][0][RTW89_ACMA][1][90] = 127,
+ [0][0][2][0][RTW89_ACMA][0][90] = 127,
+ [0][0][2][0][RTW89_CHILE][1][90] = 22,
+ [0][0][2][0][RTW89_QATAR][1][90] = 127,
+ [0][0][2][0][RTW89_QATAR][0][90] = 127,
+ [0][0][2][0][RTW89_UK][1][90] = 127,
+ [0][0][2][0][RTW89_UK][0][90] = 127,
+ [0][0][2][0][RTW89_FCC][1][92] = 22,
+ [0][0][2][0][RTW89_FCC][2][92] = 127,
+ [0][0][2][0][RTW89_ETSI][1][92] = 127,
+ [0][0][2][0][RTW89_ETSI][0][92] = 127,
+ [0][0][2][0][RTW89_MKK][1][92] = 127,
+ [0][0][2][0][RTW89_MKK][0][92] = 127,
+ [0][0][2][0][RTW89_IC][1][92] = 22,
+ [0][0][2][0][RTW89_KCC][1][92] = 32,
+ [0][0][2][0][RTW89_KCC][0][92] = 127,
+ [0][0][2][0][RTW89_ACMA][1][92] = 127,
+ [0][0][2][0][RTW89_ACMA][0][92] = 127,
+ [0][0][2][0][RTW89_CHILE][1][92] = 22,
+ [0][0][2][0][RTW89_QATAR][1][92] = 127,
+ [0][0][2][0][RTW89_QATAR][0][92] = 127,
+ [0][0][2][0][RTW89_UK][1][92] = 127,
+ [0][0][2][0][RTW89_UK][0][92] = 127,
+ [0][0][2][0][RTW89_FCC][1][94] = 22,
+ [0][0][2][0][RTW89_FCC][2][94] = 127,
+ [0][0][2][0][RTW89_ETSI][1][94] = 127,
+ [0][0][2][0][RTW89_ETSI][0][94] = 127,
+ [0][0][2][0][RTW89_MKK][1][94] = 127,
+ [0][0][2][0][RTW89_MKK][0][94] = 127,
+ [0][0][2][0][RTW89_IC][1][94] = 22,
+ [0][0][2][0][RTW89_KCC][1][94] = 32,
+ [0][0][2][0][RTW89_KCC][0][94] = 127,
+ [0][0][2][0][RTW89_ACMA][1][94] = 127,
+ [0][0][2][0][RTW89_ACMA][0][94] = 127,
+ [0][0][2][0][RTW89_CHILE][1][94] = 22,
+ [0][0][2][0][RTW89_QATAR][1][94] = 127,
+ [0][0][2][0][RTW89_QATAR][0][94] = 127,
+ [0][0][2][0][RTW89_UK][1][94] = 127,
+ [0][0][2][0][RTW89_UK][0][94] = 127,
+ [0][0][2][0][RTW89_FCC][1][96] = 22,
+ [0][0][2][0][RTW89_FCC][2][96] = 127,
+ [0][0][2][0][RTW89_ETSI][1][96] = 127,
+ [0][0][2][0][RTW89_ETSI][0][96] = 127,
+ [0][0][2][0][RTW89_MKK][1][96] = 127,
+ [0][0][2][0][RTW89_MKK][0][96] = 127,
+ [0][0][2][0][RTW89_IC][1][96] = 22,
+ [0][0][2][0][RTW89_KCC][1][96] = 32,
+ [0][0][2][0][RTW89_KCC][0][96] = 127,
+ [0][0][2][0][RTW89_ACMA][1][96] = 127,
+ [0][0][2][0][RTW89_ACMA][0][96] = 127,
+ [0][0][2][0][RTW89_CHILE][1][96] = 22,
+ [0][0][2][0][RTW89_QATAR][1][96] = 127,
+ [0][0][2][0][RTW89_QATAR][0][96] = 127,
+ [0][0][2][0][RTW89_UK][1][96] = 127,
+ [0][0][2][0][RTW89_UK][0][96] = 127,
+ [0][0][2][0][RTW89_FCC][1][98] = 22,
+ [0][0][2][0][RTW89_FCC][2][98] = 127,
+ [0][0][2][0][RTW89_ETSI][1][98] = 127,
+ [0][0][2][0][RTW89_ETSI][0][98] = 127,
+ [0][0][2][0][RTW89_MKK][1][98] = 127,
+ [0][0][2][0][RTW89_MKK][0][98] = 127,
+ [0][0][2][0][RTW89_IC][1][98] = 22,
+ [0][0][2][0][RTW89_KCC][1][98] = 32,
+ [0][0][2][0][RTW89_KCC][0][98] = 127,
+ [0][0][2][0][RTW89_ACMA][1][98] = 127,
+ [0][0][2][0][RTW89_ACMA][0][98] = 127,
+ [0][0][2][0][RTW89_CHILE][1][98] = 22,
+ [0][0][2][0][RTW89_QATAR][1][98] = 127,
+ [0][0][2][0][RTW89_QATAR][0][98] = 127,
+ [0][0][2][0][RTW89_UK][1][98] = 127,
+ [0][0][2][0][RTW89_UK][0][98] = 127,
+ [0][0][2][0][RTW89_FCC][1][100] = 22,
+ [0][0][2][0][RTW89_FCC][2][100] = 127,
+ [0][0][2][0][RTW89_ETSI][1][100] = 127,
+ [0][0][2][0][RTW89_ETSI][0][100] = 127,
+ [0][0][2][0][RTW89_MKK][1][100] = 127,
+ [0][0][2][0][RTW89_MKK][0][100] = 127,
+ [0][0][2][0][RTW89_IC][1][100] = 22,
+ [0][0][2][0][RTW89_KCC][1][100] = 32,
+ [0][0][2][0][RTW89_KCC][0][100] = 127,
+ [0][0][2][0][RTW89_ACMA][1][100] = 127,
+ [0][0][2][0][RTW89_ACMA][0][100] = 127,
+ [0][0][2][0][RTW89_CHILE][1][100] = 22,
+ [0][0][2][0][RTW89_QATAR][1][100] = 127,
+ [0][0][2][0][RTW89_QATAR][0][100] = 127,
+ [0][0][2][0][RTW89_UK][1][100] = 127,
+ [0][0][2][0][RTW89_UK][0][100] = 127,
+ [0][0][2][0][RTW89_FCC][1][102] = 22,
+ [0][0][2][0][RTW89_FCC][2][102] = 127,
+ [0][0][2][0][RTW89_ETSI][1][102] = 127,
+ [0][0][2][0][RTW89_ETSI][0][102] = 127,
+ [0][0][2][0][RTW89_MKK][1][102] = 127,
+ [0][0][2][0][RTW89_MKK][0][102] = 127,
+ [0][0][2][0][RTW89_IC][1][102] = 22,
+ [0][0][2][0][RTW89_KCC][1][102] = 32,
+ [0][0][2][0][RTW89_KCC][0][102] = 127,
+ [0][0][2][0][RTW89_ACMA][1][102] = 127,
+ [0][0][2][0][RTW89_ACMA][0][102] = 127,
+ [0][0][2][0][RTW89_CHILE][1][102] = 22,
+ [0][0][2][0][RTW89_QATAR][1][102] = 127,
+ [0][0][2][0][RTW89_QATAR][0][102] = 127,
+ [0][0][2][0][RTW89_UK][1][102] = 127,
+ [0][0][2][0][RTW89_UK][0][102] = 127,
+ [0][0][2][0][RTW89_FCC][1][104] = 22,
+ [0][0][2][0][RTW89_FCC][2][104] = 127,
+ [0][0][2][0][RTW89_ETSI][1][104] = 127,
+ [0][0][2][0][RTW89_ETSI][0][104] = 127,
+ [0][0][2][0][RTW89_MKK][1][104] = 127,
+ [0][0][2][0][RTW89_MKK][0][104] = 127,
+ [0][0][2][0][RTW89_IC][1][104] = 22,
+ [0][0][2][0][RTW89_KCC][1][104] = 32,
+ [0][0][2][0][RTW89_KCC][0][104] = 127,
+ [0][0][2][0][RTW89_ACMA][1][104] = 127,
+ [0][0][2][0][RTW89_ACMA][0][104] = 127,
+ [0][0][2][0][RTW89_CHILE][1][104] = 22,
+ [0][0][2][0][RTW89_QATAR][1][104] = 127,
+ [0][0][2][0][RTW89_QATAR][0][104] = 127,
+ [0][0][2][0][RTW89_UK][1][104] = 127,
+ [0][0][2][0][RTW89_UK][0][104] = 127,
+ [0][0][2][0][RTW89_FCC][1][105] = 22,
+ [0][0][2][0][RTW89_FCC][2][105] = 127,
+ [0][0][2][0][RTW89_ETSI][1][105] = 127,
+ [0][0][2][0][RTW89_ETSI][0][105] = 127,
+ [0][0][2][0][RTW89_MKK][1][105] = 127,
+ [0][0][2][0][RTW89_MKK][0][105] = 127,
+ [0][0][2][0][RTW89_IC][1][105] = 22,
+ [0][0][2][0][RTW89_KCC][1][105] = 32,
+ [0][0][2][0][RTW89_KCC][0][105] = 127,
+ [0][0][2][0][RTW89_ACMA][1][105] = 127,
+ [0][0][2][0][RTW89_ACMA][0][105] = 127,
+ [0][0][2][0][RTW89_CHILE][1][105] = 22,
+ [0][0][2][0][RTW89_QATAR][1][105] = 127,
+ [0][0][2][0][RTW89_QATAR][0][105] = 127,
+ [0][0][2][0][RTW89_UK][1][105] = 127,
+ [0][0][2][0][RTW89_UK][0][105] = 127,
+ [0][0][2][0][RTW89_FCC][1][107] = 24,
+ [0][0][2][0][RTW89_FCC][2][107] = 127,
+ [0][0][2][0][RTW89_ETSI][1][107] = 127,
+ [0][0][2][0][RTW89_ETSI][0][107] = 127,
+ [0][0][2][0][RTW89_MKK][1][107] = 127,
+ [0][0][2][0][RTW89_MKK][0][107] = 127,
+ [0][0][2][0][RTW89_IC][1][107] = 24,
+ [0][0][2][0][RTW89_KCC][1][107] = 32,
+ [0][0][2][0][RTW89_KCC][0][107] = 127,
+ [0][0][2][0][RTW89_ACMA][1][107] = 127,
+ [0][0][2][0][RTW89_ACMA][0][107] = 127,
+ [0][0][2][0][RTW89_CHILE][1][107] = 24,
+ [0][0][2][0][RTW89_QATAR][1][107] = 127,
+ [0][0][2][0][RTW89_QATAR][0][107] = 127,
+ [0][0][2][0][RTW89_UK][1][107] = 127,
+ [0][0][2][0][RTW89_UK][0][107] = 127,
+ [0][0][2][0][RTW89_FCC][1][109] = 24,
+ [0][0][2][0][RTW89_FCC][2][109] = 127,
+ [0][0][2][0][RTW89_ETSI][1][109] = 127,
+ [0][0][2][0][RTW89_ETSI][0][109] = 127,
+ [0][0][2][0][RTW89_MKK][1][109] = 127,
+ [0][0][2][0][RTW89_MKK][0][109] = 127,
+ [0][0][2][0][RTW89_IC][1][109] = 24,
+ [0][0][2][0][RTW89_KCC][1][109] = 32,
+ [0][0][2][0][RTW89_KCC][0][109] = 127,
+ [0][0][2][0][RTW89_ACMA][1][109] = 127,
+ [0][0][2][0][RTW89_ACMA][0][109] = 127,
+ [0][0][2][0][RTW89_CHILE][1][109] = 24,
+ [0][0][2][0][RTW89_QATAR][1][109] = 127,
+ [0][0][2][0][RTW89_QATAR][0][109] = 127,
+ [0][0][2][0][RTW89_UK][1][109] = 127,
+ [0][0][2][0][RTW89_UK][0][109] = 127,
+ [0][0][2][0][RTW89_FCC][1][111] = 127,
+ [0][0][2][0][RTW89_FCC][2][111] = 127,
+ [0][0][2][0][RTW89_ETSI][1][111] = 127,
+ [0][0][2][0][RTW89_ETSI][0][111] = 127,
+ [0][0][2][0][RTW89_MKK][1][111] = 127,
+ [0][0][2][0][RTW89_MKK][0][111] = 127,
+ [0][0][2][0][RTW89_IC][1][111] = 127,
+ [0][0][2][0][RTW89_KCC][1][111] = 127,
+ [0][0][2][0][RTW89_KCC][0][111] = 127,
+ [0][0][2][0][RTW89_ACMA][1][111] = 127,
+ [0][0][2][0][RTW89_ACMA][0][111] = 127,
+ [0][0][2][0][RTW89_CHILE][1][111] = 127,
+ [0][0][2][0][RTW89_QATAR][1][111] = 127,
+ [0][0][2][0][RTW89_QATAR][0][111] = 127,
+ [0][0][2][0][RTW89_UK][1][111] = 127,
+ [0][0][2][0][RTW89_UK][0][111] = 127,
+ [0][0][2][0][RTW89_FCC][1][113] = 127,
+ [0][0][2][0][RTW89_FCC][2][113] = 127,
+ [0][0][2][0][RTW89_ETSI][1][113] = 127,
+ [0][0][2][0][RTW89_ETSI][0][113] = 127,
+ [0][0][2][0][RTW89_MKK][1][113] = 127,
+ [0][0][2][0][RTW89_MKK][0][113] = 127,
+ [0][0][2][0][RTW89_IC][1][113] = 127,
+ [0][0][2][0][RTW89_KCC][1][113] = 127,
+ [0][0][2][0][RTW89_KCC][0][113] = 127,
+ [0][0][2][0][RTW89_ACMA][1][113] = 127,
+ [0][0][2][0][RTW89_ACMA][0][113] = 127,
+ [0][0][2][0][RTW89_CHILE][1][113] = 127,
+ [0][0][2][0][RTW89_QATAR][1][113] = 127,
+ [0][0][2][0][RTW89_QATAR][0][113] = 127,
+ [0][0][2][0][RTW89_UK][1][113] = 127,
+ [0][0][2][0][RTW89_UK][0][113] = 127,
+ [0][0][2][0][RTW89_FCC][1][115] = 127,
+ [0][0][2][0][RTW89_FCC][2][115] = 127,
+ [0][0][2][0][RTW89_ETSI][1][115] = 127,
+ [0][0][2][0][RTW89_ETSI][0][115] = 127,
+ [0][0][2][0][RTW89_MKK][1][115] = 127,
+ [0][0][2][0][RTW89_MKK][0][115] = 127,
+ [0][0][2][0][RTW89_IC][1][115] = 127,
+ [0][0][2][0][RTW89_KCC][1][115] = 127,
+ [0][0][2][0][RTW89_KCC][0][115] = 127,
+ [0][0][2][0][RTW89_ACMA][1][115] = 127,
+ [0][0][2][0][RTW89_ACMA][0][115] = 127,
+ [0][0][2][0][RTW89_CHILE][1][115] = 127,
+ [0][0][2][0][RTW89_QATAR][1][115] = 127,
+ [0][0][2][0][RTW89_QATAR][0][115] = 127,
+ [0][0][2][0][RTW89_UK][1][115] = 127,
+ [0][0][2][0][RTW89_UK][0][115] = 127,
+ [0][0][2][0][RTW89_FCC][1][117] = 127,
+ [0][0][2][0][RTW89_FCC][2][117] = 127,
+ [0][0][2][0][RTW89_ETSI][1][117] = 127,
+ [0][0][2][0][RTW89_ETSI][0][117] = 127,
+ [0][0][2][0][RTW89_MKK][1][117] = 127,
+ [0][0][2][0][RTW89_MKK][0][117] = 127,
+ [0][0][2][0][RTW89_IC][1][117] = 127,
+ [0][0][2][0][RTW89_KCC][1][117] = 127,
+ [0][0][2][0][RTW89_KCC][0][117] = 127,
+ [0][0][2][0][RTW89_ACMA][1][117] = 127,
+ [0][0][2][0][RTW89_ACMA][0][117] = 127,
+ [0][0][2][0][RTW89_CHILE][1][117] = 127,
+ [0][0][2][0][RTW89_QATAR][1][117] = 127,
+ [0][0][2][0][RTW89_QATAR][0][117] = 127,
+ [0][0][2][0][RTW89_UK][1][117] = 127,
+ [0][0][2][0][RTW89_UK][0][117] = 127,
+ [0][0][2][0][RTW89_FCC][1][119] = 127,
+ [0][0][2][0][RTW89_FCC][2][119] = 127,
+ [0][0][2][0][RTW89_ETSI][1][119] = 127,
+ [0][0][2][0][RTW89_ETSI][0][119] = 127,
+ [0][0][2][0][RTW89_MKK][1][119] = 127,
+ [0][0][2][0][RTW89_MKK][0][119] = 127,
+ [0][0][2][0][RTW89_IC][1][119] = 127,
+ [0][0][2][0][RTW89_KCC][1][119] = 127,
+ [0][0][2][0][RTW89_KCC][0][119] = 127,
+ [0][0][2][0][RTW89_ACMA][1][119] = 127,
+ [0][0][2][0][RTW89_ACMA][0][119] = 127,
+ [0][0][2][0][RTW89_CHILE][1][119] = 127,
+ [0][0][2][0][RTW89_QATAR][1][119] = 127,
+ [0][0][2][0][RTW89_QATAR][0][119] = 127,
+ [0][0][2][0][RTW89_UK][1][119] = 127,
+ [0][0][2][0][RTW89_UK][0][119] = 127,
+ [0][1][2][0][RTW89_FCC][1][0] = -2,
+ [0][1][2][0][RTW89_FCC][2][0] = 54,
+ [0][1][2][0][RTW89_ETSI][1][0] = 54,
+ [0][1][2][0][RTW89_ETSI][0][0] = 18,
+ [0][1][2][0][RTW89_MKK][1][0] = 56,
+ [0][1][2][0][RTW89_MKK][0][0] = 16,
+ [0][1][2][0][RTW89_IC][1][0] = -2,
+ [0][1][2][0][RTW89_KCC][1][0] = 12,
+ [0][1][2][0][RTW89_KCC][0][0] = 10,
+ [0][1][2][0][RTW89_ACMA][1][0] = 54,
+ [0][1][2][0][RTW89_ACMA][0][0] = 18,
+ [0][1][2][0][RTW89_CHILE][1][0] = -2,
+ [0][1][2][0][RTW89_QATAR][1][0] = 54,
+ [0][1][2][0][RTW89_QATAR][0][0] = 18,
+ [0][1][2][0][RTW89_UK][1][0] = 54,
+ [0][1][2][0][RTW89_UK][0][0] = 18,
+ [0][1][2][0][RTW89_FCC][1][2] = -4,
+ [0][1][2][0][RTW89_FCC][2][2] = 54,
+ [0][1][2][0][RTW89_ETSI][1][2] = 54,
+ [0][1][2][0][RTW89_ETSI][0][2] = 18,
+ [0][1][2][0][RTW89_MKK][1][2] = 54,
+ [0][1][2][0][RTW89_MKK][0][2] = 16,
+ [0][1][2][0][RTW89_IC][1][2] = -4,
+ [0][1][2][0][RTW89_KCC][1][2] = 12,
+ [0][1][2][0][RTW89_KCC][0][2] = 12,
+ [0][1][2][0][RTW89_ACMA][1][2] = 54,
+ [0][1][2][0][RTW89_ACMA][0][2] = 18,
+ [0][1][2][0][RTW89_CHILE][1][2] = -4,
+ [0][1][2][0][RTW89_QATAR][1][2] = 54,
+ [0][1][2][0][RTW89_QATAR][0][2] = 18,
+ [0][1][2][0][RTW89_UK][1][2] = 54,
+ [0][1][2][0][RTW89_UK][0][2] = 18,
+ [0][1][2][0][RTW89_FCC][1][4] = -4,
+ [0][1][2][0][RTW89_FCC][2][4] = 54,
+ [0][1][2][0][RTW89_ETSI][1][4] = 54,
+ [0][1][2][0][RTW89_ETSI][0][4] = 18,
+ [0][1][2][0][RTW89_MKK][1][4] = 54,
+ [0][1][2][0][RTW89_MKK][0][4] = 16,
+ [0][1][2][0][RTW89_IC][1][4] = -4,
+ [0][1][2][0][RTW89_KCC][1][4] = 12,
+ [0][1][2][0][RTW89_KCC][0][4] = 12,
+ [0][1][2][0][RTW89_ACMA][1][4] = 54,
+ [0][1][2][0][RTW89_ACMA][0][4] = 18,
+ [0][1][2][0][RTW89_CHILE][1][4] = -4,
+ [0][1][2][0][RTW89_QATAR][1][4] = 54,
+ [0][1][2][0][RTW89_QATAR][0][4] = 18,
+ [0][1][2][0][RTW89_UK][1][4] = 54,
+ [0][1][2][0][RTW89_UK][0][4] = 18,
+ [0][1][2][0][RTW89_FCC][1][6] = -4,
+ [0][1][2][0][RTW89_FCC][2][6] = 54,
+ [0][1][2][0][RTW89_ETSI][1][6] = 54,
+ [0][1][2][0][RTW89_ETSI][0][6] = 18,
+ [0][1][2][0][RTW89_MKK][1][6] = 54,
+ [0][1][2][0][RTW89_MKK][0][6] = 16,
+ [0][1][2][0][RTW89_IC][1][6] = -4,
+ [0][1][2][0][RTW89_KCC][1][6] = 12,
+ [0][1][2][0][RTW89_KCC][0][6] = 12,
+ [0][1][2][0][RTW89_ACMA][1][6] = 54,
+ [0][1][2][0][RTW89_ACMA][0][6] = 18,
+ [0][1][2][0][RTW89_CHILE][1][6] = -4,
+ [0][1][2][0][RTW89_QATAR][1][6] = 54,
+ [0][1][2][0][RTW89_QATAR][0][6] = 18,
+ [0][1][2][0][RTW89_UK][1][6] = 54,
+ [0][1][2][0][RTW89_UK][0][6] = 18,
+ [0][1][2][0][RTW89_FCC][1][8] = -4,
+ [0][1][2][0][RTW89_FCC][2][8] = 54,
+ [0][1][2][0][RTW89_ETSI][1][8] = 54,
+ [0][1][2][0][RTW89_ETSI][0][8] = 18,
+ [0][1][2][0][RTW89_MKK][1][8] = 54,
+ [0][1][2][0][RTW89_MKK][0][8] = 16,
+ [0][1][2][0][RTW89_IC][1][8] = -4,
+ [0][1][2][0][RTW89_KCC][1][8] = 12,
+ [0][1][2][0][RTW89_KCC][0][8] = 12,
+ [0][1][2][0][RTW89_ACMA][1][8] = 54,
+ [0][1][2][0][RTW89_ACMA][0][8] = 18,
+ [0][1][2][0][RTW89_CHILE][1][8] = -4,
+ [0][1][2][0][RTW89_QATAR][1][8] = 54,
+ [0][1][2][0][RTW89_QATAR][0][8] = 18,
+ [0][1][2][0][RTW89_UK][1][8] = 54,
+ [0][1][2][0][RTW89_UK][0][8] = 18,
+ [0][1][2][0][RTW89_FCC][1][10] = -4,
+ [0][1][2][0][RTW89_FCC][2][10] = 54,
+ [0][1][2][0][RTW89_ETSI][1][10] = 54,
+ [0][1][2][0][RTW89_ETSI][0][10] = 18,
+ [0][1][2][0][RTW89_MKK][1][10] = 54,
+ [0][1][2][0][RTW89_MKK][0][10] = 16,
+ [0][1][2][0][RTW89_IC][1][10] = -4,
+ [0][1][2][0][RTW89_KCC][1][10] = 12,
+ [0][1][2][0][RTW89_KCC][0][10] = 12,
+ [0][1][2][0][RTW89_ACMA][1][10] = 54,
+ [0][1][2][0][RTW89_ACMA][0][10] = 18,
+ [0][1][2][0][RTW89_CHILE][1][10] = -4,
+ [0][1][2][0][RTW89_QATAR][1][10] = 54,
+ [0][1][2][0][RTW89_QATAR][0][10] = 18,
+ [0][1][2][0][RTW89_UK][1][10] = 54,
+ [0][1][2][0][RTW89_UK][0][10] = 18,
+ [0][1][2][0][RTW89_FCC][1][12] = -4,
+ [0][1][2][0][RTW89_FCC][2][12] = 54,
+ [0][1][2][0][RTW89_ETSI][1][12] = 54,
+ [0][1][2][0][RTW89_ETSI][0][12] = 18,
+ [0][1][2][0][RTW89_MKK][1][12] = 54,
+ [0][1][2][0][RTW89_MKK][0][12] = 16,
+ [0][1][2][0][RTW89_IC][1][12] = -4,
+ [0][1][2][0][RTW89_KCC][1][12] = 12,
+ [0][1][2][0][RTW89_KCC][0][12] = 12,
+ [0][1][2][0][RTW89_ACMA][1][12] = 54,
+ [0][1][2][0][RTW89_ACMA][0][12] = 18,
+ [0][1][2][0][RTW89_CHILE][1][12] = -4,
+ [0][1][2][0][RTW89_QATAR][1][12] = 54,
+ [0][1][2][0][RTW89_QATAR][0][12] = 18,
+ [0][1][2][0][RTW89_UK][1][12] = 54,
+ [0][1][2][0][RTW89_UK][0][12] = 18,
+ [0][1][2][0][RTW89_FCC][1][14] = -4,
+ [0][1][2][0][RTW89_FCC][2][14] = 54,
+ [0][1][2][0][RTW89_ETSI][1][14] = 54,
+ [0][1][2][0][RTW89_ETSI][0][14] = 18,
+ [0][1][2][0][RTW89_MKK][1][14] = 54,
+ [0][1][2][0][RTW89_MKK][0][14] = 16,
+ [0][1][2][0][RTW89_IC][1][14] = -4,
+ [0][1][2][0][RTW89_KCC][1][14] = 12,
+ [0][1][2][0][RTW89_KCC][0][14] = 12,
+ [0][1][2][0][RTW89_ACMA][1][14] = 54,
+ [0][1][2][0][RTW89_ACMA][0][14] = 18,
+ [0][1][2][0][RTW89_CHILE][1][14] = -4,
+ [0][1][2][0][RTW89_QATAR][1][14] = 54,
+ [0][1][2][0][RTW89_QATAR][0][14] = 18,
+ [0][1][2][0][RTW89_UK][1][14] = 54,
+ [0][1][2][0][RTW89_UK][0][14] = 18,
+ [0][1][2][0][RTW89_FCC][1][15] = -4,
+ [0][1][2][0][RTW89_FCC][2][15] = 54,
+ [0][1][2][0][RTW89_ETSI][1][15] = 54,
+ [0][1][2][0][RTW89_ETSI][0][15] = 18,
+ [0][1][2][0][RTW89_MKK][1][15] = 54,
+ [0][1][2][0][RTW89_MKK][0][15] = 16,
+ [0][1][2][0][RTW89_IC][1][15] = -4,
+ [0][1][2][0][RTW89_KCC][1][15] = 12,
+ [0][1][2][0][RTW89_KCC][0][15] = 12,
+ [0][1][2][0][RTW89_ACMA][1][15] = 54,
+ [0][1][2][0][RTW89_ACMA][0][15] = 18,
+ [0][1][2][0][RTW89_CHILE][1][15] = -4,
+ [0][1][2][0][RTW89_QATAR][1][15] = 54,
+ [0][1][2][0][RTW89_QATAR][0][15] = 18,
+ [0][1][2][0][RTW89_UK][1][15] = 54,
+ [0][1][2][0][RTW89_UK][0][15] = 18,
+ [0][1][2][0][RTW89_FCC][1][17] = -4,
+ [0][1][2][0][RTW89_FCC][2][17] = 54,
+ [0][1][2][0][RTW89_ETSI][1][17] = 54,
+ [0][1][2][0][RTW89_ETSI][0][17] = 18,
+ [0][1][2][0][RTW89_MKK][1][17] = 54,
+ [0][1][2][0][RTW89_MKK][0][17] = 16,
+ [0][1][2][0][RTW89_IC][1][17] = -4,
+ [0][1][2][0][RTW89_KCC][1][17] = 12,
+ [0][1][2][0][RTW89_KCC][0][17] = 12,
+ [0][1][2][0][RTW89_ACMA][1][17] = 54,
+ [0][1][2][0][RTW89_ACMA][0][17] = 18,
+ [0][1][2][0][RTW89_CHILE][1][17] = -4,
+ [0][1][2][0][RTW89_QATAR][1][17] = 54,
+ [0][1][2][0][RTW89_QATAR][0][17] = 18,
+ [0][1][2][0][RTW89_UK][1][17] = 54,
+ [0][1][2][0][RTW89_UK][0][17] = 18,
+ [0][1][2][0][RTW89_FCC][1][19] = -4,
+ [0][1][2][0][RTW89_FCC][2][19] = 54,
+ [0][1][2][0][RTW89_ETSI][1][19] = 54,
+ [0][1][2][0][RTW89_ETSI][0][19] = 18,
+ [0][1][2][0][RTW89_MKK][1][19] = 54,
+ [0][1][2][0][RTW89_MKK][0][19] = 16,
+ [0][1][2][0][RTW89_IC][1][19] = -4,
+ [0][1][2][0][RTW89_KCC][1][19] = 12,
+ [0][1][2][0][RTW89_KCC][0][19] = 12,
+ [0][1][2][0][RTW89_ACMA][1][19] = 54,
+ [0][1][2][0][RTW89_ACMA][0][19] = 18,
+ [0][1][2][0][RTW89_CHILE][1][19] = -4,
+ [0][1][2][0][RTW89_QATAR][1][19] = 54,
+ [0][1][2][0][RTW89_QATAR][0][19] = 18,
+ [0][1][2][0][RTW89_UK][1][19] = 54,
+ [0][1][2][0][RTW89_UK][0][19] = 18,
+ [0][1][2][0][RTW89_FCC][1][21] = -4,
+ [0][1][2][0][RTW89_FCC][2][21] = 54,
+ [0][1][2][0][RTW89_ETSI][1][21] = 54,
+ [0][1][2][0][RTW89_ETSI][0][21] = 18,
+ [0][1][2][0][RTW89_MKK][1][21] = 54,
+ [0][1][2][0][RTW89_MKK][0][21] = 16,
+ [0][1][2][0][RTW89_IC][1][21] = -4,
+ [0][1][2][0][RTW89_KCC][1][21] = 12,
+ [0][1][2][0][RTW89_KCC][0][21] = 12,
+ [0][1][2][0][RTW89_ACMA][1][21] = 54,
+ [0][1][2][0][RTW89_ACMA][0][21] = 18,
+ [0][1][2][0][RTW89_CHILE][1][21] = -4,
+ [0][1][2][0][RTW89_QATAR][1][21] = 54,
+ [0][1][2][0][RTW89_QATAR][0][21] = 18,
+ [0][1][2][0][RTW89_UK][1][21] = 54,
+ [0][1][2][0][RTW89_UK][0][21] = 18,
+ [0][1][2][0][RTW89_FCC][1][23] = -4,
+ [0][1][2][0][RTW89_FCC][2][23] = 68,
+ [0][1][2][0][RTW89_ETSI][1][23] = 54,
+ [0][1][2][0][RTW89_ETSI][0][23] = 18,
+ [0][1][2][0][RTW89_MKK][1][23] = 54,
+ [0][1][2][0][RTW89_MKK][0][23] = 16,
+ [0][1][2][0][RTW89_IC][1][23] = -4,
+ [0][1][2][0][RTW89_KCC][1][23] = 12,
+ [0][1][2][0][RTW89_KCC][0][23] = 10,
+ [0][1][2][0][RTW89_ACMA][1][23] = 54,
+ [0][1][2][0][RTW89_ACMA][0][23] = 18,
+ [0][1][2][0][RTW89_CHILE][1][23] = -4,
+ [0][1][2][0][RTW89_QATAR][1][23] = 54,
+ [0][1][2][0][RTW89_QATAR][0][23] = 18,
+ [0][1][2][0][RTW89_UK][1][23] = 54,
+ [0][1][2][0][RTW89_UK][0][23] = 18,
+ [0][1][2][0][RTW89_FCC][1][25] = -4,
+ [0][1][2][0][RTW89_FCC][2][25] = 68,
+ [0][1][2][0][RTW89_ETSI][1][25] = 54,
+ [0][1][2][0][RTW89_ETSI][0][25] = 18,
+ [0][1][2][0][RTW89_MKK][1][25] = 54,
+ [0][1][2][0][RTW89_MKK][0][25] = 16,
+ [0][1][2][0][RTW89_IC][1][25] = -4,
+ [0][1][2][0][RTW89_KCC][1][25] = 12,
+ [0][1][2][0][RTW89_KCC][0][25] = 14,
+ [0][1][2][0][RTW89_ACMA][1][25] = 54,
+ [0][1][2][0][RTW89_ACMA][0][25] = 18,
+ [0][1][2][0][RTW89_CHILE][1][25] = -4,
+ [0][1][2][0][RTW89_QATAR][1][25] = 54,
+ [0][1][2][0][RTW89_QATAR][0][25] = 18,
+ [0][1][2][0][RTW89_UK][1][25] = 54,
+ [0][1][2][0][RTW89_UK][0][25] = 18,
+ [0][1][2][0][RTW89_FCC][1][27] = -4,
+ [0][1][2][0][RTW89_FCC][2][27] = 68,
+ [0][1][2][0][RTW89_ETSI][1][27] = 54,
+ [0][1][2][0][RTW89_ETSI][0][27] = 18,
+ [0][1][2][0][RTW89_MKK][1][27] = 54,
+ [0][1][2][0][RTW89_MKK][0][27] = 16,
+ [0][1][2][0][RTW89_IC][1][27] = -4,
+ [0][1][2][0][RTW89_KCC][1][27] = 12,
+ [0][1][2][0][RTW89_KCC][0][27] = 14,
+ [0][1][2][0][RTW89_ACMA][1][27] = 54,
+ [0][1][2][0][RTW89_ACMA][0][27] = 18,
+ [0][1][2][0][RTW89_CHILE][1][27] = -4,
+ [0][1][2][0][RTW89_QATAR][1][27] = 54,
+ [0][1][2][0][RTW89_QATAR][0][27] = 18,
+ [0][1][2][0][RTW89_UK][1][27] = 54,
+ [0][1][2][0][RTW89_UK][0][27] = 18,
+ [0][1][2][0][RTW89_FCC][1][29] = -4,
+ [0][1][2][0][RTW89_FCC][2][29] = 68,
+ [0][1][2][0][RTW89_ETSI][1][29] = 54,
+ [0][1][2][0][RTW89_ETSI][0][29] = 18,
+ [0][1][2][0][RTW89_MKK][1][29] = 54,
+ [0][1][2][0][RTW89_MKK][0][29] = 16,
+ [0][1][2][0][RTW89_IC][1][29] = -4,
+ [0][1][2][0][RTW89_KCC][1][29] = 12,
+ [0][1][2][0][RTW89_KCC][0][29] = 14,
+ [0][1][2][0][RTW89_ACMA][1][29] = 54,
+ [0][1][2][0][RTW89_ACMA][0][29] = 18,
+ [0][1][2][0][RTW89_CHILE][1][29] = -4,
+ [0][1][2][0][RTW89_QATAR][1][29] = 54,
+ [0][1][2][0][RTW89_QATAR][0][29] = 18,
+ [0][1][2][0][RTW89_UK][1][29] = 54,
+ [0][1][2][0][RTW89_UK][0][29] = 18,
+ [0][1][2][0][RTW89_FCC][1][30] = -4,
+ [0][1][2][0][RTW89_FCC][2][30] = 68,
+ [0][1][2][0][RTW89_ETSI][1][30] = 54,
+ [0][1][2][0][RTW89_ETSI][0][30] = 18,
+ [0][1][2][0][RTW89_MKK][1][30] = 54,
+ [0][1][2][0][RTW89_MKK][0][30] = 16,
+ [0][1][2][0][RTW89_IC][1][30] = -4,
+ [0][1][2][0][RTW89_KCC][1][30] = 12,
+ [0][1][2][0][RTW89_KCC][0][30] = 14,
+ [0][1][2][0][RTW89_ACMA][1][30] = 54,
+ [0][1][2][0][RTW89_ACMA][0][30] = 18,
+ [0][1][2][0][RTW89_CHILE][1][30] = -4,
+ [0][1][2][0][RTW89_QATAR][1][30] = 54,
+ [0][1][2][0][RTW89_QATAR][0][30] = 18,
+ [0][1][2][0][RTW89_UK][1][30] = 54,
+ [0][1][2][0][RTW89_UK][0][30] = 18,
+ [0][1][2][0][RTW89_FCC][1][32] = -4,
+ [0][1][2][0][RTW89_FCC][2][32] = 68,
+ [0][1][2][0][RTW89_ETSI][1][32] = 54,
+ [0][1][2][0][RTW89_ETSI][0][32] = 18,
+ [0][1][2][0][RTW89_MKK][1][32] = 54,
+ [0][1][2][0][RTW89_MKK][0][32] = 16,
+ [0][1][2][0][RTW89_IC][1][32] = -4,
+ [0][1][2][0][RTW89_KCC][1][32] = 12,
+ [0][1][2][0][RTW89_KCC][0][32] = 14,
+ [0][1][2][0][RTW89_ACMA][1][32] = 54,
+ [0][1][2][0][RTW89_ACMA][0][32] = 18,
+ [0][1][2][0][RTW89_CHILE][1][32] = -4,
+ [0][1][2][0][RTW89_QATAR][1][32] = 54,
+ [0][1][2][0][RTW89_QATAR][0][32] = 18,
+ [0][1][2][0][RTW89_UK][1][32] = 54,
+ [0][1][2][0][RTW89_UK][0][32] = 18,
+ [0][1][2][0][RTW89_FCC][1][34] = -4,
+ [0][1][2][0][RTW89_FCC][2][34] = 68,
+ [0][1][2][0][RTW89_ETSI][1][34] = 54,
+ [0][1][2][0][RTW89_ETSI][0][34] = 18,
+ [0][1][2][0][RTW89_MKK][1][34] = 54,
+ [0][1][2][0][RTW89_MKK][0][34] = 16,
+ [0][1][2][0][RTW89_IC][1][34] = -4,
+ [0][1][2][0][RTW89_KCC][1][34] = 12,
+ [0][1][2][0][RTW89_KCC][0][34] = 14,
+ [0][1][2][0][RTW89_ACMA][1][34] = 54,
+ [0][1][2][0][RTW89_ACMA][0][34] = 18,
+ [0][1][2][0][RTW89_CHILE][1][34] = -4,
+ [0][1][2][0][RTW89_QATAR][1][34] = 54,
+ [0][1][2][0][RTW89_QATAR][0][34] = 18,
+ [0][1][2][0][RTW89_UK][1][34] = 54,
+ [0][1][2][0][RTW89_UK][0][34] = 18,
+ [0][1][2][0][RTW89_FCC][1][36] = -4,
+ [0][1][2][0][RTW89_FCC][2][36] = 68,
+ [0][1][2][0][RTW89_ETSI][1][36] = 54,
+ [0][1][2][0][RTW89_ETSI][0][36] = 18,
+ [0][1][2][0][RTW89_MKK][1][36] = 54,
+ [0][1][2][0][RTW89_MKK][0][36] = 16,
+ [0][1][2][0][RTW89_IC][1][36] = -4,
+ [0][1][2][0][RTW89_KCC][1][36] = 12,
+ [0][1][2][0][RTW89_KCC][0][36] = 14,
+ [0][1][2][0][RTW89_ACMA][1][36] = 54,
+ [0][1][2][0][RTW89_ACMA][0][36] = 18,
+ [0][1][2][0][RTW89_CHILE][1][36] = -4,
+ [0][1][2][0][RTW89_QATAR][1][36] = 54,
+ [0][1][2][0][RTW89_QATAR][0][36] = 18,
+ [0][1][2][0][RTW89_UK][1][36] = 54,
+ [0][1][2][0][RTW89_UK][0][36] = 18,
+ [0][1][2][0][RTW89_FCC][1][38] = -4,
+ [0][1][2][0][RTW89_FCC][2][38] = 68,
+ [0][1][2][0][RTW89_ETSI][1][38] = 54,
+ [0][1][2][0][RTW89_ETSI][0][38] = 18,
+ [0][1][2][0][RTW89_MKK][1][38] = 54,
+ [0][1][2][0][RTW89_MKK][0][38] = 16,
+ [0][1][2][0][RTW89_IC][1][38] = -4,
+ [0][1][2][0][RTW89_KCC][1][38] = 12,
+ [0][1][2][0][RTW89_KCC][0][38] = 14,
+ [0][1][2][0][RTW89_ACMA][1][38] = 54,
+ [0][1][2][0][RTW89_ACMA][0][38] = 18,
+ [0][1][2][0][RTW89_CHILE][1][38] = -4,
+ [0][1][2][0][RTW89_QATAR][1][38] = 54,
+ [0][1][2][0][RTW89_QATAR][0][38] = 18,
+ [0][1][2][0][RTW89_UK][1][38] = 54,
+ [0][1][2][0][RTW89_UK][0][38] = 18,
+ [0][1][2][0][RTW89_FCC][1][40] = -4,
+ [0][1][2][0][RTW89_FCC][2][40] = 68,
+ [0][1][2][0][RTW89_ETSI][1][40] = 54,
+ [0][1][2][0][RTW89_ETSI][0][40] = 18,
+ [0][1][2][0][RTW89_MKK][1][40] = 54,
+ [0][1][2][0][RTW89_MKK][0][40] = 16,
+ [0][1][2][0][RTW89_IC][1][40] = -4,
+ [0][1][2][0][RTW89_KCC][1][40] = 12,
+ [0][1][2][0][RTW89_KCC][0][40] = 14,
+ [0][1][2][0][RTW89_ACMA][1][40] = 54,
+ [0][1][2][0][RTW89_ACMA][0][40] = 18,
+ [0][1][2][0][RTW89_CHILE][1][40] = -4,
+ [0][1][2][0][RTW89_QATAR][1][40] = 54,
+ [0][1][2][0][RTW89_QATAR][0][40] = 18,
+ [0][1][2][0][RTW89_UK][1][40] = 54,
+ [0][1][2][0][RTW89_UK][0][40] = 18,
+ [0][1][2][0][RTW89_FCC][1][42] = -4,
+ [0][1][2][0][RTW89_FCC][2][42] = 68,
+ [0][1][2][0][RTW89_ETSI][1][42] = 54,
+ [0][1][2][0][RTW89_ETSI][0][42] = 18,
+ [0][1][2][0][RTW89_MKK][1][42] = 54,
+ [0][1][2][0][RTW89_MKK][0][42] = 16,
+ [0][1][2][0][RTW89_IC][1][42] = -4,
+ [0][1][2][0][RTW89_KCC][1][42] = 12,
+ [0][1][2][0][RTW89_KCC][0][42] = 14,
+ [0][1][2][0][RTW89_ACMA][1][42] = 54,
+ [0][1][2][0][RTW89_ACMA][0][42] = 18,
+ [0][1][2][0][RTW89_CHILE][1][42] = -4,
+ [0][1][2][0][RTW89_QATAR][1][42] = 54,
+ [0][1][2][0][RTW89_QATAR][0][42] = 18,
+ [0][1][2][0][RTW89_UK][1][42] = 54,
+ [0][1][2][0][RTW89_UK][0][42] = 18,
+ [0][1][2][0][RTW89_FCC][1][44] = -2,
+ [0][1][2][0][RTW89_FCC][2][44] = 68,
+ [0][1][2][0][RTW89_ETSI][1][44] = 54,
+ [0][1][2][0][RTW89_ETSI][0][44] = 18,
+ [0][1][2][0][RTW89_MKK][1][44] = 34,
+ [0][1][2][0][RTW89_MKK][0][44] = 16,
+ [0][1][2][0][RTW89_IC][1][44] = -2,
+ [0][1][2][0][RTW89_KCC][1][44] = 12,
+ [0][1][2][0][RTW89_KCC][0][44] = 12,
+ [0][1][2][0][RTW89_ACMA][1][44] = 54,
+ [0][1][2][0][RTW89_ACMA][0][44] = 18,
+ [0][1][2][0][RTW89_CHILE][1][44] = -2,
+ [0][1][2][0][RTW89_QATAR][1][44] = 54,
+ [0][1][2][0][RTW89_QATAR][0][44] = 18,
+ [0][1][2][0][RTW89_UK][1][44] = 54,
+ [0][1][2][0][RTW89_UK][0][44] = 18,
+ [0][1][2][0][RTW89_FCC][1][45] = -2,
+ [0][1][2][0][RTW89_FCC][2][45] = 127,
+ [0][1][2][0][RTW89_ETSI][1][45] = 127,
+ [0][1][2][0][RTW89_ETSI][0][45] = 127,
+ [0][1][2][0][RTW89_MKK][1][45] = 127,
+ [0][1][2][0][RTW89_MKK][0][45] = 127,
+ [0][1][2][0][RTW89_IC][1][45] = -2,
+ [0][1][2][0][RTW89_KCC][1][45] = 12,
+ [0][1][2][0][RTW89_KCC][0][45] = 127,
+ [0][1][2][0][RTW89_ACMA][1][45] = 127,
+ [0][1][2][0][RTW89_ACMA][0][45] = 127,
+ [0][1][2][0][RTW89_CHILE][1][45] = -2,
+ [0][1][2][0][RTW89_QATAR][1][45] = 127,
+ [0][1][2][0][RTW89_QATAR][0][45] = 127,
+ [0][1][2][0][RTW89_UK][1][45] = 127,
+ [0][1][2][0][RTW89_UK][0][45] = 127,
+ [0][1][2][0][RTW89_FCC][1][47] = -2,
+ [0][1][2][0][RTW89_FCC][2][47] = 127,
+ [0][1][2][0][RTW89_ETSI][1][47] = 127,
+ [0][1][2][0][RTW89_ETSI][0][47] = 127,
+ [0][1][2][0][RTW89_MKK][1][47] = 127,
+ [0][1][2][0][RTW89_MKK][0][47] = 127,
+ [0][1][2][0][RTW89_IC][1][47] = -2,
+ [0][1][2][0][RTW89_KCC][1][47] = 12,
+ [0][1][2][0][RTW89_KCC][0][47] = 127,
+ [0][1][2][0][RTW89_ACMA][1][47] = 127,
+ [0][1][2][0][RTW89_ACMA][0][47] = 127,
+ [0][1][2][0][RTW89_CHILE][1][47] = -2,
+ [0][1][2][0][RTW89_QATAR][1][47] = 127,
+ [0][1][2][0][RTW89_QATAR][0][47] = 127,
+ [0][1][2][0][RTW89_UK][1][47] = 127,
+ [0][1][2][0][RTW89_UK][0][47] = 127,
+ [0][1][2][0][RTW89_FCC][1][49] = -2,
+ [0][1][2][0][RTW89_FCC][2][49] = 127,
+ [0][1][2][0][RTW89_ETSI][1][49] = 127,
+ [0][1][2][0][RTW89_ETSI][0][49] = 127,
+ [0][1][2][0][RTW89_MKK][1][49] = 127,
+ [0][1][2][0][RTW89_MKK][0][49] = 127,
+ [0][1][2][0][RTW89_IC][1][49] = -2,
+ [0][1][2][0][RTW89_KCC][1][49] = 12,
+ [0][1][2][0][RTW89_KCC][0][49] = 127,
+ [0][1][2][0][RTW89_ACMA][1][49] = 127,
+ [0][1][2][0][RTW89_ACMA][0][49] = 127,
+ [0][1][2][0][RTW89_CHILE][1][49] = -2,
+ [0][1][2][0][RTW89_QATAR][1][49] = 127,
+ [0][1][2][0][RTW89_QATAR][0][49] = 127,
+ [0][1][2][0][RTW89_UK][1][49] = 127,
+ [0][1][2][0][RTW89_UK][0][49] = 127,
+ [0][1][2][0][RTW89_FCC][1][51] = -2,
+ [0][1][2][0][RTW89_FCC][2][51] = 127,
+ [0][1][2][0][RTW89_ETSI][1][51] = 127,
+ [0][1][2][0][RTW89_ETSI][0][51] = 127,
+ [0][1][2][0][RTW89_MKK][1][51] = 127,
+ [0][1][2][0][RTW89_MKK][0][51] = 127,
+ [0][1][2][0][RTW89_IC][1][51] = -2,
+ [0][1][2][0][RTW89_KCC][1][51] = 12,
+ [0][1][2][0][RTW89_KCC][0][51] = 127,
+ [0][1][2][0][RTW89_ACMA][1][51] = 127,
+ [0][1][2][0][RTW89_ACMA][0][51] = 127,
+ [0][1][2][0][RTW89_CHILE][1][51] = -2,
+ [0][1][2][0][RTW89_QATAR][1][51] = 127,
+ [0][1][2][0][RTW89_QATAR][0][51] = 127,
+ [0][1][2][0][RTW89_UK][1][51] = 127,
+ [0][1][2][0][RTW89_UK][0][51] = 127,
+ [0][1][2][0][RTW89_FCC][1][53] = -2,
+ [0][1][2][0][RTW89_FCC][2][53] = 127,
+ [0][1][2][0][RTW89_ETSI][1][53] = 127,
+ [0][1][2][0][RTW89_ETSI][0][53] = 127,
+ [0][1][2][0][RTW89_MKK][1][53] = 127,
+ [0][1][2][0][RTW89_MKK][0][53] = 127,
+ [0][1][2][0][RTW89_IC][1][53] = -2,
+ [0][1][2][0][RTW89_KCC][1][53] = 12,
+ [0][1][2][0][RTW89_KCC][0][53] = 127,
+ [0][1][2][0][RTW89_ACMA][1][53] = 127,
+ [0][1][2][0][RTW89_ACMA][0][53] = 127,
+ [0][1][2][0][RTW89_CHILE][1][53] = -2,
+ [0][1][2][0][RTW89_QATAR][1][53] = 127,
+ [0][1][2][0][RTW89_QATAR][0][53] = 127,
+ [0][1][2][0][RTW89_UK][1][53] = 127,
+ [0][1][2][0][RTW89_UK][0][53] = 127,
+ [0][1][2][0][RTW89_FCC][1][55] = -2,
+ [0][1][2][0][RTW89_FCC][2][55] = 68,
+ [0][1][2][0][RTW89_ETSI][1][55] = 127,
+ [0][1][2][0][RTW89_ETSI][0][55] = 127,
+ [0][1][2][0][RTW89_MKK][1][55] = 127,
+ [0][1][2][0][RTW89_MKK][0][55] = 127,
+ [0][1][2][0][RTW89_IC][1][55] = -2,
+ [0][1][2][0][RTW89_KCC][1][55] = 12,
+ [0][1][2][0][RTW89_KCC][0][55] = 127,
+ [0][1][2][0][RTW89_ACMA][1][55] = 127,
+ [0][1][2][0][RTW89_ACMA][0][55] = 127,
+ [0][1][2][0][RTW89_CHILE][1][55] = -2,
+ [0][1][2][0][RTW89_QATAR][1][55] = 127,
+ [0][1][2][0][RTW89_QATAR][0][55] = 127,
+ [0][1][2][0][RTW89_UK][1][55] = 127,
+ [0][1][2][0][RTW89_UK][0][55] = 127,
+ [0][1][2][0][RTW89_FCC][1][57] = -2,
+ [0][1][2][0][RTW89_FCC][2][57] = 68,
+ [0][1][2][0][RTW89_ETSI][1][57] = 127,
+ [0][1][2][0][RTW89_ETSI][0][57] = 127,
+ [0][1][2][0][RTW89_MKK][1][57] = 127,
+ [0][1][2][0][RTW89_MKK][0][57] = 127,
+ [0][1][2][0][RTW89_IC][1][57] = -2,
+ [0][1][2][0][RTW89_KCC][1][57] = 12,
+ [0][1][2][0][RTW89_KCC][0][57] = 127,
+ [0][1][2][0][RTW89_ACMA][1][57] = 127,
+ [0][1][2][0][RTW89_ACMA][0][57] = 127,
+ [0][1][2][0][RTW89_CHILE][1][57] = -2,
+ [0][1][2][0][RTW89_QATAR][1][57] = 127,
+ [0][1][2][0][RTW89_QATAR][0][57] = 127,
+ [0][1][2][0][RTW89_UK][1][57] = 127,
+ [0][1][2][0][RTW89_UK][0][57] = 127,
+ [0][1][2][0][RTW89_FCC][1][59] = -2,
+ [0][1][2][0][RTW89_FCC][2][59] = 68,
+ [0][1][2][0][RTW89_ETSI][1][59] = 127,
+ [0][1][2][0][RTW89_ETSI][0][59] = 127,
+ [0][1][2][0][RTW89_MKK][1][59] = 127,
+ [0][1][2][0][RTW89_MKK][0][59] = 127,
+ [0][1][2][0][RTW89_IC][1][59] = -2,
+ [0][1][2][0][RTW89_KCC][1][59] = 12,
+ [0][1][2][0][RTW89_KCC][0][59] = 127,
+ [0][1][2][0][RTW89_ACMA][1][59] = 127,
+ [0][1][2][0][RTW89_ACMA][0][59] = 127,
+ [0][1][2][0][RTW89_CHILE][1][59] = -2,
+ [0][1][2][0][RTW89_QATAR][1][59] = 127,
+ [0][1][2][0][RTW89_QATAR][0][59] = 127,
+ [0][1][2][0][RTW89_UK][1][59] = 127,
+ [0][1][2][0][RTW89_UK][0][59] = 127,
+ [0][1][2][0][RTW89_FCC][1][60] = -2,
+ [0][1][2][0][RTW89_FCC][2][60] = 68,
+ [0][1][2][0][RTW89_ETSI][1][60] = 127,
+ [0][1][2][0][RTW89_ETSI][0][60] = 127,
+ [0][1][2][0][RTW89_MKK][1][60] = 127,
+ [0][1][2][0][RTW89_MKK][0][60] = 127,
+ [0][1][2][0][RTW89_IC][1][60] = -2,
+ [0][1][2][0][RTW89_KCC][1][60] = 12,
+ [0][1][2][0][RTW89_KCC][0][60] = 127,
+ [0][1][2][0][RTW89_ACMA][1][60] = 127,
+ [0][1][2][0][RTW89_ACMA][0][60] = 127,
+ [0][1][2][0][RTW89_CHILE][1][60] = -2,
+ [0][1][2][0][RTW89_QATAR][1][60] = 127,
+ [0][1][2][0][RTW89_QATAR][0][60] = 127,
+ [0][1][2][0][RTW89_UK][1][60] = 127,
+ [0][1][2][0][RTW89_UK][0][60] = 127,
+ [0][1][2][0][RTW89_FCC][1][62] = -2,
+ [0][1][2][0][RTW89_FCC][2][62] = 68,
+ [0][1][2][0][RTW89_ETSI][1][62] = 127,
+ [0][1][2][0][RTW89_ETSI][0][62] = 127,
+ [0][1][2][0][RTW89_MKK][1][62] = 127,
+ [0][1][2][0][RTW89_MKK][0][62] = 127,
+ [0][1][2][0][RTW89_IC][1][62] = -2,
+ [0][1][2][0][RTW89_KCC][1][62] = 12,
+ [0][1][2][0][RTW89_KCC][0][62] = 127,
+ [0][1][2][0][RTW89_ACMA][1][62] = 127,
+ [0][1][2][0][RTW89_ACMA][0][62] = 127,
+ [0][1][2][0][RTW89_CHILE][1][62] = -2,
+ [0][1][2][0][RTW89_QATAR][1][62] = 127,
+ [0][1][2][0][RTW89_QATAR][0][62] = 127,
+ [0][1][2][0][RTW89_UK][1][62] = 127,
+ [0][1][2][0][RTW89_UK][0][62] = 127,
+ [0][1][2][0][RTW89_FCC][1][64] = -2,
+ [0][1][2][0][RTW89_FCC][2][64] = 68,
+ [0][1][2][0][RTW89_ETSI][1][64] = 127,
+ [0][1][2][0][RTW89_ETSI][0][64] = 127,
+ [0][1][2][0][RTW89_MKK][1][64] = 127,
+ [0][1][2][0][RTW89_MKK][0][64] = 127,
+ [0][1][2][0][RTW89_IC][1][64] = -2,
+ [0][1][2][0][RTW89_KCC][1][64] = 12,
+ [0][1][2][0][RTW89_KCC][0][64] = 127,
+ [0][1][2][0][RTW89_ACMA][1][64] = 127,
+ [0][1][2][0][RTW89_ACMA][0][64] = 127,
+ [0][1][2][0][RTW89_CHILE][1][64] = -2,
+ [0][1][2][0][RTW89_QATAR][1][64] = 127,
+ [0][1][2][0][RTW89_QATAR][0][64] = 127,
+ [0][1][2][0][RTW89_UK][1][64] = 127,
+ [0][1][2][0][RTW89_UK][0][64] = 127,
+ [0][1][2][0][RTW89_FCC][1][66] = -2,
+ [0][1][2][0][RTW89_FCC][2][66] = 68,
+ [0][1][2][0][RTW89_ETSI][1][66] = 127,
+ [0][1][2][0][RTW89_ETSI][0][66] = 127,
+ [0][1][2][0][RTW89_MKK][1][66] = 127,
+ [0][1][2][0][RTW89_MKK][0][66] = 127,
+ [0][1][2][0][RTW89_IC][1][66] = -2,
+ [0][1][2][0][RTW89_KCC][1][66] = 12,
+ [0][1][2][0][RTW89_KCC][0][66] = 127,
+ [0][1][2][0][RTW89_ACMA][1][66] = 127,
+ [0][1][2][0][RTW89_ACMA][0][66] = 127,
+ [0][1][2][0][RTW89_CHILE][1][66] = -2,
+ [0][1][2][0][RTW89_QATAR][1][66] = 127,
+ [0][1][2][0][RTW89_QATAR][0][66] = 127,
+ [0][1][2][0][RTW89_UK][1][66] = 127,
+ [0][1][2][0][RTW89_UK][0][66] = 127,
+ [0][1][2][0][RTW89_FCC][1][68] = -2,
+ [0][1][2][0][RTW89_FCC][2][68] = 68,
+ [0][1][2][0][RTW89_ETSI][1][68] = 127,
+ [0][1][2][0][RTW89_ETSI][0][68] = 127,
+ [0][1][2][0][RTW89_MKK][1][68] = 127,
+ [0][1][2][0][RTW89_MKK][0][68] = 127,
+ [0][1][2][0][RTW89_IC][1][68] = -2,
+ [0][1][2][0][RTW89_KCC][1][68] = 12,
+ [0][1][2][0][RTW89_KCC][0][68] = 127,
+ [0][1][2][0][RTW89_ACMA][1][68] = 127,
+ [0][1][2][0][RTW89_ACMA][0][68] = 127,
+ [0][1][2][0][RTW89_CHILE][1][68] = -2,
+ [0][1][2][0][RTW89_QATAR][1][68] = 127,
+ [0][1][2][0][RTW89_QATAR][0][68] = 127,
+ [0][1][2][0][RTW89_UK][1][68] = 127,
+ [0][1][2][0][RTW89_UK][0][68] = 127,
+ [0][1][2][0][RTW89_FCC][1][70] = -2,
+ [0][1][2][0][RTW89_FCC][2][70] = 68,
+ [0][1][2][0][RTW89_ETSI][1][70] = 127,
+ [0][1][2][0][RTW89_ETSI][0][70] = 127,
+ [0][1][2][0][RTW89_MKK][1][70] = 127,
+ [0][1][2][0][RTW89_MKK][0][70] = 127,
+ [0][1][2][0][RTW89_IC][1][70] = -2,
+ [0][1][2][0][RTW89_KCC][1][70] = 12,
+ [0][1][2][0][RTW89_KCC][0][70] = 127,
+ [0][1][2][0][RTW89_ACMA][1][70] = 127,
+ [0][1][2][0][RTW89_ACMA][0][70] = 127,
+ [0][1][2][0][RTW89_CHILE][1][70] = -2,
+ [0][1][2][0][RTW89_QATAR][1][70] = 127,
+ [0][1][2][0][RTW89_QATAR][0][70] = 127,
+ [0][1][2][0][RTW89_UK][1][70] = 127,
+ [0][1][2][0][RTW89_UK][0][70] = 127,
+ [0][1][2][0][RTW89_FCC][1][72] = -2,
+ [0][1][2][0][RTW89_FCC][2][72] = 68,
+ [0][1][2][0][RTW89_ETSI][1][72] = 127,
+ [0][1][2][0][RTW89_ETSI][0][72] = 127,
+ [0][1][2][0][RTW89_MKK][1][72] = 127,
+ [0][1][2][0][RTW89_MKK][0][72] = 127,
+ [0][1][2][0][RTW89_IC][1][72] = -2,
+ [0][1][2][0][RTW89_KCC][1][72] = 12,
+ [0][1][2][0][RTW89_KCC][0][72] = 127,
+ [0][1][2][0][RTW89_ACMA][1][72] = 127,
+ [0][1][2][0][RTW89_ACMA][0][72] = 127,
+ [0][1][2][0][RTW89_CHILE][1][72] = -2,
+ [0][1][2][0][RTW89_QATAR][1][72] = 127,
+ [0][1][2][0][RTW89_QATAR][0][72] = 127,
+ [0][1][2][0][RTW89_UK][1][72] = 127,
+ [0][1][2][0][RTW89_UK][0][72] = 127,
+ [0][1][2][0][RTW89_FCC][1][74] = -2,
+ [0][1][2][0][RTW89_FCC][2][74] = 68,
+ [0][1][2][0][RTW89_ETSI][1][74] = 127,
+ [0][1][2][0][RTW89_ETSI][0][74] = 127,
+ [0][1][2][0][RTW89_MKK][1][74] = 127,
+ [0][1][2][0][RTW89_MKK][0][74] = 127,
+ [0][1][2][0][RTW89_IC][1][74] = -2,
+ [0][1][2][0][RTW89_KCC][1][74] = 12,
+ [0][1][2][0][RTW89_KCC][0][74] = 127,
+ [0][1][2][0][RTW89_ACMA][1][74] = 127,
+ [0][1][2][0][RTW89_ACMA][0][74] = 127,
+ [0][1][2][0][RTW89_CHILE][1][74] = -2,
+ [0][1][2][0][RTW89_QATAR][1][74] = 127,
+ [0][1][2][0][RTW89_QATAR][0][74] = 127,
+ [0][1][2][0][RTW89_UK][1][74] = 127,
+ [0][1][2][0][RTW89_UK][0][74] = 127,
+ [0][1][2][0][RTW89_FCC][1][75] = -2,
+ [0][1][2][0][RTW89_FCC][2][75] = 68,
+ [0][1][2][0][RTW89_ETSI][1][75] = 127,
+ [0][1][2][0][RTW89_ETSI][0][75] = 127,
+ [0][1][2][0][RTW89_MKK][1][75] = 127,
+ [0][1][2][0][RTW89_MKK][0][75] = 127,
+ [0][1][2][0][RTW89_IC][1][75] = -2,
+ [0][1][2][0][RTW89_KCC][1][75] = 12,
+ [0][1][2][0][RTW89_KCC][0][75] = 127,
+ [0][1][2][0][RTW89_ACMA][1][75] = 127,
+ [0][1][2][0][RTW89_ACMA][0][75] = 127,
+ [0][1][2][0][RTW89_CHILE][1][75] = -2,
+ [0][1][2][0][RTW89_QATAR][1][75] = 127,
+ [0][1][2][0][RTW89_QATAR][0][75] = 127,
+ [0][1][2][0][RTW89_UK][1][75] = 127,
+ [0][1][2][0][RTW89_UK][0][75] = 127,
+ [0][1][2][0][RTW89_FCC][1][77] = -2,
+ [0][1][2][0][RTW89_FCC][2][77] = 68,
+ [0][1][2][0][RTW89_ETSI][1][77] = 127,
+ [0][1][2][0][RTW89_ETSI][0][77] = 127,
+ [0][1][2][0][RTW89_MKK][1][77] = 127,
+ [0][1][2][0][RTW89_MKK][0][77] = 127,
+ [0][1][2][0][RTW89_IC][1][77] = -2,
+ [0][1][2][0][RTW89_KCC][1][77] = 12,
+ [0][1][2][0][RTW89_KCC][0][77] = 127,
+ [0][1][2][0][RTW89_ACMA][1][77] = 127,
+ [0][1][2][0][RTW89_ACMA][0][77] = 127,
+ [0][1][2][0][RTW89_CHILE][1][77] = -2,
+ [0][1][2][0][RTW89_QATAR][1][77] = 127,
+ [0][1][2][0][RTW89_QATAR][0][77] = 127,
+ [0][1][2][0][RTW89_UK][1][77] = 127,
+ [0][1][2][0][RTW89_UK][0][77] = 127,
+ [0][1][2][0][RTW89_FCC][1][79] = -2,
+ [0][1][2][0][RTW89_FCC][2][79] = 68,
+ [0][1][2][0][RTW89_ETSI][1][79] = 127,
+ [0][1][2][0][RTW89_ETSI][0][79] = 127,
+ [0][1][2][0][RTW89_MKK][1][79] = 127,
+ [0][1][2][0][RTW89_MKK][0][79] = 127,
+ [0][1][2][0][RTW89_IC][1][79] = -2,
+ [0][1][2][0][RTW89_KCC][1][79] = 12,
+ [0][1][2][0][RTW89_KCC][0][79] = 127,
+ [0][1][2][0][RTW89_ACMA][1][79] = 127,
+ [0][1][2][0][RTW89_ACMA][0][79] = 127,
+ [0][1][2][0][RTW89_CHILE][1][79] = -2,
+ [0][1][2][0][RTW89_QATAR][1][79] = 127,
+ [0][1][2][0][RTW89_QATAR][0][79] = 127,
+ [0][1][2][0][RTW89_UK][1][79] = 127,
+ [0][1][2][0][RTW89_UK][0][79] = 127,
+ [0][1][2][0][RTW89_FCC][1][81] = -2,
+ [0][1][2][0][RTW89_FCC][2][81] = 68,
+ [0][1][2][0][RTW89_ETSI][1][81] = 127,
+ [0][1][2][0][RTW89_ETSI][0][81] = 127,
+ [0][1][2][0][RTW89_MKK][1][81] = 127,
+ [0][1][2][0][RTW89_MKK][0][81] = 127,
+ [0][1][2][0][RTW89_IC][1][81] = -2,
+ [0][1][2][0][RTW89_KCC][1][81] = 12,
+ [0][1][2][0][RTW89_KCC][0][81] = 127,
+ [0][1][2][0][RTW89_ACMA][1][81] = 127,
+ [0][1][2][0][RTW89_ACMA][0][81] = 127,
+ [0][1][2][0][RTW89_CHILE][1][81] = -2,
+ [0][1][2][0][RTW89_QATAR][1][81] = 127,
+ [0][1][2][0][RTW89_QATAR][0][81] = 127,
+ [0][1][2][0][RTW89_UK][1][81] = 127,
+ [0][1][2][0][RTW89_UK][0][81] = 127,
+ [0][1][2][0][RTW89_FCC][1][83] = -2,
+ [0][1][2][0][RTW89_FCC][2][83] = 68,
+ [0][1][2][0][RTW89_ETSI][1][83] = 127,
+ [0][1][2][0][RTW89_ETSI][0][83] = 127,
+ [0][1][2][0][RTW89_MKK][1][83] = 127,
+ [0][1][2][0][RTW89_MKK][0][83] = 127,
+ [0][1][2][0][RTW89_IC][1][83] = -2,
+ [0][1][2][0][RTW89_KCC][1][83] = 20,
+ [0][1][2][0][RTW89_KCC][0][83] = 127,
+ [0][1][2][0][RTW89_ACMA][1][83] = 127,
+ [0][1][2][0][RTW89_ACMA][0][83] = 127,
+ [0][1][2][0][RTW89_CHILE][1][83] = -2,
+ [0][1][2][0][RTW89_QATAR][1][83] = 127,
+ [0][1][2][0][RTW89_QATAR][0][83] = 127,
+ [0][1][2][0][RTW89_UK][1][83] = 127,
+ [0][1][2][0][RTW89_UK][0][83] = 127,
+ [0][1][2][0][RTW89_FCC][1][85] = -2,
+ [0][1][2][0][RTW89_FCC][2][85] = 68,
+ [0][1][2][0][RTW89_ETSI][1][85] = 127,
+ [0][1][2][0][RTW89_ETSI][0][85] = 127,
+ [0][1][2][0][RTW89_MKK][1][85] = 127,
+ [0][1][2][0][RTW89_MKK][0][85] = 127,
+ [0][1][2][0][RTW89_IC][1][85] = -2,
+ [0][1][2][0][RTW89_KCC][1][85] = 20,
+ [0][1][2][0][RTW89_KCC][0][85] = 127,
+ [0][1][2][0][RTW89_ACMA][1][85] = 127,
+ [0][1][2][0][RTW89_ACMA][0][85] = 127,
+ [0][1][2][0][RTW89_CHILE][1][85] = -2,
+ [0][1][2][0][RTW89_QATAR][1][85] = 127,
+ [0][1][2][0][RTW89_QATAR][0][85] = 127,
+ [0][1][2][0][RTW89_UK][1][85] = 127,
+ [0][1][2][0][RTW89_UK][0][85] = 127,
+ [0][1][2][0][RTW89_FCC][1][87] = -2,
+ [0][1][2][0][RTW89_FCC][2][87] = 127,
+ [0][1][2][0][RTW89_ETSI][1][87] = 127,
+ [0][1][2][0][RTW89_ETSI][0][87] = 127,
+ [0][1][2][0][RTW89_MKK][1][87] = 127,
+ [0][1][2][0][RTW89_MKK][0][87] = 127,
+ [0][1][2][0][RTW89_IC][1][87] = -2,
+ [0][1][2][0][RTW89_KCC][1][87] = 20,
+ [0][1][2][0][RTW89_KCC][0][87] = 127,
+ [0][1][2][0][RTW89_ACMA][1][87] = 127,
+ [0][1][2][0][RTW89_ACMA][0][87] = 127,
+ [0][1][2][0][RTW89_CHILE][1][87] = -2,
+ [0][1][2][0][RTW89_QATAR][1][87] = 127,
+ [0][1][2][0][RTW89_QATAR][0][87] = 127,
+ [0][1][2][0][RTW89_UK][1][87] = 127,
+ [0][1][2][0][RTW89_UK][0][87] = 127,
+ [0][1][2][0][RTW89_FCC][1][89] = -2,
+ [0][1][2][0][RTW89_FCC][2][89] = 127,
+ [0][1][2][0][RTW89_ETSI][1][89] = 127,
+ [0][1][2][0][RTW89_ETSI][0][89] = 127,
+ [0][1][2][0][RTW89_MKK][1][89] = 127,
+ [0][1][2][0][RTW89_MKK][0][89] = 127,
+ [0][1][2][0][RTW89_IC][1][89] = -2,
+ [0][1][2][0][RTW89_KCC][1][89] = 20,
+ [0][1][2][0][RTW89_KCC][0][89] = 127,
+ [0][1][2][0][RTW89_ACMA][1][89] = 127,
+ [0][1][2][0][RTW89_ACMA][0][89] = 127,
+ [0][1][2][0][RTW89_CHILE][1][89] = -2,
+ [0][1][2][0][RTW89_QATAR][1][89] = 127,
+ [0][1][2][0][RTW89_QATAR][0][89] = 127,
+ [0][1][2][0][RTW89_UK][1][89] = 127,
+ [0][1][2][0][RTW89_UK][0][89] = 127,
+ [0][1][2][0][RTW89_FCC][1][90] = -2,
+ [0][1][2][0][RTW89_FCC][2][90] = 127,
+ [0][1][2][0][RTW89_ETSI][1][90] = 127,
+ [0][1][2][0][RTW89_ETSI][0][90] = 127,
+ [0][1][2][0][RTW89_MKK][1][90] = 127,
+ [0][1][2][0][RTW89_MKK][0][90] = 127,
+ [0][1][2][0][RTW89_IC][1][90] = -2,
+ [0][1][2][0][RTW89_KCC][1][90] = 20,
+ [0][1][2][0][RTW89_KCC][0][90] = 127,
+ [0][1][2][0][RTW89_ACMA][1][90] = 127,
+ [0][1][2][0][RTW89_ACMA][0][90] = 127,
+ [0][1][2][0][RTW89_CHILE][1][90] = -2,
+ [0][1][2][0][RTW89_QATAR][1][90] = 127,
+ [0][1][2][0][RTW89_QATAR][0][90] = 127,
+ [0][1][2][0][RTW89_UK][1][90] = 127,
+ [0][1][2][0][RTW89_UK][0][90] = 127,
+ [0][1][2][0][RTW89_FCC][1][92] = -2,
+ [0][1][2][0][RTW89_FCC][2][92] = 127,
+ [0][1][2][0][RTW89_ETSI][1][92] = 127,
+ [0][1][2][0][RTW89_ETSI][0][92] = 127,
+ [0][1][2][0][RTW89_MKK][1][92] = 127,
+ [0][1][2][0][RTW89_MKK][0][92] = 127,
+ [0][1][2][0][RTW89_IC][1][92] = -2,
+ [0][1][2][0][RTW89_KCC][1][92] = 20,
+ [0][1][2][0][RTW89_KCC][0][92] = 127,
+ [0][1][2][0][RTW89_ACMA][1][92] = 127,
+ [0][1][2][0][RTW89_ACMA][0][92] = 127,
+ [0][1][2][0][RTW89_CHILE][1][92] = -2,
+ [0][1][2][0][RTW89_QATAR][1][92] = 127,
+ [0][1][2][0][RTW89_QATAR][0][92] = 127,
+ [0][1][2][0][RTW89_UK][1][92] = 127,
+ [0][1][2][0][RTW89_UK][0][92] = 127,
+ [0][1][2][0][RTW89_FCC][1][94] = -2,
+ [0][1][2][0][RTW89_FCC][2][94] = 127,
+ [0][1][2][0][RTW89_ETSI][1][94] = 127,
+ [0][1][2][0][RTW89_ETSI][0][94] = 127,
+ [0][1][2][0][RTW89_MKK][1][94] = 127,
+ [0][1][2][0][RTW89_MKK][0][94] = 127,
+ [0][1][2][0][RTW89_IC][1][94] = -2,
+ [0][1][2][0][RTW89_KCC][1][94] = 20,
+ [0][1][2][0][RTW89_KCC][0][94] = 127,
+ [0][1][2][0][RTW89_ACMA][1][94] = 127,
+ [0][1][2][0][RTW89_ACMA][0][94] = 127,
+ [0][1][2][0][RTW89_CHILE][1][94] = -2,
+ [0][1][2][0][RTW89_QATAR][1][94] = 127,
+ [0][1][2][0][RTW89_QATAR][0][94] = 127,
+ [0][1][2][0][RTW89_UK][1][94] = 127,
+ [0][1][2][0][RTW89_UK][0][94] = 127,
+ [0][1][2][0][RTW89_FCC][1][96] = -2,
+ [0][1][2][0][RTW89_FCC][2][96] = 127,
+ [0][1][2][0][RTW89_ETSI][1][96] = 127,
+ [0][1][2][0][RTW89_ETSI][0][96] = 127,
+ [0][1][2][0][RTW89_MKK][1][96] = 127,
+ [0][1][2][0][RTW89_MKK][0][96] = 127,
+ [0][1][2][0][RTW89_IC][1][96] = -2,
+ [0][1][2][0][RTW89_KCC][1][96] = 20,
+ [0][1][2][0][RTW89_KCC][0][96] = 127,
+ [0][1][2][0][RTW89_ACMA][1][96] = 127,
+ [0][1][2][0][RTW89_ACMA][0][96] = 127,
+ [0][1][2][0][RTW89_CHILE][1][96] = -2,
+ [0][1][2][0][RTW89_QATAR][1][96] = 127,
+ [0][1][2][0][RTW89_QATAR][0][96] = 127,
+ [0][1][2][0][RTW89_UK][1][96] = 127,
+ [0][1][2][0][RTW89_UK][0][96] = 127,
+ [0][1][2][0][RTW89_FCC][1][98] = -2,
+ [0][1][2][0][RTW89_FCC][2][98] = 127,
+ [0][1][2][0][RTW89_ETSI][1][98] = 127,
+ [0][1][2][0][RTW89_ETSI][0][98] = 127,
+ [0][1][2][0][RTW89_MKK][1][98] = 127,
+ [0][1][2][0][RTW89_MKK][0][98] = 127,
+ [0][1][2][0][RTW89_IC][1][98] = -2,
+ [0][1][2][0][RTW89_KCC][1][98] = 20,
+ [0][1][2][0][RTW89_KCC][0][98] = 127,
+ [0][1][2][0][RTW89_ACMA][1][98] = 127,
+ [0][1][2][0][RTW89_ACMA][0][98] = 127,
+ [0][1][2][0][RTW89_CHILE][1][98] = -2,
+ [0][1][2][0][RTW89_QATAR][1][98] = 127,
+ [0][1][2][0][RTW89_QATAR][0][98] = 127,
+ [0][1][2][0][RTW89_UK][1][98] = 127,
+ [0][1][2][0][RTW89_UK][0][98] = 127,
+ [0][1][2][0][RTW89_FCC][1][100] = -2,
+ [0][1][2][0][RTW89_FCC][2][100] = 127,
+ [0][1][2][0][RTW89_ETSI][1][100] = 127,
+ [0][1][2][0][RTW89_ETSI][0][100] = 127,
+ [0][1][2][0][RTW89_MKK][1][100] = 127,
+ [0][1][2][0][RTW89_MKK][0][100] = 127,
+ [0][1][2][0][RTW89_IC][1][100] = -2,
+ [0][1][2][0][RTW89_KCC][1][100] = 20,
+ [0][1][2][0][RTW89_KCC][0][100] = 127,
+ [0][1][2][0][RTW89_ACMA][1][100] = 127,
+ [0][1][2][0][RTW89_ACMA][0][100] = 127,
+ [0][1][2][0][RTW89_CHILE][1][100] = -2,
+ [0][1][2][0][RTW89_QATAR][1][100] = 127,
+ [0][1][2][0][RTW89_QATAR][0][100] = 127,
+ [0][1][2][0][RTW89_UK][1][100] = 127,
+ [0][1][2][0][RTW89_UK][0][100] = 127,
+ [0][1][2][0][RTW89_FCC][1][102] = -2,
+ [0][1][2][0][RTW89_FCC][2][102] = 127,
+ [0][1][2][0][RTW89_ETSI][1][102] = 127,
+ [0][1][2][0][RTW89_ETSI][0][102] = 127,
+ [0][1][2][0][RTW89_MKK][1][102] = 127,
+ [0][1][2][0][RTW89_MKK][0][102] = 127,
+ [0][1][2][0][RTW89_IC][1][102] = -2,
+ [0][1][2][0][RTW89_KCC][1][102] = 20,
+ [0][1][2][0][RTW89_KCC][0][102] = 127,
+ [0][1][2][0][RTW89_ACMA][1][102] = 127,
+ [0][1][2][0][RTW89_ACMA][0][102] = 127,
+ [0][1][2][0][RTW89_CHILE][1][102] = -2,
+ [0][1][2][0][RTW89_QATAR][1][102] = 127,
+ [0][1][2][0][RTW89_QATAR][0][102] = 127,
+ [0][1][2][0][RTW89_UK][1][102] = 127,
+ [0][1][2][0][RTW89_UK][0][102] = 127,
+ [0][1][2][0][RTW89_FCC][1][104] = -2,
+ [0][1][2][0][RTW89_FCC][2][104] = 127,
+ [0][1][2][0][RTW89_ETSI][1][104] = 127,
+ [0][1][2][0][RTW89_ETSI][0][104] = 127,
+ [0][1][2][0][RTW89_MKK][1][104] = 127,
+ [0][1][2][0][RTW89_MKK][0][104] = 127,
+ [0][1][2][0][RTW89_IC][1][104] = -2,
+ [0][1][2][0][RTW89_KCC][1][104] = 20,
+ [0][1][2][0][RTW89_KCC][0][104] = 127,
+ [0][1][2][0][RTW89_ACMA][1][104] = 127,
+ [0][1][2][0][RTW89_ACMA][0][104] = 127,
+ [0][1][2][0][RTW89_CHILE][1][104] = -2,
+ [0][1][2][0][RTW89_QATAR][1][104] = 127,
+ [0][1][2][0][RTW89_QATAR][0][104] = 127,
+ [0][1][2][0][RTW89_UK][1][104] = 127,
+ [0][1][2][0][RTW89_UK][0][104] = 127,
+ [0][1][2][0][RTW89_FCC][1][105] = -2,
+ [0][1][2][0][RTW89_FCC][2][105] = 127,
+ [0][1][2][0][RTW89_ETSI][1][105] = 127,
+ [0][1][2][0][RTW89_ETSI][0][105] = 127,
+ [0][1][2][0][RTW89_MKK][1][105] = 127,
+ [0][1][2][0][RTW89_MKK][0][105] = 127,
+ [0][1][2][0][RTW89_IC][1][105] = -2,
+ [0][1][2][0][RTW89_KCC][1][105] = 20,
+ [0][1][2][0][RTW89_KCC][0][105] = 127,
+ [0][1][2][0][RTW89_ACMA][1][105] = 127,
+ [0][1][2][0][RTW89_ACMA][0][105] = 127,
+ [0][1][2][0][RTW89_CHILE][1][105] = -2,
+ [0][1][2][0][RTW89_QATAR][1][105] = 127,
+ [0][1][2][0][RTW89_QATAR][0][105] = 127,
+ [0][1][2][0][RTW89_UK][1][105] = 127,
+ [0][1][2][0][RTW89_UK][0][105] = 127,
+ [0][1][2][0][RTW89_FCC][1][107] = 1,
+ [0][1][2][0][RTW89_FCC][2][107] = 127,
+ [0][1][2][0][RTW89_ETSI][1][107] = 127,
+ [0][1][2][0][RTW89_ETSI][0][107] = 127,
+ [0][1][2][0][RTW89_MKK][1][107] = 127,
+ [0][1][2][0][RTW89_MKK][0][107] = 127,
+ [0][1][2][0][RTW89_IC][1][107] = 1,
+ [0][1][2][0][RTW89_KCC][1][107] = 20,
+ [0][1][2][0][RTW89_KCC][0][107] = 127,
+ [0][1][2][0][RTW89_ACMA][1][107] = 127,
+ [0][1][2][0][RTW89_ACMA][0][107] = 127,
+ [0][1][2][0][RTW89_CHILE][1][107] = 1,
+ [0][1][2][0][RTW89_QATAR][1][107] = 127,
+ [0][1][2][0][RTW89_QATAR][0][107] = 127,
+ [0][1][2][0][RTW89_UK][1][107] = 127,
+ [0][1][2][0][RTW89_UK][0][107] = 127,
+ [0][1][2][0][RTW89_FCC][1][109] = 1,
+ [0][1][2][0][RTW89_FCC][2][109] = 127,
+ [0][1][2][0][RTW89_ETSI][1][109] = 127,
+ [0][1][2][0][RTW89_ETSI][0][109] = 127,
+ [0][1][2][0][RTW89_MKK][1][109] = 127,
+ [0][1][2][0][RTW89_MKK][0][109] = 127,
+ [0][1][2][0][RTW89_IC][1][109] = 1,
+ [0][1][2][0][RTW89_KCC][1][109] = 20,
+ [0][1][2][0][RTW89_KCC][0][109] = 127,
+ [0][1][2][0][RTW89_ACMA][1][109] = 127,
+ [0][1][2][0][RTW89_ACMA][0][109] = 127,
+ [0][1][2][0][RTW89_CHILE][1][109] = 1,
+ [0][1][2][0][RTW89_QATAR][1][109] = 127,
+ [0][1][2][0][RTW89_QATAR][0][109] = 127,
+ [0][1][2][0][RTW89_UK][1][109] = 127,
+ [0][1][2][0][RTW89_UK][0][109] = 127,
+ [0][1][2][0][RTW89_FCC][1][111] = 127,
+ [0][1][2][0][RTW89_FCC][2][111] = 127,
+ [0][1][2][0][RTW89_ETSI][1][111] = 127,
+ [0][1][2][0][RTW89_ETSI][0][111] = 127,
+ [0][1][2][0][RTW89_MKK][1][111] = 127,
+ [0][1][2][0][RTW89_MKK][0][111] = 127,
+ [0][1][2][0][RTW89_IC][1][111] = 127,
+ [0][1][2][0][RTW89_KCC][1][111] = 127,
+ [0][1][2][0][RTW89_KCC][0][111] = 127,
+ [0][1][2][0][RTW89_ACMA][1][111] = 127,
+ [0][1][2][0][RTW89_ACMA][0][111] = 127,
+ [0][1][2][0][RTW89_CHILE][1][111] = 127,
+ [0][1][2][0][RTW89_QATAR][1][111] = 127,
+ [0][1][2][0][RTW89_QATAR][0][111] = 127,
+ [0][1][2][0][RTW89_UK][1][111] = 127,
+ [0][1][2][0][RTW89_UK][0][111] = 127,
+ [0][1][2][0][RTW89_FCC][1][113] = 127,
+ [0][1][2][0][RTW89_FCC][2][113] = 127,
+ [0][1][2][0][RTW89_ETSI][1][113] = 127,
+ [0][1][2][0][RTW89_ETSI][0][113] = 127,
+ [0][1][2][0][RTW89_MKK][1][113] = 127,
+ [0][1][2][0][RTW89_MKK][0][113] = 127,
+ [0][1][2][0][RTW89_IC][1][113] = 127,
+ [0][1][2][0][RTW89_KCC][1][113] = 127,
+ [0][1][2][0][RTW89_KCC][0][113] = 127,
+ [0][1][2][0][RTW89_ACMA][1][113] = 127,
+ [0][1][2][0][RTW89_ACMA][0][113] = 127,
+ [0][1][2][0][RTW89_CHILE][1][113] = 127,
+ [0][1][2][0][RTW89_QATAR][1][113] = 127,
+ [0][1][2][0][RTW89_QATAR][0][113] = 127,
+ [0][1][2][0][RTW89_UK][1][113] = 127,
+ [0][1][2][0][RTW89_UK][0][113] = 127,
+ [0][1][2][0][RTW89_FCC][1][115] = 127,
+ [0][1][2][0][RTW89_FCC][2][115] = 127,
+ [0][1][2][0][RTW89_ETSI][1][115] = 127,
+ [0][1][2][0][RTW89_ETSI][0][115] = 127,
+ [0][1][2][0][RTW89_MKK][1][115] = 127,
+ [0][1][2][0][RTW89_MKK][0][115] = 127,
+ [0][1][2][0][RTW89_IC][1][115] = 127,
+ [0][1][2][0][RTW89_KCC][1][115] = 127,
+ [0][1][2][0][RTW89_KCC][0][115] = 127,
+ [0][1][2][0][RTW89_ACMA][1][115] = 127,
+ [0][1][2][0][RTW89_ACMA][0][115] = 127,
+ [0][1][2][0][RTW89_CHILE][1][115] = 127,
+ [0][1][2][0][RTW89_QATAR][1][115] = 127,
+ [0][1][2][0][RTW89_QATAR][0][115] = 127,
+ [0][1][2][0][RTW89_UK][1][115] = 127,
+ [0][1][2][0][RTW89_UK][0][115] = 127,
+ [0][1][2][0][RTW89_FCC][1][117] = 127,
+ [0][1][2][0][RTW89_FCC][2][117] = 127,
+ [0][1][2][0][RTW89_ETSI][1][117] = 127,
+ [0][1][2][0][RTW89_ETSI][0][117] = 127,
+ [0][1][2][0][RTW89_MKK][1][117] = 127,
+ [0][1][2][0][RTW89_MKK][0][117] = 127,
+ [0][1][2][0][RTW89_IC][1][117] = 127,
+ [0][1][2][0][RTW89_KCC][1][117] = 127,
+ [0][1][2][0][RTW89_KCC][0][117] = 127,
+ [0][1][2][0][RTW89_ACMA][1][117] = 127,
+ [0][1][2][0][RTW89_ACMA][0][117] = 127,
+ [0][1][2][0][RTW89_CHILE][1][117] = 127,
+ [0][1][2][0][RTW89_QATAR][1][117] = 127,
+ [0][1][2][0][RTW89_QATAR][0][117] = 127,
+ [0][1][2][0][RTW89_UK][1][117] = 127,
+ [0][1][2][0][RTW89_UK][0][117] = 127,
+ [0][1][2][0][RTW89_FCC][1][119] = 127,
+ [0][1][2][0][RTW89_FCC][2][119] = 127,
+ [0][1][2][0][RTW89_ETSI][1][119] = 127,
+ [0][1][2][0][RTW89_ETSI][0][119] = 127,
+ [0][1][2][0][RTW89_MKK][1][119] = 127,
+ [0][1][2][0][RTW89_MKK][0][119] = 127,
+ [0][1][2][0][RTW89_IC][1][119] = 127,
+ [0][1][2][0][RTW89_KCC][1][119] = 127,
+ [0][1][2][0][RTW89_KCC][0][119] = 127,
+ [0][1][2][0][RTW89_ACMA][1][119] = 127,
+ [0][1][2][0][RTW89_ACMA][0][119] = 127,
+ [0][1][2][0][RTW89_CHILE][1][119] = 127,
+ [0][1][2][0][RTW89_QATAR][1][119] = 127,
+ [0][1][2][0][RTW89_QATAR][0][119] = 127,
+ [0][1][2][0][RTW89_UK][1][119] = 127,
+ [0][1][2][0][RTW89_UK][0][119] = 127,
+ [0][1][2][1][RTW89_FCC][1][0] = -2,
+ [0][1][2][1][RTW89_FCC][2][0] = 54,
+ [0][1][2][1][RTW89_ETSI][1][0] = 42,
+ [0][1][2][1][RTW89_ETSI][0][0] = 6,
+ [0][1][2][1][RTW89_MKK][1][0] = 56,
+ [0][1][2][1][RTW89_MKK][0][0] = 16,
+ [0][1][2][1][RTW89_IC][1][0] = -2,
+ [0][1][2][1][RTW89_KCC][1][0] = 12,
+ [0][1][2][1][RTW89_KCC][0][0] = 10,
+ [0][1][2][1][RTW89_ACMA][1][0] = 42,
+ [0][1][2][1][RTW89_ACMA][0][0] = 6,
+ [0][1][2][1][RTW89_CHILE][1][0] = -2,
+ [0][1][2][1][RTW89_QATAR][1][0] = 42,
+ [0][1][2][1][RTW89_QATAR][0][0] = 6,
+ [0][1][2][1][RTW89_UK][1][0] = 42,
+ [0][1][2][1][RTW89_UK][0][0] = 6,
+ [0][1][2][1][RTW89_FCC][1][2] = -4,
+ [0][1][2][1][RTW89_FCC][2][2] = 54,
+ [0][1][2][1][RTW89_ETSI][1][2] = 42,
+ [0][1][2][1][RTW89_ETSI][0][2] = 6,
+ [0][1][2][1][RTW89_MKK][1][2] = 54,
+ [0][1][2][1][RTW89_MKK][0][2] = 16,
+ [0][1][2][1][RTW89_IC][1][2] = -4,
+ [0][1][2][1][RTW89_KCC][1][2] = 12,
+ [0][1][2][1][RTW89_KCC][0][2] = 12,
+ [0][1][2][1][RTW89_ACMA][1][2] = 42,
+ [0][1][2][1][RTW89_ACMA][0][2] = 6,
+ [0][1][2][1][RTW89_CHILE][1][2] = -4,
+ [0][1][2][1][RTW89_QATAR][1][2] = 42,
+ [0][1][2][1][RTW89_QATAR][0][2] = 6,
+ [0][1][2][1][RTW89_UK][1][2] = 42,
+ [0][1][2][1][RTW89_UK][0][2] = 6,
+ [0][1][2][1][RTW89_FCC][1][4] = -4,
+ [0][1][2][1][RTW89_FCC][2][4] = 54,
+ [0][1][2][1][RTW89_ETSI][1][4] = 42,
+ [0][1][2][1][RTW89_ETSI][0][4] = 6,
+ [0][1][2][1][RTW89_MKK][1][4] = 54,
+ [0][1][2][1][RTW89_MKK][0][4] = 16,
+ [0][1][2][1][RTW89_IC][1][4] = -4,
+ [0][1][2][1][RTW89_KCC][1][4] = 12,
+ [0][1][2][1][RTW89_KCC][0][4] = 12,
+ [0][1][2][1][RTW89_ACMA][1][4] = 42,
+ [0][1][2][1][RTW89_ACMA][0][4] = 6,
+ [0][1][2][1][RTW89_CHILE][1][4] = -4,
+ [0][1][2][1][RTW89_QATAR][1][4] = 42,
+ [0][1][2][1][RTW89_QATAR][0][4] = 6,
+ [0][1][2][1][RTW89_UK][1][4] = 42,
+ [0][1][2][1][RTW89_UK][0][4] = 6,
+ [0][1][2][1][RTW89_FCC][1][6] = -4,
+ [0][1][2][1][RTW89_FCC][2][6] = 54,
+ [0][1][2][1][RTW89_ETSI][1][6] = 42,
+ [0][1][2][1][RTW89_ETSI][0][6] = 6,
+ [0][1][2][1][RTW89_MKK][1][6] = 54,
+ [0][1][2][1][RTW89_MKK][0][6] = 16,
+ [0][1][2][1][RTW89_IC][1][6] = -4,
+ [0][1][2][1][RTW89_KCC][1][6] = 12,
+ [0][1][2][1][RTW89_KCC][0][6] = 12,
+ [0][1][2][1][RTW89_ACMA][1][6] = 42,
+ [0][1][2][1][RTW89_ACMA][0][6] = 6,
+ [0][1][2][1][RTW89_CHILE][1][6] = -4,
+ [0][1][2][1][RTW89_QATAR][1][6] = 42,
+ [0][1][2][1][RTW89_QATAR][0][6] = 6,
+ [0][1][2][1][RTW89_UK][1][6] = 42,
+ [0][1][2][1][RTW89_UK][0][6] = 6,
+ [0][1][2][1][RTW89_FCC][1][8] = -4,
+ [0][1][2][1][RTW89_FCC][2][8] = 54,
+ [0][1][2][1][RTW89_ETSI][1][8] = 42,
+ [0][1][2][1][RTW89_ETSI][0][8] = 6,
+ [0][1][2][1][RTW89_MKK][1][8] = 54,
+ [0][1][2][1][RTW89_MKK][0][8] = 16,
+ [0][1][2][1][RTW89_IC][1][8] = -4,
+ [0][1][2][1][RTW89_KCC][1][8] = 12,
+ [0][1][2][1][RTW89_KCC][0][8] = 12,
+ [0][1][2][1][RTW89_ACMA][1][8] = 42,
+ [0][1][2][1][RTW89_ACMA][0][8] = 6,
+ [0][1][2][1][RTW89_CHILE][1][8] = -4,
+ [0][1][2][1][RTW89_QATAR][1][8] = 42,
+ [0][1][2][1][RTW89_QATAR][0][8] = 6,
+ [0][1][2][1][RTW89_UK][1][8] = 42,
+ [0][1][2][1][RTW89_UK][0][8] = 6,
+ [0][1][2][1][RTW89_FCC][1][10] = -4,
+ [0][1][2][1][RTW89_FCC][2][10] = 54,
+ [0][1][2][1][RTW89_ETSI][1][10] = 42,
+ [0][1][2][1][RTW89_ETSI][0][10] = 6,
+ [0][1][2][1][RTW89_MKK][1][10] = 54,
+ [0][1][2][1][RTW89_MKK][0][10] = 16,
+ [0][1][2][1][RTW89_IC][1][10] = -4,
+ [0][1][2][1][RTW89_KCC][1][10] = 12,
+ [0][1][2][1][RTW89_KCC][0][10] = 12,
+ [0][1][2][1][RTW89_ACMA][1][10] = 42,
+ [0][1][2][1][RTW89_ACMA][0][10] = 6,
+ [0][1][2][1][RTW89_CHILE][1][10] = -4,
+ [0][1][2][1][RTW89_QATAR][1][10] = 42,
+ [0][1][2][1][RTW89_QATAR][0][10] = 6,
+ [0][1][2][1][RTW89_UK][1][10] = 42,
+ [0][1][2][1][RTW89_UK][0][10] = 6,
+ [0][1][2][1][RTW89_FCC][1][12] = -4,
+ [0][1][2][1][RTW89_FCC][2][12] = 54,
+ [0][1][2][1][RTW89_ETSI][1][12] = 42,
+ [0][1][2][1][RTW89_ETSI][0][12] = 6,
+ [0][1][2][1][RTW89_MKK][1][12] = 54,
+ [0][1][2][1][RTW89_MKK][0][12] = 16,
+ [0][1][2][1][RTW89_IC][1][12] = -4,
+ [0][1][2][1][RTW89_KCC][1][12] = 12,
+ [0][1][2][1][RTW89_KCC][0][12] = 12,
+ [0][1][2][1][RTW89_ACMA][1][12] = 42,
+ [0][1][2][1][RTW89_ACMA][0][12] = 6,
+ [0][1][2][1][RTW89_CHILE][1][12] = -4,
+ [0][1][2][1][RTW89_QATAR][1][12] = 42,
+ [0][1][2][1][RTW89_QATAR][0][12] = 6,
+ [0][1][2][1][RTW89_UK][1][12] = 42,
+ [0][1][2][1][RTW89_UK][0][12] = 6,
+ [0][1][2][1][RTW89_FCC][1][14] = -4,
+ [0][1][2][1][RTW89_FCC][2][14] = 54,
+ [0][1][2][1][RTW89_ETSI][1][14] = 42,
+ [0][1][2][1][RTW89_ETSI][0][14] = 6,
+ [0][1][2][1][RTW89_MKK][1][14] = 54,
+ [0][1][2][1][RTW89_MKK][0][14] = 16,
+ [0][1][2][1][RTW89_IC][1][14] = -4,
+ [0][1][2][1][RTW89_KCC][1][14] = 12,
+ [0][1][2][1][RTW89_KCC][0][14] = 12,
+ [0][1][2][1][RTW89_ACMA][1][14] = 42,
+ [0][1][2][1][RTW89_ACMA][0][14] = 6,
+ [0][1][2][1][RTW89_CHILE][1][14] = -4,
+ [0][1][2][1][RTW89_QATAR][1][14] = 42,
+ [0][1][2][1][RTW89_QATAR][0][14] = 6,
+ [0][1][2][1][RTW89_UK][1][14] = 42,
+ [0][1][2][1][RTW89_UK][0][14] = 6,
+ [0][1][2][1][RTW89_FCC][1][15] = -4,
+ [0][1][2][1][RTW89_FCC][2][15] = 54,
+ [0][1][2][1][RTW89_ETSI][1][15] = 42,
+ [0][1][2][1][RTW89_ETSI][0][15] = 6,
+ [0][1][2][1][RTW89_MKK][1][15] = 54,
+ [0][1][2][1][RTW89_MKK][0][15] = 16,
+ [0][1][2][1][RTW89_IC][1][15] = -4,
+ [0][1][2][1][RTW89_KCC][1][15] = 12,
+ [0][1][2][1][RTW89_KCC][0][15] = 12,
+ [0][1][2][1][RTW89_ACMA][1][15] = 42,
+ [0][1][2][1][RTW89_ACMA][0][15] = 6,
+ [0][1][2][1][RTW89_CHILE][1][15] = -4,
+ [0][1][2][1][RTW89_QATAR][1][15] = 42,
+ [0][1][2][1][RTW89_QATAR][0][15] = 6,
+ [0][1][2][1][RTW89_UK][1][15] = 42,
+ [0][1][2][1][RTW89_UK][0][15] = 6,
+ [0][1][2][1][RTW89_FCC][1][17] = -4,
+ [0][1][2][1][RTW89_FCC][2][17] = 54,
+ [0][1][2][1][RTW89_ETSI][1][17] = 42,
+ [0][1][2][1][RTW89_ETSI][0][17] = 6,
+ [0][1][2][1][RTW89_MKK][1][17] = 54,
+ [0][1][2][1][RTW89_MKK][0][17] = 16,
+ [0][1][2][1][RTW89_IC][1][17] = -4,
+ [0][1][2][1][RTW89_KCC][1][17] = 12,
+ [0][1][2][1][RTW89_KCC][0][17] = 12,
+ [0][1][2][1][RTW89_ACMA][1][17] = 42,
+ [0][1][2][1][RTW89_ACMA][0][17] = 6,
+ [0][1][2][1][RTW89_CHILE][1][17] = -4,
+ [0][1][2][1][RTW89_QATAR][1][17] = 42,
+ [0][1][2][1][RTW89_QATAR][0][17] = 6,
+ [0][1][2][1][RTW89_UK][1][17] = 42,
+ [0][1][2][1][RTW89_UK][0][17] = 6,
+ [0][1][2][1][RTW89_FCC][1][19] = -4,
+ [0][1][2][1][RTW89_FCC][2][19] = 54,
+ [0][1][2][1][RTW89_ETSI][1][19] = 42,
+ [0][1][2][1][RTW89_ETSI][0][19] = 6,
+ [0][1][2][1][RTW89_MKK][1][19] = 54,
+ [0][1][2][1][RTW89_MKK][0][19] = 16,
+ [0][1][2][1][RTW89_IC][1][19] = -4,
+ [0][1][2][1][RTW89_KCC][1][19] = 12,
+ [0][1][2][1][RTW89_KCC][0][19] = 12,
+ [0][1][2][1][RTW89_ACMA][1][19] = 42,
+ [0][1][2][1][RTW89_ACMA][0][19] = 6,
+ [0][1][2][1][RTW89_CHILE][1][19] = -4,
+ [0][1][2][1][RTW89_QATAR][1][19] = 42,
+ [0][1][2][1][RTW89_QATAR][0][19] = 6,
+ [0][1][2][1][RTW89_UK][1][19] = 42,
+ [0][1][2][1][RTW89_UK][0][19] = 6,
+ [0][1][2][1][RTW89_FCC][1][21] = -4,
+ [0][1][2][1][RTW89_FCC][2][21] = 54,
+ [0][1][2][1][RTW89_ETSI][1][21] = 42,
+ [0][1][2][1][RTW89_ETSI][0][21] = 6,
+ [0][1][2][1][RTW89_MKK][1][21] = 54,
+ [0][1][2][1][RTW89_MKK][0][21] = 16,
+ [0][1][2][1][RTW89_IC][1][21] = -4,
+ [0][1][2][1][RTW89_KCC][1][21] = 12,
+ [0][1][2][1][RTW89_KCC][0][21] = 12,
+ [0][1][2][1][RTW89_ACMA][1][21] = 42,
+ [0][1][2][1][RTW89_ACMA][0][21] = 6,
+ [0][1][2][1][RTW89_CHILE][1][21] = -4,
+ [0][1][2][1][RTW89_QATAR][1][21] = 42,
+ [0][1][2][1][RTW89_QATAR][0][21] = 6,
+ [0][1][2][1][RTW89_UK][1][21] = 42,
+ [0][1][2][1][RTW89_UK][0][21] = 6,
+ [0][1][2][1][RTW89_FCC][1][23] = -4,
+ [0][1][2][1][RTW89_FCC][2][23] = 68,
+ [0][1][2][1][RTW89_ETSI][1][23] = 42,
+ [0][1][2][1][RTW89_ETSI][0][23] = 6,
+ [0][1][2][1][RTW89_MKK][1][23] = 54,
+ [0][1][2][1][RTW89_MKK][0][23] = 16,
+ [0][1][2][1][RTW89_IC][1][23] = -4,
+ [0][1][2][1][RTW89_KCC][1][23] = 12,
+ [0][1][2][1][RTW89_KCC][0][23] = 10,
+ [0][1][2][1][RTW89_ACMA][1][23] = 42,
+ [0][1][2][1][RTW89_ACMA][0][23] = 6,
+ [0][1][2][1][RTW89_CHILE][1][23] = -4,
+ [0][1][2][1][RTW89_QATAR][1][23] = 42,
+ [0][1][2][1][RTW89_QATAR][0][23] = 6,
+ [0][1][2][1][RTW89_UK][1][23] = 42,
+ [0][1][2][1][RTW89_UK][0][23] = 6,
+ [0][1][2][1][RTW89_FCC][1][25] = -4,
+ [0][1][2][1][RTW89_FCC][2][25] = 68,
+ [0][1][2][1][RTW89_ETSI][1][25] = 42,
+ [0][1][2][1][RTW89_ETSI][0][25] = 6,
+ [0][1][2][1][RTW89_MKK][1][25] = 54,
+ [0][1][2][1][RTW89_MKK][0][25] = 16,
+ [0][1][2][1][RTW89_IC][1][25] = -4,
+ [0][1][2][1][RTW89_KCC][1][25] = 12,
+ [0][1][2][1][RTW89_KCC][0][25] = 14,
+ [0][1][2][1][RTW89_ACMA][1][25] = 42,
+ [0][1][2][1][RTW89_ACMA][0][25] = 6,
+ [0][1][2][1][RTW89_CHILE][1][25] = -4,
+ [0][1][2][1][RTW89_QATAR][1][25] = 42,
+ [0][1][2][1][RTW89_QATAR][0][25] = 6,
+ [0][1][2][1][RTW89_UK][1][25] = 42,
+ [0][1][2][1][RTW89_UK][0][25] = 6,
+ [0][1][2][1][RTW89_FCC][1][27] = -4,
+ [0][1][2][1][RTW89_FCC][2][27] = 68,
+ [0][1][2][1][RTW89_ETSI][1][27] = 42,
+ [0][1][2][1][RTW89_ETSI][0][27] = 6,
+ [0][1][2][1][RTW89_MKK][1][27] = 54,
+ [0][1][2][1][RTW89_MKK][0][27] = 16,
+ [0][1][2][1][RTW89_IC][1][27] = -4,
+ [0][1][2][1][RTW89_KCC][1][27] = 12,
+ [0][1][2][1][RTW89_KCC][0][27] = 14,
+ [0][1][2][1][RTW89_ACMA][1][27] = 42,
+ [0][1][2][1][RTW89_ACMA][0][27] = 6,
+ [0][1][2][1][RTW89_CHILE][1][27] = -4,
+ [0][1][2][1][RTW89_QATAR][1][27] = 42,
+ [0][1][2][1][RTW89_QATAR][0][27] = 6,
+ [0][1][2][1][RTW89_UK][1][27] = 42,
+ [0][1][2][1][RTW89_UK][0][27] = 6,
+ [0][1][2][1][RTW89_FCC][1][29] = -4,
+ [0][1][2][1][RTW89_FCC][2][29] = 68,
+ [0][1][2][1][RTW89_ETSI][1][29] = 42,
+ [0][1][2][1][RTW89_ETSI][0][29] = 6,
+ [0][1][2][1][RTW89_MKK][1][29] = 54,
+ [0][1][2][1][RTW89_MKK][0][29] = 16,
+ [0][1][2][1][RTW89_IC][1][29] = -4,
+ [0][1][2][1][RTW89_KCC][1][29] = 12,
+ [0][1][2][1][RTW89_KCC][0][29] = 14,
+ [0][1][2][1][RTW89_ACMA][1][29] = 42,
+ [0][1][2][1][RTW89_ACMA][0][29] = 6,
+ [0][1][2][1][RTW89_CHILE][1][29] = -4,
+ [0][1][2][1][RTW89_QATAR][1][29] = 42,
+ [0][1][2][1][RTW89_QATAR][0][29] = 6,
+ [0][1][2][1][RTW89_UK][1][29] = 42,
+ [0][1][2][1][RTW89_UK][0][29] = 6,
+ [0][1][2][1][RTW89_FCC][1][30] = -4,
+ [0][1][2][1][RTW89_FCC][2][30] = 68,
+ [0][1][2][1][RTW89_ETSI][1][30] = 42,
+ [0][1][2][1][RTW89_ETSI][0][30] = 6,
+ [0][1][2][1][RTW89_MKK][1][30] = 54,
+ [0][1][2][1][RTW89_MKK][0][30] = 16,
+ [0][1][2][1][RTW89_IC][1][30] = -4,
+ [0][1][2][1][RTW89_KCC][1][30] = 12,
+ [0][1][2][1][RTW89_KCC][0][30] = 14,
+ [0][1][2][1][RTW89_ACMA][1][30] = 42,
+ [0][1][2][1][RTW89_ACMA][0][30] = 6,
+ [0][1][2][1][RTW89_CHILE][1][30] = -4,
+ [0][1][2][1][RTW89_QATAR][1][30] = 42,
+ [0][1][2][1][RTW89_QATAR][0][30] = 6,
+ [0][1][2][1][RTW89_UK][1][30] = 42,
+ [0][1][2][1][RTW89_UK][0][30] = 6,
+ [0][1][2][1][RTW89_FCC][1][32] = -4,
+ [0][1][2][1][RTW89_FCC][2][32] = 68,
+ [0][1][2][1][RTW89_ETSI][1][32] = 42,
+ [0][1][2][1][RTW89_ETSI][0][32] = 6,
+ [0][1][2][1][RTW89_MKK][1][32] = 54,
+ [0][1][2][1][RTW89_MKK][0][32] = 16,
+ [0][1][2][1][RTW89_IC][1][32] = -4,
+ [0][1][2][1][RTW89_KCC][1][32] = 12,
+ [0][1][2][1][RTW89_KCC][0][32] = 14,
+ [0][1][2][1][RTW89_ACMA][1][32] = 42,
+ [0][1][2][1][RTW89_ACMA][0][32] = 6,
+ [0][1][2][1][RTW89_CHILE][1][32] = -4,
+ [0][1][2][1][RTW89_QATAR][1][32] = 42,
+ [0][1][2][1][RTW89_QATAR][0][32] = 6,
+ [0][1][2][1][RTW89_UK][1][32] = 42,
+ [0][1][2][1][RTW89_UK][0][32] = 6,
+ [0][1][2][1][RTW89_FCC][1][34] = -4,
+ [0][1][2][1][RTW89_FCC][2][34] = 68,
+ [0][1][2][1][RTW89_ETSI][1][34] = 42,
+ [0][1][2][1][RTW89_ETSI][0][34] = 6,
+ [0][1][2][1][RTW89_MKK][1][34] = 54,
+ [0][1][2][1][RTW89_MKK][0][34] = 16,
+ [0][1][2][1][RTW89_IC][1][34] = -4,
+ [0][1][2][1][RTW89_KCC][1][34] = 12,
+ [0][1][2][1][RTW89_KCC][0][34] = 14,
+ [0][1][2][1][RTW89_ACMA][1][34] = 42,
+ [0][1][2][1][RTW89_ACMA][0][34] = 6,
+ [0][1][2][1][RTW89_CHILE][1][34] = -4,
+ [0][1][2][1][RTW89_QATAR][1][34] = 42,
+ [0][1][2][1][RTW89_QATAR][0][34] = 6,
+ [0][1][2][1][RTW89_UK][1][34] = 42,
+ [0][1][2][1][RTW89_UK][0][34] = 6,
+ [0][1][2][1][RTW89_FCC][1][36] = -4,
+ [0][1][2][1][RTW89_FCC][2][36] = 68,
+ [0][1][2][1][RTW89_ETSI][1][36] = 42,
+ [0][1][2][1][RTW89_ETSI][0][36] = 6,
+ [0][1][2][1][RTW89_MKK][1][36] = 54,
+ [0][1][2][1][RTW89_MKK][0][36] = 16,
+ [0][1][2][1][RTW89_IC][1][36] = -4,
+ [0][1][2][1][RTW89_KCC][1][36] = 12,
+ [0][1][2][1][RTW89_KCC][0][36] = 14,
+ [0][1][2][1][RTW89_ACMA][1][36] = 42,
+ [0][1][2][1][RTW89_ACMA][0][36] = 6,
+ [0][1][2][1][RTW89_CHILE][1][36] = -4,
+ [0][1][2][1][RTW89_QATAR][1][36] = 42,
+ [0][1][2][1][RTW89_QATAR][0][36] = 6,
+ [0][1][2][1][RTW89_UK][1][36] = 42,
+ [0][1][2][1][RTW89_UK][0][36] = 6,
+ [0][1][2][1][RTW89_FCC][1][38] = -4,
+ [0][1][2][1][RTW89_FCC][2][38] = 68,
+ [0][1][2][1][RTW89_ETSI][1][38] = 42,
+ [0][1][2][1][RTW89_ETSI][0][38] = 6,
+ [0][1][2][1][RTW89_MKK][1][38] = 54,
+ [0][1][2][1][RTW89_MKK][0][38] = 16,
+ [0][1][2][1][RTW89_IC][1][38] = -4,
+ [0][1][2][1][RTW89_KCC][1][38] = 12,
+ [0][1][2][1][RTW89_KCC][0][38] = 14,
+ [0][1][2][1][RTW89_ACMA][1][38] = 42,
+ [0][1][2][1][RTW89_ACMA][0][38] = 6,
+ [0][1][2][1][RTW89_CHILE][1][38] = -4,
+ [0][1][2][1][RTW89_QATAR][1][38] = 42,
+ [0][1][2][1][RTW89_QATAR][0][38] = 6,
+ [0][1][2][1][RTW89_UK][1][38] = 42,
+ [0][1][2][1][RTW89_UK][0][38] = 6,
+ [0][1][2][1][RTW89_FCC][1][40] = -4,
+ [0][1][2][1][RTW89_FCC][2][40] = 68,
+ [0][1][2][1][RTW89_ETSI][1][40] = 42,
+ [0][1][2][1][RTW89_ETSI][0][40] = 6,
+ [0][1][2][1][RTW89_MKK][1][40] = 54,
+ [0][1][2][1][RTW89_MKK][0][40] = 16,
+ [0][1][2][1][RTW89_IC][1][40] = -4,
+ [0][1][2][1][RTW89_KCC][1][40] = 12,
+ [0][1][2][1][RTW89_KCC][0][40] = 14,
+ [0][1][2][1][RTW89_ACMA][1][40] = 42,
+ [0][1][2][1][RTW89_ACMA][0][40] = 6,
+ [0][1][2][1][RTW89_CHILE][1][40] = -4,
+ [0][1][2][1][RTW89_QATAR][1][40] = 42,
+ [0][1][2][1][RTW89_QATAR][0][40] = 6,
+ [0][1][2][1][RTW89_UK][1][40] = 42,
+ [0][1][2][1][RTW89_UK][0][40] = 6,
+ [0][1][2][1][RTW89_FCC][1][42] = -4,
+ [0][1][2][1][RTW89_FCC][2][42] = 68,
+ [0][1][2][1][RTW89_ETSI][1][42] = 42,
+ [0][1][2][1][RTW89_ETSI][0][42] = 6,
+ [0][1][2][1][RTW89_MKK][1][42] = 54,
+ [0][1][2][1][RTW89_MKK][0][42] = 16,
+ [0][1][2][1][RTW89_IC][1][42] = -4,
+ [0][1][2][1][RTW89_KCC][1][42] = 12,
+ [0][1][2][1][RTW89_KCC][0][42] = 14,
+ [0][1][2][1][RTW89_ACMA][1][42] = 42,
+ [0][1][2][1][RTW89_ACMA][0][42] = 6,
+ [0][1][2][1][RTW89_CHILE][1][42] = -4,
+ [0][1][2][1][RTW89_QATAR][1][42] = 42,
+ [0][1][2][1][RTW89_QATAR][0][42] = 6,
+ [0][1][2][1][RTW89_UK][1][42] = 42,
+ [0][1][2][1][RTW89_UK][0][42] = 6,
+ [0][1][2][1][RTW89_FCC][1][44] = -2,
+ [0][1][2][1][RTW89_FCC][2][44] = 68,
+ [0][1][2][1][RTW89_ETSI][1][44] = 42,
+ [0][1][2][1][RTW89_ETSI][0][44] = 6,
+ [0][1][2][1][RTW89_MKK][1][44] = 34,
+ [0][1][2][1][RTW89_MKK][0][44] = 16,
+ [0][1][2][1][RTW89_IC][1][44] = -2,
+ [0][1][2][1][RTW89_KCC][1][44] = 12,
+ [0][1][2][1][RTW89_KCC][0][44] = 12,
+ [0][1][2][1][RTW89_ACMA][1][44] = 42,
+ [0][1][2][1][RTW89_ACMA][0][44] = 6,
+ [0][1][2][1][RTW89_CHILE][1][44] = -2,
+ [0][1][2][1][RTW89_QATAR][1][44] = 42,
+ [0][1][2][1][RTW89_QATAR][0][44] = 6,
+ [0][1][2][1][RTW89_UK][1][44] = 42,
+ [0][1][2][1][RTW89_UK][0][44] = 6,
+ [0][1][2][1][RTW89_FCC][1][45] = -2,
+ [0][1][2][1][RTW89_FCC][2][45] = 127,
+ [0][1][2][1][RTW89_ETSI][1][45] = 127,
+ [0][1][2][1][RTW89_ETSI][0][45] = 127,
+ [0][1][2][1][RTW89_MKK][1][45] = 127,
+ [0][1][2][1][RTW89_MKK][0][45] = 127,
+ [0][1][2][1][RTW89_IC][1][45] = -2,
+ [0][1][2][1][RTW89_KCC][1][45] = 12,
+ [0][1][2][1][RTW89_KCC][0][45] = 127,
+ [0][1][2][1][RTW89_ACMA][1][45] = 127,
+ [0][1][2][1][RTW89_ACMA][0][45] = 127,
+ [0][1][2][1][RTW89_CHILE][1][45] = -2,
+ [0][1][2][1][RTW89_QATAR][1][45] = 127,
+ [0][1][2][1][RTW89_QATAR][0][45] = 127,
+ [0][1][2][1][RTW89_UK][1][45] = 127,
+ [0][1][2][1][RTW89_UK][0][45] = 127,
+ [0][1][2][1][RTW89_FCC][1][47] = -2,
+ [0][1][2][1][RTW89_FCC][2][47] = 127,
+ [0][1][2][1][RTW89_ETSI][1][47] = 127,
+ [0][1][2][1][RTW89_ETSI][0][47] = 127,
+ [0][1][2][1][RTW89_MKK][1][47] = 127,
+ [0][1][2][1][RTW89_MKK][0][47] = 127,
+ [0][1][2][1][RTW89_IC][1][47] = -2,
+ [0][1][2][1][RTW89_KCC][1][47] = 12,
+ [0][1][2][1][RTW89_KCC][0][47] = 127,
+ [0][1][2][1][RTW89_ACMA][1][47] = 127,
+ [0][1][2][1][RTW89_ACMA][0][47] = 127,
+ [0][1][2][1][RTW89_CHILE][1][47] = -2,
+ [0][1][2][1][RTW89_QATAR][1][47] = 127,
+ [0][1][2][1][RTW89_QATAR][0][47] = 127,
+ [0][1][2][1][RTW89_UK][1][47] = 127,
+ [0][1][2][1][RTW89_UK][0][47] = 127,
+ [0][1][2][1][RTW89_FCC][1][49] = -2,
+ [0][1][2][1][RTW89_FCC][2][49] = 127,
+ [0][1][2][1][RTW89_ETSI][1][49] = 127,
+ [0][1][2][1][RTW89_ETSI][0][49] = 127,
+ [0][1][2][1][RTW89_MKK][1][49] = 127,
+ [0][1][2][1][RTW89_MKK][0][49] = 127,
+ [0][1][2][1][RTW89_IC][1][49] = -2,
+ [0][1][2][1][RTW89_KCC][1][49] = 12,
+ [0][1][2][1][RTW89_KCC][0][49] = 127,
+ [0][1][2][1][RTW89_ACMA][1][49] = 127,
+ [0][1][2][1][RTW89_ACMA][0][49] = 127,
+ [0][1][2][1][RTW89_CHILE][1][49] = -2,
+ [0][1][2][1][RTW89_QATAR][1][49] = 127,
+ [0][1][2][1][RTW89_QATAR][0][49] = 127,
+ [0][1][2][1][RTW89_UK][1][49] = 127,
+ [0][1][2][1][RTW89_UK][0][49] = 127,
+ [0][1][2][1][RTW89_FCC][1][51] = -2,
+ [0][1][2][1][RTW89_FCC][2][51] = 127,
+ [0][1][2][1][RTW89_ETSI][1][51] = 127,
+ [0][1][2][1][RTW89_ETSI][0][51] = 127,
+ [0][1][2][1][RTW89_MKK][1][51] = 127,
+ [0][1][2][1][RTW89_MKK][0][51] = 127,
+ [0][1][2][1][RTW89_IC][1][51] = -2,
+ [0][1][2][1][RTW89_KCC][1][51] = 12,
+ [0][1][2][1][RTW89_KCC][0][51] = 127,
+ [0][1][2][1][RTW89_ACMA][1][51] = 127,
+ [0][1][2][1][RTW89_ACMA][0][51] = 127,
+ [0][1][2][1][RTW89_CHILE][1][51] = -2,
+ [0][1][2][1][RTW89_QATAR][1][51] = 127,
+ [0][1][2][1][RTW89_QATAR][0][51] = 127,
+ [0][1][2][1][RTW89_UK][1][51] = 127,
+ [0][1][2][1][RTW89_UK][0][51] = 127,
+ [0][1][2][1][RTW89_FCC][1][53] = -2,
+ [0][1][2][1][RTW89_FCC][2][53] = 127,
+ [0][1][2][1][RTW89_ETSI][1][53] = 127,
+ [0][1][2][1][RTW89_ETSI][0][53] = 127,
+ [0][1][2][1][RTW89_MKK][1][53] = 127,
+ [0][1][2][1][RTW89_MKK][0][53] = 127,
+ [0][1][2][1][RTW89_IC][1][53] = -2,
+ [0][1][2][1][RTW89_KCC][1][53] = 12,
+ [0][1][2][1][RTW89_KCC][0][53] = 127,
+ [0][1][2][1][RTW89_ACMA][1][53] = 127,
+ [0][1][2][1][RTW89_ACMA][0][53] = 127,
+ [0][1][2][1][RTW89_CHILE][1][53] = -2,
+ [0][1][2][1][RTW89_QATAR][1][53] = 127,
+ [0][1][2][1][RTW89_QATAR][0][53] = 127,
+ [0][1][2][1][RTW89_UK][1][53] = 127,
+ [0][1][2][1][RTW89_UK][0][53] = 127,
+ [0][1][2][1][RTW89_FCC][1][55] = -2,
+ [0][1][2][1][RTW89_FCC][2][55] = 68,
+ [0][1][2][1][RTW89_ETSI][1][55] = 127,
+ [0][1][2][1][RTW89_ETSI][0][55] = 127,
+ [0][1][2][1][RTW89_MKK][1][55] = 127,
+ [0][1][2][1][RTW89_MKK][0][55] = 127,
+ [0][1][2][1][RTW89_IC][1][55] = -2,
+ [0][1][2][1][RTW89_KCC][1][55] = 12,
+ [0][1][2][1][RTW89_KCC][0][55] = 127,
+ [0][1][2][1][RTW89_ACMA][1][55] = 127,
+ [0][1][2][1][RTW89_ACMA][0][55] = 127,
+ [0][1][2][1][RTW89_CHILE][1][55] = -2,
+ [0][1][2][1][RTW89_QATAR][1][55] = 127,
+ [0][1][2][1][RTW89_QATAR][0][55] = 127,
+ [0][1][2][1][RTW89_UK][1][55] = 127,
+ [0][1][2][1][RTW89_UK][0][55] = 127,
+ [0][1][2][1][RTW89_FCC][1][57] = -2,
+ [0][1][2][1][RTW89_FCC][2][57] = 68,
+ [0][1][2][1][RTW89_ETSI][1][57] = 127,
+ [0][1][2][1][RTW89_ETSI][0][57] = 127,
+ [0][1][2][1][RTW89_MKK][1][57] = 127,
+ [0][1][2][1][RTW89_MKK][0][57] = 127,
+ [0][1][2][1][RTW89_IC][1][57] = -2,
+ [0][1][2][1][RTW89_KCC][1][57] = 12,
+ [0][1][2][1][RTW89_KCC][0][57] = 127,
+ [0][1][2][1][RTW89_ACMA][1][57] = 127,
+ [0][1][2][1][RTW89_ACMA][0][57] = 127,
+ [0][1][2][1][RTW89_CHILE][1][57] = -2,
+ [0][1][2][1][RTW89_QATAR][1][57] = 127,
+ [0][1][2][1][RTW89_QATAR][0][57] = 127,
+ [0][1][2][1][RTW89_UK][1][57] = 127,
+ [0][1][2][1][RTW89_UK][0][57] = 127,
+ [0][1][2][1][RTW89_FCC][1][59] = -2,
+ [0][1][2][1][RTW89_FCC][2][59] = 68,
+ [0][1][2][1][RTW89_ETSI][1][59] = 127,
+ [0][1][2][1][RTW89_ETSI][0][59] = 127,
+ [0][1][2][1][RTW89_MKK][1][59] = 127,
+ [0][1][2][1][RTW89_MKK][0][59] = 127,
+ [0][1][2][1][RTW89_IC][1][59] = -2,
+ [0][1][2][1][RTW89_KCC][1][59] = 12,
+ [0][1][2][1][RTW89_KCC][0][59] = 127,
+ [0][1][2][1][RTW89_ACMA][1][59] = 127,
+ [0][1][2][1][RTW89_ACMA][0][59] = 127,
+ [0][1][2][1][RTW89_CHILE][1][59] = -2,
+ [0][1][2][1][RTW89_QATAR][1][59] = 127,
+ [0][1][2][1][RTW89_QATAR][0][59] = 127,
+ [0][1][2][1][RTW89_UK][1][59] = 127,
+ [0][1][2][1][RTW89_UK][0][59] = 127,
+ [0][1][2][1][RTW89_FCC][1][60] = -2,
+ [0][1][2][1][RTW89_FCC][2][60] = 68,
+ [0][1][2][1][RTW89_ETSI][1][60] = 127,
+ [0][1][2][1][RTW89_ETSI][0][60] = 127,
+ [0][1][2][1][RTW89_MKK][1][60] = 127,
+ [0][1][2][1][RTW89_MKK][0][60] = 127,
+ [0][1][2][1][RTW89_IC][1][60] = -2,
+ [0][1][2][1][RTW89_KCC][1][60] = 12,
+ [0][1][2][1][RTW89_KCC][0][60] = 127,
+ [0][1][2][1][RTW89_ACMA][1][60] = 127,
+ [0][1][2][1][RTW89_ACMA][0][60] = 127,
+ [0][1][2][1][RTW89_CHILE][1][60] = -2,
+ [0][1][2][1][RTW89_QATAR][1][60] = 127,
+ [0][1][2][1][RTW89_QATAR][0][60] = 127,
+ [0][1][2][1][RTW89_UK][1][60] = 127,
+ [0][1][2][1][RTW89_UK][0][60] = 127,
+ [0][1][2][1][RTW89_FCC][1][62] = -2,
+ [0][1][2][1][RTW89_FCC][2][62] = 68,
+ [0][1][2][1][RTW89_ETSI][1][62] = 127,
+ [0][1][2][1][RTW89_ETSI][0][62] = 127,
+ [0][1][2][1][RTW89_MKK][1][62] = 127,
+ [0][1][2][1][RTW89_MKK][0][62] = 127,
+ [0][1][2][1][RTW89_IC][1][62] = -2,
+ [0][1][2][1][RTW89_KCC][1][62] = 12,
+ [0][1][2][1][RTW89_KCC][0][62] = 127,
+ [0][1][2][1][RTW89_ACMA][1][62] = 127,
+ [0][1][2][1][RTW89_ACMA][0][62] = 127,
+ [0][1][2][1][RTW89_CHILE][1][62] = -2,
+ [0][1][2][1][RTW89_QATAR][1][62] = 127,
+ [0][1][2][1][RTW89_QATAR][0][62] = 127,
+ [0][1][2][1][RTW89_UK][1][62] = 127,
+ [0][1][2][1][RTW89_UK][0][62] = 127,
+ [0][1][2][1][RTW89_FCC][1][64] = -2,
+ [0][1][2][1][RTW89_FCC][2][64] = 68,
+ [0][1][2][1][RTW89_ETSI][1][64] = 127,
+ [0][1][2][1][RTW89_ETSI][0][64] = 127,
+ [0][1][2][1][RTW89_MKK][1][64] = 127,
+ [0][1][2][1][RTW89_MKK][0][64] = 127,
+ [0][1][2][1][RTW89_IC][1][64] = -2,
+ [0][1][2][1][RTW89_KCC][1][64] = 12,
+ [0][1][2][1][RTW89_KCC][0][64] = 127,
+ [0][1][2][1][RTW89_ACMA][1][64] = 127,
+ [0][1][2][1][RTW89_ACMA][0][64] = 127,
+ [0][1][2][1][RTW89_CHILE][1][64] = -2,
+ [0][1][2][1][RTW89_QATAR][1][64] = 127,
+ [0][1][2][1][RTW89_QATAR][0][64] = 127,
+ [0][1][2][1][RTW89_UK][1][64] = 127,
+ [0][1][2][1][RTW89_UK][0][64] = 127,
+ [0][1][2][1][RTW89_FCC][1][66] = -2,
+ [0][1][2][1][RTW89_FCC][2][66] = 68,
+ [0][1][2][1][RTW89_ETSI][1][66] = 127,
+ [0][1][2][1][RTW89_ETSI][0][66] = 127,
+ [0][1][2][1][RTW89_MKK][1][66] = 127,
+ [0][1][2][1][RTW89_MKK][0][66] = 127,
+ [0][1][2][1][RTW89_IC][1][66] = -2,
+ [0][1][2][1][RTW89_KCC][1][66] = 12,
+ [0][1][2][1][RTW89_KCC][0][66] = 127,
+ [0][1][2][1][RTW89_ACMA][1][66] = 127,
+ [0][1][2][1][RTW89_ACMA][0][66] = 127,
+ [0][1][2][1][RTW89_CHILE][1][66] = -2,
+ [0][1][2][1][RTW89_QATAR][1][66] = 127,
+ [0][1][2][1][RTW89_QATAR][0][66] = 127,
+ [0][1][2][1][RTW89_UK][1][66] = 127,
+ [0][1][2][1][RTW89_UK][0][66] = 127,
+ [0][1][2][1][RTW89_FCC][1][68] = -2,
+ [0][1][2][1][RTW89_FCC][2][68] = 68,
+ [0][1][2][1][RTW89_ETSI][1][68] = 127,
+ [0][1][2][1][RTW89_ETSI][0][68] = 127,
+ [0][1][2][1][RTW89_MKK][1][68] = 127,
+ [0][1][2][1][RTW89_MKK][0][68] = 127,
+ [0][1][2][1][RTW89_IC][1][68] = -2,
+ [0][1][2][1][RTW89_KCC][1][68] = 12,
+ [0][1][2][1][RTW89_KCC][0][68] = 127,
+ [0][1][2][1][RTW89_ACMA][1][68] = 127,
+ [0][1][2][1][RTW89_ACMA][0][68] = 127,
+ [0][1][2][1][RTW89_CHILE][1][68] = -2,
+ [0][1][2][1][RTW89_QATAR][1][68] = 127,
+ [0][1][2][1][RTW89_QATAR][0][68] = 127,
+ [0][1][2][1][RTW89_UK][1][68] = 127,
+ [0][1][2][1][RTW89_UK][0][68] = 127,
+ [0][1][2][1][RTW89_FCC][1][70] = -2,
+ [0][1][2][1][RTW89_FCC][2][70] = 68,
+ [0][1][2][1][RTW89_ETSI][1][70] = 127,
+ [0][1][2][1][RTW89_ETSI][0][70] = 127,
+ [0][1][2][1][RTW89_MKK][1][70] = 127,
+ [0][1][2][1][RTW89_MKK][0][70] = 127,
+ [0][1][2][1][RTW89_IC][1][70] = -2,
+ [0][1][2][1][RTW89_KCC][1][70] = 12,
+ [0][1][2][1][RTW89_KCC][0][70] = 127,
+ [0][1][2][1][RTW89_ACMA][1][70] = 127,
+ [0][1][2][1][RTW89_ACMA][0][70] = 127,
+ [0][1][2][1][RTW89_CHILE][1][70] = -2,
+ [0][1][2][1][RTW89_QATAR][1][70] = 127,
+ [0][1][2][1][RTW89_QATAR][0][70] = 127,
+ [0][1][2][1][RTW89_UK][1][70] = 127,
+ [0][1][2][1][RTW89_UK][0][70] = 127,
+ [0][1][2][1][RTW89_FCC][1][72] = -2,
+ [0][1][2][1][RTW89_FCC][2][72] = 68,
+ [0][1][2][1][RTW89_ETSI][1][72] = 127,
+ [0][1][2][1][RTW89_ETSI][0][72] = 127,
+ [0][1][2][1][RTW89_MKK][1][72] = 127,
+ [0][1][2][1][RTW89_MKK][0][72] = 127,
+ [0][1][2][1][RTW89_IC][1][72] = -2,
+ [0][1][2][1][RTW89_KCC][1][72] = 12,
+ [0][1][2][1][RTW89_KCC][0][72] = 127,
+ [0][1][2][1][RTW89_ACMA][1][72] = 127,
+ [0][1][2][1][RTW89_ACMA][0][72] = 127,
+ [0][1][2][1][RTW89_CHILE][1][72] = -2,
+ [0][1][2][1][RTW89_QATAR][1][72] = 127,
+ [0][1][2][1][RTW89_QATAR][0][72] = 127,
+ [0][1][2][1][RTW89_UK][1][72] = 127,
+ [0][1][2][1][RTW89_UK][0][72] = 127,
+ [0][1][2][1][RTW89_FCC][1][74] = -2,
+ [0][1][2][1][RTW89_FCC][2][74] = 68,
+ [0][1][2][1][RTW89_ETSI][1][74] = 127,
+ [0][1][2][1][RTW89_ETSI][0][74] = 127,
+ [0][1][2][1][RTW89_MKK][1][74] = 127,
+ [0][1][2][1][RTW89_MKK][0][74] = 127,
+ [0][1][2][1][RTW89_IC][1][74] = -2,
+ [0][1][2][1][RTW89_KCC][1][74] = 12,
+ [0][1][2][1][RTW89_KCC][0][74] = 127,
+ [0][1][2][1][RTW89_ACMA][1][74] = 127,
+ [0][1][2][1][RTW89_ACMA][0][74] = 127,
+ [0][1][2][1][RTW89_CHILE][1][74] = -2,
+ [0][1][2][1][RTW89_QATAR][1][74] = 127,
+ [0][1][2][1][RTW89_QATAR][0][74] = 127,
+ [0][1][2][1][RTW89_UK][1][74] = 127,
+ [0][1][2][1][RTW89_UK][0][74] = 127,
+ [0][1][2][1][RTW89_FCC][1][75] = -2,
+ [0][1][2][1][RTW89_FCC][2][75] = 68,
+ [0][1][2][1][RTW89_ETSI][1][75] = 127,
+ [0][1][2][1][RTW89_ETSI][0][75] = 127,
+ [0][1][2][1][RTW89_MKK][1][75] = 127,
+ [0][1][2][1][RTW89_MKK][0][75] = 127,
+ [0][1][2][1][RTW89_IC][1][75] = -2,
+ [0][1][2][1][RTW89_KCC][1][75] = 12,
+ [0][1][2][1][RTW89_KCC][0][75] = 127,
+ [0][1][2][1][RTW89_ACMA][1][75] = 127,
+ [0][1][2][1][RTW89_ACMA][0][75] = 127,
+ [0][1][2][1][RTW89_CHILE][1][75] = -2,
+ [0][1][2][1][RTW89_QATAR][1][75] = 127,
+ [0][1][2][1][RTW89_QATAR][0][75] = 127,
+ [0][1][2][1][RTW89_UK][1][75] = 127,
+ [0][1][2][1][RTW89_UK][0][75] = 127,
+ [0][1][2][1][RTW89_FCC][1][77] = -2,
+ [0][1][2][1][RTW89_FCC][2][77] = 68,
+ [0][1][2][1][RTW89_ETSI][1][77] = 127,
+ [0][1][2][1][RTW89_ETSI][0][77] = 127,
+ [0][1][2][1][RTW89_MKK][1][77] = 127,
+ [0][1][2][1][RTW89_MKK][0][77] = 127,
+ [0][1][2][1][RTW89_IC][1][77] = -2,
+ [0][1][2][1][RTW89_KCC][1][77] = 12,
+ [0][1][2][1][RTW89_KCC][0][77] = 127,
+ [0][1][2][1][RTW89_ACMA][1][77] = 127,
+ [0][1][2][1][RTW89_ACMA][0][77] = 127,
+ [0][1][2][1][RTW89_CHILE][1][77] = -2,
+ [0][1][2][1][RTW89_QATAR][1][77] = 127,
+ [0][1][2][1][RTW89_QATAR][0][77] = 127,
+ [0][1][2][1][RTW89_UK][1][77] = 127,
+ [0][1][2][1][RTW89_UK][0][77] = 127,
+ [0][1][2][1][RTW89_FCC][1][79] = -2,
+ [0][1][2][1][RTW89_FCC][2][79] = 68,
+ [0][1][2][1][RTW89_ETSI][1][79] = 127,
+ [0][1][2][1][RTW89_ETSI][0][79] = 127,
+ [0][1][2][1][RTW89_MKK][1][79] = 127,
+ [0][1][2][1][RTW89_MKK][0][79] = 127,
+ [0][1][2][1][RTW89_IC][1][79] = -2,
+ [0][1][2][1][RTW89_KCC][1][79] = 12,
+ [0][1][2][1][RTW89_KCC][0][79] = 127,
+ [0][1][2][1][RTW89_ACMA][1][79] = 127,
+ [0][1][2][1][RTW89_ACMA][0][79] = 127,
+ [0][1][2][1][RTW89_CHILE][1][79] = -2,
+ [0][1][2][1][RTW89_QATAR][1][79] = 127,
+ [0][1][2][1][RTW89_QATAR][0][79] = 127,
+ [0][1][2][1][RTW89_UK][1][79] = 127,
+ [0][1][2][1][RTW89_UK][0][79] = 127,
+ [0][1][2][1][RTW89_FCC][1][81] = -2,
+ [0][1][2][1][RTW89_FCC][2][81] = 68,
+ [0][1][2][1][RTW89_ETSI][1][81] = 127,
+ [0][1][2][1][RTW89_ETSI][0][81] = 127,
+ [0][1][2][1][RTW89_MKK][1][81] = 127,
+ [0][1][2][1][RTW89_MKK][0][81] = 127,
+ [0][1][2][1][RTW89_IC][1][81] = -2,
+ [0][1][2][1][RTW89_KCC][1][81] = 12,
+ [0][1][2][1][RTW89_KCC][0][81] = 127,
+ [0][1][2][1][RTW89_ACMA][1][81] = 127,
+ [0][1][2][1][RTW89_ACMA][0][81] = 127,
+ [0][1][2][1][RTW89_CHILE][1][81] = -2,
+ [0][1][2][1][RTW89_QATAR][1][81] = 127,
+ [0][1][2][1][RTW89_QATAR][0][81] = 127,
+ [0][1][2][1][RTW89_UK][1][81] = 127,
+ [0][1][2][1][RTW89_UK][0][81] = 127,
+ [0][1][2][1][RTW89_FCC][1][83] = -2,
+ [0][1][2][1][RTW89_FCC][2][83] = 68,
+ [0][1][2][1][RTW89_ETSI][1][83] = 127,
+ [0][1][2][1][RTW89_ETSI][0][83] = 127,
+ [0][1][2][1][RTW89_MKK][1][83] = 127,
+ [0][1][2][1][RTW89_MKK][0][83] = 127,
+ [0][1][2][1][RTW89_IC][1][83] = -2,
+ [0][1][2][1][RTW89_KCC][1][83] = 20,
+ [0][1][2][1][RTW89_KCC][0][83] = 127,
+ [0][1][2][1][RTW89_ACMA][1][83] = 127,
+ [0][1][2][1][RTW89_ACMA][0][83] = 127,
+ [0][1][2][1][RTW89_CHILE][1][83] = -2,
+ [0][1][2][1][RTW89_QATAR][1][83] = 127,
+ [0][1][2][1][RTW89_QATAR][0][83] = 127,
+ [0][1][2][1][RTW89_UK][1][83] = 127,
+ [0][1][2][1][RTW89_UK][0][83] = 127,
+ [0][1][2][1][RTW89_FCC][1][85] = -2,
+ [0][1][2][1][RTW89_FCC][2][85] = 68,
+ [0][1][2][1][RTW89_ETSI][1][85] = 127,
+ [0][1][2][1][RTW89_ETSI][0][85] = 127,
+ [0][1][2][1][RTW89_MKK][1][85] = 127,
+ [0][1][2][1][RTW89_MKK][0][85] = 127,
+ [0][1][2][1][RTW89_IC][1][85] = -2,
+ [0][1][2][1][RTW89_KCC][1][85] = 20,
+ [0][1][2][1][RTW89_KCC][0][85] = 127,
+ [0][1][2][1][RTW89_ACMA][1][85] = 127,
+ [0][1][2][1][RTW89_ACMA][0][85] = 127,
+ [0][1][2][1][RTW89_CHILE][1][85] = -2,
+ [0][1][2][1][RTW89_QATAR][1][85] = 127,
+ [0][1][2][1][RTW89_QATAR][0][85] = 127,
+ [0][1][2][1][RTW89_UK][1][85] = 127,
+ [0][1][2][1][RTW89_UK][0][85] = 127,
+ [0][1][2][1][RTW89_FCC][1][87] = -2,
+ [0][1][2][1][RTW89_FCC][2][87] = 127,
+ [0][1][2][1][RTW89_ETSI][1][87] = 127,
+ [0][1][2][1][RTW89_ETSI][0][87] = 127,
+ [0][1][2][1][RTW89_MKK][1][87] = 127,
+ [0][1][2][1][RTW89_MKK][0][87] = 127,
+ [0][1][2][1][RTW89_IC][1][87] = -2,
+ [0][1][2][1][RTW89_KCC][1][87] = 20,
+ [0][1][2][1][RTW89_KCC][0][87] = 127,
+ [0][1][2][1][RTW89_ACMA][1][87] = 127,
+ [0][1][2][1][RTW89_ACMA][0][87] = 127,
+ [0][1][2][1][RTW89_CHILE][1][87] = -2,
+ [0][1][2][1][RTW89_QATAR][1][87] = 127,
+ [0][1][2][1][RTW89_QATAR][0][87] = 127,
+ [0][1][2][1][RTW89_UK][1][87] = 127,
+ [0][1][2][1][RTW89_UK][0][87] = 127,
+ [0][1][2][1][RTW89_FCC][1][89] = -2,
+ [0][1][2][1][RTW89_FCC][2][89] = 127,
+ [0][1][2][1][RTW89_ETSI][1][89] = 127,
+ [0][1][2][1][RTW89_ETSI][0][89] = 127,
+ [0][1][2][1][RTW89_MKK][1][89] = 127,
+ [0][1][2][1][RTW89_MKK][0][89] = 127,
+ [0][1][2][1][RTW89_IC][1][89] = -2,
+ [0][1][2][1][RTW89_KCC][1][89] = 20,
+ [0][1][2][1][RTW89_KCC][0][89] = 127,
+ [0][1][2][1][RTW89_ACMA][1][89] = 127,
+ [0][1][2][1][RTW89_ACMA][0][89] = 127,
+ [0][1][2][1][RTW89_CHILE][1][89] = -2,
+ [0][1][2][1][RTW89_QATAR][1][89] = 127,
+ [0][1][2][1][RTW89_QATAR][0][89] = 127,
+ [0][1][2][1][RTW89_UK][1][89] = 127,
+ [0][1][2][1][RTW89_UK][0][89] = 127,
+ [0][1][2][1][RTW89_FCC][1][90] = -2,
+ [0][1][2][1][RTW89_FCC][2][90] = 127,
+ [0][1][2][1][RTW89_ETSI][1][90] = 127,
+ [0][1][2][1][RTW89_ETSI][0][90] = 127,
+ [0][1][2][1][RTW89_MKK][1][90] = 127,
+ [0][1][2][1][RTW89_MKK][0][90] = 127,
+ [0][1][2][1][RTW89_IC][1][90] = -2,
+ [0][1][2][1][RTW89_KCC][1][90] = 20,
+ [0][1][2][1][RTW89_KCC][0][90] = 127,
+ [0][1][2][1][RTW89_ACMA][1][90] = 127,
+ [0][1][2][1][RTW89_ACMA][0][90] = 127,
+ [0][1][2][1][RTW89_CHILE][1][90] = -2,
+ [0][1][2][1][RTW89_QATAR][1][90] = 127,
+ [0][1][2][1][RTW89_QATAR][0][90] = 127,
+ [0][1][2][1][RTW89_UK][1][90] = 127,
+ [0][1][2][1][RTW89_UK][0][90] = 127,
+ [0][1][2][1][RTW89_FCC][1][92] = -2,
+ [0][1][2][1][RTW89_FCC][2][92] = 127,
+ [0][1][2][1][RTW89_ETSI][1][92] = 127,
+ [0][1][2][1][RTW89_ETSI][0][92] = 127,
+ [0][1][2][1][RTW89_MKK][1][92] = 127,
+ [0][1][2][1][RTW89_MKK][0][92] = 127,
+ [0][1][2][1][RTW89_IC][1][92] = -2,
+ [0][1][2][1][RTW89_KCC][1][92] = 20,
+ [0][1][2][1][RTW89_KCC][0][92] = 127,
+ [0][1][2][1][RTW89_ACMA][1][92] = 127,
+ [0][1][2][1][RTW89_ACMA][0][92] = 127,
+ [0][1][2][1][RTW89_CHILE][1][92] = -2,
+ [0][1][2][1][RTW89_QATAR][1][92] = 127,
+ [0][1][2][1][RTW89_QATAR][0][92] = 127,
+ [0][1][2][1][RTW89_UK][1][92] = 127,
+ [0][1][2][1][RTW89_UK][0][92] = 127,
+ [0][1][2][1][RTW89_FCC][1][94] = -2,
+ [0][1][2][1][RTW89_FCC][2][94] = 127,
+ [0][1][2][1][RTW89_ETSI][1][94] = 127,
+ [0][1][2][1][RTW89_ETSI][0][94] = 127,
+ [0][1][2][1][RTW89_MKK][1][94] = 127,
+ [0][1][2][1][RTW89_MKK][0][94] = 127,
+ [0][1][2][1][RTW89_IC][1][94] = -2,
+ [0][1][2][1][RTW89_KCC][1][94] = 20,
+ [0][1][2][1][RTW89_KCC][0][94] = 127,
+ [0][1][2][1][RTW89_ACMA][1][94] = 127,
+ [0][1][2][1][RTW89_ACMA][0][94] = 127,
+ [0][1][2][1][RTW89_CHILE][1][94] = -2,
+ [0][1][2][1][RTW89_QATAR][1][94] = 127,
+ [0][1][2][1][RTW89_QATAR][0][94] = 127,
+ [0][1][2][1][RTW89_UK][1][94] = 127,
+ [0][1][2][1][RTW89_UK][0][94] = 127,
+ [0][1][2][1][RTW89_FCC][1][96] = -2,
+ [0][1][2][1][RTW89_FCC][2][96] = 127,
+ [0][1][2][1][RTW89_ETSI][1][96] = 127,
+ [0][1][2][1][RTW89_ETSI][0][96] = 127,
+ [0][1][2][1][RTW89_MKK][1][96] = 127,
+ [0][1][2][1][RTW89_MKK][0][96] = 127,
+ [0][1][2][1][RTW89_IC][1][96] = -2,
+ [0][1][2][1][RTW89_KCC][1][96] = 20,
+ [0][1][2][1][RTW89_KCC][0][96] = 127,
+ [0][1][2][1][RTW89_ACMA][1][96] = 127,
+ [0][1][2][1][RTW89_ACMA][0][96] = 127,
+ [0][1][2][1][RTW89_CHILE][1][96] = -2,
+ [0][1][2][1][RTW89_QATAR][1][96] = 127,
+ [0][1][2][1][RTW89_QATAR][0][96] = 127,
+ [0][1][2][1][RTW89_UK][1][96] = 127,
+ [0][1][2][1][RTW89_UK][0][96] = 127,
+ [0][1][2][1][RTW89_FCC][1][98] = -2,
+ [0][1][2][1][RTW89_FCC][2][98] = 127,
+ [0][1][2][1][RTW89_ETSI][1][98] = 127,
+ [0][1][2][1][RTW89_ETSI][0][98] = 127,
+ [0][1][2][1][RTW89_MKK][1][98] = 127,
+ [0][1][2][1][RTW89_MKK][0][98] = 127,
+ [0][1][2][1][RTW89_IC][1][98] = -2,
+ [0][1][2][1][RTW89_KCC][1][98] = 20,
+ [0][1][2][1][RTW89_KCC][0][98] = 127,
+ [0][1][2][1][RTW89_ACMA][1][98] = 127,
+ [0][1][2][1][RTW89_ACMA][0][98] = 127,
+ [0][1][2][1][RTW89_CHILE][1][98] = -2,
+ [0][1][2][1][RTW89_QATAR][1][98] = 127,
+ [0][1][2][1][RTW89_QATAR][0][98] = 127,
+ [0][1][2][1][RTW89_UK][1][98] = 127,
+ [0][1][2][1][RTW89_UK][0][98] = 127,
+ [0][1][2][1][RTW89_FCC][1][100] = -2,
+ [0][1][2][1][RTW89_FCC][2][100] = 127,
+ [0][1][2][1][RTW89_ETSI][1][100] = 127,
+ [0][1][2][1][RTW89_ETSI][0][100] = 127,
+ [0][1][2][1][RTW89_MKK][1][100] = 127,
+ [0][1][2][1][RTW89_MKK][0][100] = 127,
+ [0][1][2][1][RTW89_IC][1][100] = -2,
+ [0][1][2][1][RTW89_KCC][1][100] = 20,
+ [0][1][2][1][RTW89_KCC][0][100] = 127,
+ [0][1][2][1][RTW89_ACMA][1][100] = 127,
+ [0][1][2][1][RTW89_ACMA][0][100] = 127,
+ [0][1][2][1][RTW89_CHILE][1][100] = -2,
+ [0][1][2][1][RTW89_QATAR][1][100] = 127,
+ [0][1][2][1][RTW89_QATAR][0][100] = 127,
+ [0][1][2][1][RTW89_UK][1][100] = 127,
+ [0][1][2][1][RTW89_UK][0][100] = 127,
+ [0][1][2][1][RTW89_FCC][1][102] = -2,
+ [0][1][2][1][RTW89_FCC][2][102] = 127,
+ [0][1][2][1][RTW89_ETSI][1][102] = 127,
+ [0][1][2][1][RTW89_ETSI][0][102] = 127,
+ [0][1][2][1][RTW89_MKK][1][102] = 127,
+ [0][1][2][1][RTW89_MKK][0][102] = 127,
+ [0][1][2][1][RTW89_IC][1][102] = -2,
+ [0][1][2][1][RTW89_KCC][1][102] = 20,
+ [0][1][2][1][RTW89_KCC][0][102] = 127,
+ [0][1][2][1][RTW89_ACMA][1][102] = 127,
+ [0][1][2][1][RTW89_ACMA][0][102] = 127,
+ [0][1][2][1][RTW89_CHILE][1][102] = -2,
+ [0][1][2][1][RTW89_QATAR][1][102] = 127,
+ [0][1][2][1][RTW89_QATAR][0][102] = 127,
+ [0][1][2][1][RTW89_UK][1][102] = 127,
+ [0][1][2][1][RTW89_UK][0][102] = 127,
+ [0][1][2][1][RTW89_FCC][1][104] = -2,
+ [0][1][2][1][RTW89_FCC][2][104] = 127,
+ [0][1][2][1][RTW89_ETSI][1][104] = 127,
+ [0][1][2][1][RTW89_ETSI][0][104] = 127,
+ [0][1][2][1][RTW89_MKK][1][104] = 127,
+ [0][1][2][1][RTW89_MKK][0][104] = 127,
+ [0][1][2][1][RTW89_IC][1][104] = -2,
+ [0][1][2][1][RTW89_KCC][1][104] = 20,
+ [0][1][2][1][RTW89_KCC][0][104] = 127,
+ [0][1][2][1][RTW89_ACMA][1][104] = 127,
+ [0][1][2][1][RTW89_ACMA][0][104] = 127,
+ [0][1][2][1][RTW89_CHILE][1][104] = -2,
+ [0][1][2][1][RTW89_QATAR][1][104] = 127,
+ [0][1][2][1][RTW89_QATAR][0][104] = 127,
+ [0][1][2][1][RTW89_UK][1][104] = 127,
+ [0][1][2][1][RTW89_UK][0][104] = 127,
+ [0][1][2][1][RTW89_FCC][1][105] = -2,
+ [0][1][2][1][RTW89_FCC][2][105] = 127,
+ [0][1][2][1][RTW89_ETSI][1][105] = 127,
+ [0][1][2][1][RTW89_ETSI][0][105] = 127,
+ [0][1][2][1][RTW89_MKK][1][105] = 127,
+ [0][1][2][1][RTW89_MKK][0][105] = 127,
+ [0][1][2][1][RTW89_IC][1][105] = -2,
+ [0][1][2][1][RTW89_KCC][1][105] = 20,
+ [0][1][2][1][RTW89_KCC][0][105] = 127,
+ [0][1][2][1][RTW89_ACMA][1][105] = 127,
+ [0][1][2][1][RTW89_ACMA][0][105] = 127,
+ [0][1][2][1][RTW89_CHILE][1][105] = -2,
+ [0][1][2][1][RTW89_QATAR][1][105] = 127,
+ [0][1][2][1][RTW89_QATAR][0][105] = 127,
+ [0][1][2][1][RTW89_UK][1][105] = 127,
+ [0][1][2][1][RTW89_UK][0][105] = 127,
+ [0][1][2][1][RTW89_FCC][1][107] = 1,
+ [0][1][2][1][RTW89_FCC][2][107] = 127,
+ [0][1][2][1][RTW89_ETSI][1][107] = 127,
+ [0][1][2][1][RTW89_ETSI][0][107] = 127,
+ [0][1][2][1][RTW89_MKK][1][107] = 127,
+ [0][1][2][1][RTW89_MKK][0][107] = 127,
+ [0][1][2][1][RTW89_IC][1][107] = 1,
+ [0][1][2][1][RTW89_KCC][1][107] = 20,
+ [0][1][2][1][RTW89_KCC][0][107] = 127,
+ [0][1][2][1][RTW89_ACMA][1][107] = 127,
+ [0][1][2][1][RTW89_ACMA][0][107] = 127,
+ [0][1][2][1][RTW89_CHILE][1][107] = 1,
+ [0][1][2][1][RTW89_QATAR][1][107] = 127,
+ [0][1][2][1][RTW89_QATAR][0][107] = 127,
+ [0][1][2][1][RTW89_UK][1][107] = 127,
+ [0][1][2][1][RTW89_UK][0][107] = 127,
+ [0][1][2][1][RTW89_FCC][1][109] = 1,
+ [0][1][2][1][RTW89_FCC][2][109] = 127,
+ [0][1][2][1][RTW89_ETSI][1][109] = 127,
+ [0][1][2][1][RTW89_ETSI][0][109] = 127,
+ [0][1][2][1][RTW89_MKK][1][109] = 127,
+ [0][1][2][1][RTW89_MKK][0][109] = 127,
+ [0][1][2][1][RTW89_IC][1][109] = 1,
+ [0][1][2][1][RTW89_KCC][1][109] = 20,
+ [0][1][2][1][RTW89_KCC][0][109] = 127,
+ [0][1][2][1][RTW89_ACMA][1][109] = 127,
+ [0][1][2][1][RTW89_ACMA][0][109] = 127,
+ [0][1][2][1][RTW89_CHILE][1][109] = 1,
+ [0][1][2][1][RTW89_QATAR][1][109] = 127,
+ [0][1][2][1][RTW89_QATAR][0][109] = 127,
+ [0][1][2][1][RTW89_UK][1][109] = 127,
+ [0][1][2][1][RTW89_UK][0][109] = 127,
+ [0][1][2][1][RTW89_FCC][1][111] = 127,
+ [0][1][2][1][RTW89_FCC][2][111] = 127,
+ [0][1][2][1][RTW89_ETSI][1][111] = 127,
+ [0][1][2][1][RTW89_ETSI][0][111] = 127,
+ [0][1][2][1][RTW89_MKK][1][111] = 127,
+ [0][1][2][1][RTW89_MKK][0][111] = 127,
+ [0][1][2][1][RTW89_IC][1][111] = 127,
+ [0][1][2][1][RTW89_KCC][1][111] = 127,
+ [0][1][2][1][RTW89_KCC][0][111] = 127,
+ [0][1][2][1][RTW89_ACMA][1][111] = 127,
+ [0][1][2][1][RTW89_ACMA][0][111] = 127,
+ [0][1][2][1][RTW89_CHILE][1][111] = 127,
+ [0][1][2][1][RTW89_QATAR][1][111] = 127,
+ [0][1][2][1][RTW89_QATAR][0][111] = 127,
+ [0][1][2][1][RTW89_UK][1][111] = 127,
+ [0][1][2][1][RTW89_UK][0][111] = 127,
+ [0][1][2][1][RTW89_FCC][1][113] = 127,
+ [0][1][2][1][RTW89_FCC][2][113] = 127,
+ [0][1][2][1][RTW89_ETSI][1][113] = 127,
+ [0][1][2][1][RTW89_ETSI][0][113] = 127,
+ [0][1][2][1][RTW89_MKK][1][113] = 127,
+ [0][1][2][1][RTW89_MKK][0][113] = 127,
+ [0][1][2][1][RTW89_IC][1][113] = 127,
+ [0][1][2][1][RTW89_KCC][1][113] = 127,
+ [0][1][2][1][RTW89_KCC][0][113] = 127,
+ [0][1][2][1][RTW89_ACMA][1][113] = 127,
+ [0][1][2][1][RTW89_ACMA][0][113] = 127,
+ [0][1][2][1][RTW89_CHILE][1][113] = 127,
+ [0][1][2][1][RTW89_QATAR][1][113] = 127,
+ [0][1][2][1][RTW89_QATAR][0][113] = 127,
+ [0][1][2][1][RTW89_UK][1][113] = 127,
+ [0][1][2][1][RTW89_UK][0][113] = 127,
+ [0][1][2][1][RTW89_FCC][1][115] = 127,
+ [0][1][2][1][RTW89_FCC][2][115] = 127,
+ [0][1][2][1][RTW89_ETSI][1][115] = 127,
+ [0][1][2][1][RTW89_ETSI][0][115] = 127,
+ [0][1][2][1][RTW89_MKK][1][115] = 127,
+ [0][1][2][1][RTW89_MKK][0][115] = 127,
+ [0][1][2][1][RTW89_IC][1][115] = 127,
+ [0][1][2][1][RTW89_KCC][1][115] = 127,
+ [0][1][2][1][RTW89_KCC][0][115] = 127,
+ [0][1][2][1][RTW89_ACMA][1][115] = 127,
+ [0][1][2][1][RTW89_ACMA][0][115] = 127,
+ [0][1][2][1][RTW89_CHILE][1][115] = 127,
+ [0][1][2][1][RTW89_QATAR][1][115] = 127,
+ [0][1][2][1][RTW89_QATAR][0][115] = 127,
+ [0][1][2][1][RTW89_UK][1][115] = 127,
+ [0][1][2][1][RTW89_UK][0][115] = 127,
+ [0][1][2][1][RTW89_FCC][1][117] = 127,
+ [0][1][2][1][RTW89_FCC][2][117] = 127,
+ [0][1][2][1][RTW89_ETSI][1][117] = 127,
+ [0][1][2][1][RTW89_ETSI][0][117] = 127,
+ [0][1][2][1][RTW89_MKK][1][117] = 127,
+ [0][1][2][1][RTW89_MKK][0][117] = 127,
+ [0][1][2][1][RTW89_IC][1][117] = 127,
+ [0][1][2][1][RTW89_KCC][1][117] = 127,
+ [0][1][2][1][RTW89_KCC][0][117] = 127,
+ [0][1][2][1][RTW89_ACMA][1][117] = 127,
+ [0][1][2][1][RTW89_ACMA][0][117] = 127,
+ [0][1][2][1][RTW89_CHILE][1][117] = 127,
+ [0][1][2][1][RTW89_QATAR][1][117] = 127,
+ [0][1][2][1][RTW89_QATAR][0][117] = 127,
+ [0][1][2][1][RTW89_UK][1][117] = 127,
+ [0][1][2][1][RTW89_UK][0][117] = 127,
+ [0][1][2][1][RTW89_FCC][1][119] = 127,
+ [0][1][2][1][RTW89_FCC][2][119] = 127,
+ [0][1][2][1][RTW89_ETSI][1][119] = 127,
+ [0][1][2][1][RTW89_ETSI][0][119] = 127,
+ [0][1][2][1][RTW89_MKK][1][119] = 127,
+ [0][1][2][1][RTW89_MKK][0][119] = 127,
+ [0][1][2][1][RTW89_IC][1][119] = 127,
+ [0][1][2][1][RTW89_KCC][1][119] = 127,
+ [0][1][2][1][RTW89_KCC][0][119] = 127,
+ [0][1][2][1][RTW89_ACMA][1][119] = 127,
+ [0][1][2][1][RTW89_ACMA][0][119] = 127,
+ [0][1][2][1][RTW89_CHILE][1][119] = 127,
+ [0][1][2][1][RTW89_QATAR][1][119] = 127,
+ [0][1][2][1][RTW89_QATAR][0][119] = 127,
+ [0][1][2][1][RTW89_UK][1][119] = 127,
+ [0][1][2][1][RTW89_UK][0][119] = 127,
+ [1][0][2][0][RTW89_FCC][1][1] = 34,
+ [1][0][2][0][RTW89_FCC][2][1] = 70,
+ [1][0][2][0][RTW89_ETSI][1][1] = 66,
+ [1][0][2][0][RTW89_ETSI][0][1] = 30,
+ [1][0][2][0][RTW89_MKK][1][1] = 62,
+ [1][0][2][0][RTW89_MKK][0][1] = 26,
+ [1][0][2][0][RTW89_IC][1][1] = 34,
+ [1][0][2][0][RTW89_KCC][1][1] = 40,
+ [1][0][2][0][RTW89_KCC][0][1] = 24,
+ [1][0][2][0][RTW89_ACMA][1][1] = 66,
+ [1][0][2][0][RTW89_ACMA][0][1] = 30,
+ [1][0][2][0][RTW89_CHILE][1][1] = 34,
+ [1][0][2][0][RTW89_QATAR][1][1] = 66,
+ [1][0][2][0][RTW89_QATAR][0][1] = 30,
+ [1][0][2][0][RTW89_UK][1][1] = 66,
+ [1][0][2][0][RTW89_UK][0][1] = 30,
+ [1][0][2][0][RTW89_FCC][1][5] = 34,
+ [1][0][2][0][RTW89_FCC][2][5] = 70,
+ [1][0][2][0][RTW89_ETSI][1][5] = 66,
+ [1][0][2][0][RTW89_ETSI][0][5] = 30,
+ [1][0][2][0][RTW89_MKK][1][5] = 62,
+ [1][0][2][0][RTW89_MKK][0][5] = 26,
+ [1][0][2][0][RTW89_IC][1][5] = 34,
+ [1][0][2][0][RTW89_KCC][1][5] = 40,
+ [1][0][2][0][RTW89_KCC][0][5] = 24,
+ [1][0][2][0][RTW89_ACMA][1][5] = 66,
+ [1][0][2][0][RTW89_ACMA][0][5] = 30,
+ [1][0][2][0][RTW89_CHILE][1][5] = 34,
+ [1][0][2][0][RTW89_QATAR][1][5] = 66,
+ [1][0][2][0][RTW89_QATAR][0][5] = 30,
+ [1][0][2][0][RTW89_UK][1][5] = 66,
+ [1][0][2][0][RTW89_UK][0][5] = 30,
+ [1][0][2][0][RTW89_FCC][1][9] = 34,
+ [1][0][2][0][RTW89_FCC][2][9] = 70,
+ [1][0][2][0][RTW89_ETSI][1][9] = 66,
+ [1][0][2][0][RTW89_ETSI][0][9] = 30,
+ [1][0][2][0][RTW89_MKK][1][9] = 62,
+ [1][0][2][0][RTW89_MKK][0][9] = 26,
+ [1][0][2][0][RTW89_IC][1][9] = 34,
+ [1][0][2][0][RTW89_KCC][1][9] = 40,
+ [1][0][2][0][RTW89_KCC][0][9] = 24,
+ [1][0][2][0][RTW89_ACMA][1][9] = 66,
+ [1][0][2][0][RTW89_ACMA][0][9] = 30,
+ [1][0][2][0][RTW89_CHILE][1][9] = 34,
+ [1][0][2][0][RTW89_QATAR][1][9] = 66,
+ [1][0][2][0][RTW89_QATAR][0][9] = 30,
+ [1][0][2][0][RTW89_UK][1][9] = 66,
+ [1][0][2][0][RTW89_UK][0][9] = 30,
+ [1][0][2][0][RTW89_FCC][1][13] = 34,
+ [1][0][2][0][RTW89_FCC][2][13] = 70,
+ [1][0][2][0][RTW89_ETSI][1][13] = 66,
+ [1][0][2][0][RTW89_ETSI][0][13] = 30,
+ [1][0][2][0][RTW89_MKK][1][13] = 62,
+ [1][0][2][0][RTW89_MKK][0][13] = 26,
+ [1][0][2][0][RTW89_IC][1][13] = 34,
+ [1][0][2][0][RTW89_KCC][1][13] = 40,
+ [1][0][2][0][RTW89_KCC][0][13] = 24,
+ [1][0][2][0][RTW89_ACMA][1][13] = 66,
+ [1][0][2][0][RTW89_ACMA][0][13] = 30,
+ [1][0][2][0][RTW89_CHILE][1][13] = 34,
+ [1][0][2][0][RTW89_QATAR][1][13] = 66,
+ [1][0][2][0][RTW89_QATAR][0][13] = 30,
+ [1][0][2][0][RTW89_UK][1][13] = 66,
+ [1][0][2][0][RTW89_UK][0][13] = 30,
+ [1][0][2][0][RTW89_FCC][1][16] = 34,
+ [1][0][2][0][RTW89_FCC][2][16] = 70,
+ [1][0][2][0][RTW89_ETSI][1][16] = 66,
+ [1][0][2][0][RTW89_ETSI][0][16] = 30,
+ [1][0][2][0][RTW89_MKK][1][16] = 62,
+ [1][0][2][0][RTW89_MKK][0][16] = 26,
+ [1][0][2][0][RTW89_IC][1][16] = 34,
+ [1][0][2][0][RTW89_KCC][1][16] = 40,
+ [1][0][2][0][RTW89_KCC][0][16] = 24,
+ [1][0][2][0][RTW89_ACMA][1][16] = 66,
+ [1][0][2][0][RTW89_ACMA][0][16] = 30,
+ [1][0][2][0][RTW89_CHILE][1][16] = 34,
+ [1][0][2][0][RTW89_QATAR][1][16] = 66,
+ [1][0][2][0][RTW89_QATAR][0][16] = 30,
+ [1][0][2][0][RTW89_UK][1][16] = 66,
+ [1][0][2][0][RTW89_UK][0][16] = 30,
+ [1][0][2][0][RTW89_FCC][1][20] = 34,
+ [1][0][2][0][RTW89_FCC][2][20] = 70,
+ [1][0][2][0][RTW89_ETSI][1][20] = 66,
+ [1][0][2][0][RTW89_ETSI][0][20] = 30,
+ [1][0][2][0][RTW89_MKK][1][20] = 62,
+ [1][0][2][0][RTW89_MKK][0][20] = 26,
+ [1][0][2][0][RTW89_IC][1][20] = 34,
+ [1][0][2][0][RTW89_KCC][1][20] = 40,
+ [1][0][2][0][RTW89_KCC][0][20] = 24,
+ [1][0][2][0][RTW89_ACMA][1][20] = 66,
+ [1][0][2][0][RTW89_ACMA][0][20] = 30,
+ [1][0][2][0][RTW89_CHILE][1][20] = 34,
+ [1][0][2][0][RTW89_QATAR][1][20] = 66,
+ [1][0][2][0][RTW89_QATAR][0][20] = 30,
+ [1][0][2][0][RTW89_UK][1][20] = 66,
+ [1][0][2][0][RTW89_UK][0][20] = 30,
+ [1][0][2][0][RTW89_FCC][1][24] = 36,
+ [1][0][2][0][RTW89_FCC][2][24] = 70,
+ [1][0][2][0][RTW89_ETSI][1][24] = 66,
+ [1][0][2][0][RTW89_ETSI][0][24] = 30,
+ [1][0][2][0][RTW89_MKK][1][24] = 64,
+ [1][0][2][0][RTW89_MKK][0][24] = 28,
+ [1][0][2][0][RTW89_IC][1][24] = 36,
+ [1][0][2][0][RTW89_KCC][1][24] = 40,
+ [1][0][2][0][RTW89_KCC][0][24] = 26,
+ [1][0][2][0][RTW89_ACMA][1][24] = 66,
+ [1][0][2][0][RTW89_ACMA][0][24] = 30,
+ [1][0][2][0][RTW89_CHILE][1][24] = 36,
+ [1][0][2][0][RTW89_QATAR][1][24] = 66,
+ [1][0][2][0][RTW89_QATAR][0][24] = 30,
+ [1][0][2][0][RTW89_UK][1][24] = 66,
+ [1][0][2][0][RTW89_UK][0][24] = 30,
+ [1][0][2][0][RTW89_FCC][1][28] = 34,
+ [1][0][2][0][RTW89_FCC][2][28] = 70,
+ [1][0][2][0][RTW89_ETSI][1][28] = 66,
+ [1][0][2][0][RTW89_ETSI][0][28] = 30,
+ [1][0][2][0][RTW89_MKK][1][28] = 64,
+ [1][0][2][0][RTW89_MKK][0][28] = 26,
+ [1][0][2][0][RTW89_IC][1][28] = 34,
+ [1][0][2][0][RTW89_KCC][1][28] = 40,
+ [1][0][2][0][RTW89_KCC][0][28] = 26,
+ [1][0][2][0][RTW89_ACMA][1][28] = 66,
+ [1][0][2][0][RTW89_ACMA][0][28] = 30,
+ [1][0][2][0][RTW89_CHILE][1][28] = 34,
+ [1][0][2][0][RTW89_QATAR][1][28] = 66,
+ [1][0][2][0][RTW89_QATAR][0][28] = 30,
+ [1][0][2][0][RTW89_UK][1][28] = 66,
+ [1][0][2][0][RTW89_UK][0][28] = 30,
+ [1][0][2][0][RTW89_FCC][1][31] = 34,
+ [1][0][2][0][RTW89_FCC][2][31] = 70,
+ [1][0][2][0][RTW89_ETSI][1][31] = 66,
+ [1][0][2][0][RTW89_ETSI][0][31] = 30,
+ [1][0][2][0][RTW89_MKK][1][31] = 64,
+ [1][0][2][0][RTW89_MKK][0][31] = 26,
+ [1][0][2][0][RTW89_IC][1][31] = 34,
+ [1][0][2][0][RTW89_KCC][1][31] = 40,
+ [1][0][2][0][RTW89_KCC][0][31] = 26,
+ [1][0][2][0][RTW89_ACMA][1][31] = 66,
+ [1][0][2][0][RTW89_ACMA][0][31] = 30,
+ [1][0][2][0][RTW89_CHILE][1][31] = 34,
+ [1][0][2][0][RTW89_QATAR][1][31] = 66,
+ [1][0][2][0][RTW89_QATAR][0][31] = 30,
+ [1][0][2][0][RTW89_UK][1][31] = 66,
+ [1][0][2][0][RTW89_UK][0][31] = 30,
+ [1][0][2][0][RTW89_FCC][1][35] = 34,
+ [1][0][2][0][RTW89_FCC][2][35] = 70,
+ [1][0][2][0][RTW89_ETSI][1][35] = 66,
+ [1][0][2][0][RTW89_ETSI][0][35] = 30,
+ [1][0][2][0][RTW89_MKK][1][35] = 64,
+ [1][0][2][0][RTW89_MKK][0][35] = 26,
+ [1][0][2][0][RTW89_IC][1][35] = 34,
+ [1][0][2][0][RTW89_KCC][1][35] = 40,
+ [1][0][2][0][RTW89_KCC][0][35] = 26,
+ [1][0][2][0][RTW89_ACMA][1][35] = 66,
+ [1][0][2][0][RTW89_ACMA][0][35] = 30,
+ [1][0][2][0][RTW89_CHILE][1][35] = 34,
+ [1][0][2][0][RTW89_QATAR][1][35] = 66,
+ [1][0][2][0][RTW89_QATAR][0][35] = 30,
+ [1][0][2][0][RTW89_UK][1][35] = 66,
+ [1][0][2][0][RTW89_UK][0][35] = 30,
+ [1][0][2][0][RTW89_FCC][1][39] = 34,
+ [1][0][2][0][RTW89_FCC][2][39] = 70,
+ [1][0][2][0][RTW89_ETSI][1][39] = 66,
+ [1][0][2][0][RTW89_ETSI][0][39] = 30,
+ [1][0][2][0][RTW89_MKK][1][39] = 64,
+ [1][0][2][0][RTW89_MKK][0][39] = 26,
+ [1][0][2][0][RTW89_IC][1][39] = 34,
+ [1][0][2][0][RTW89_KCC][1][39] = 40,
+ [1][0][2][0][RTW89_KCC][0][39] = 26,
+ [1][0][2][0][RTW89_ACMA][1][39] = 66,
+ [1][0][2][0][RTW89_ACMA][0][39] = 30,
+ [1][0][2][0][RTW89_CHILE][1][39] = 34,
+ [1][0][2][0][RTW89_QATAR][1][39] = 66,
+ [1][0][2][0][RTW89_QATAR][0][39] = 30,
+ [1][0][2][0][RTW89_UK][1][39] = 66,
+ [1][0][2][0][RTW89_UK][0][39] = 30,
+ [1][0][2][0][RTW89_FCC][1][43] = 34,
+ [1][0][2][0][RTW89_FCC][2][43] = 70,
+ [1][0][2][0][RTW89_ETSI][1][43] = 66,
+ [1][0][2][0][RTW89_ETSI][0][43] = 30,
+ [1][0][2][0][RTW89_MKK][1][43] = 64,
+ [1][0][2][0][RTW89_MKK][0][43] = 26,
+ [1][0][2][0][RTW89_IC][1][43] = 34,
+ [1][0][2][0][RTW89_KCC][1][43] = 40,
+ [1][0][2][0][RTW89_KCC][0][43] = 26,
+ [1][0][2][0][RTW89_ACMA][1][43] = 66,
+ [1][0][2][0][RTW89_ACMA][0][43] = 30,
+ [1][0][2][0][RTW89_CHILE][1][43] = 34,
+ [1][0][2][0][RTW89_QATAR][1][43] = 66,
+ [1][0][2][0][RTW89_QATAR][0][43] = 30,
+ [1][0][2][0][RTW89_UK][1][43] = 66,
+ [1][0][2][0][RTW89_UK][0][43] = 30,
+ [1][0][2][0][RTW89_FCC][1][46] = 34,
+ [1][0][2][0][RTW89_FCC][2][46] = 127,
+ [1][0][2][0][RTW89_ETSI][1][46] = 127,
+ [1][0][2][0][RTW89_ETSI][0][46] = 127,
+ [1][0][2][0][RTW89_MKK][1][46] = 127,
+ [1][0][2][0][RTW89_MKK][0][46] = 127,
+ [1][0][2][0][RTW89_IC][1][46] = 34,
+ [1][0][2][0][RTW89_KCC][1][46] = 40,
+ [1][0][2][0][RTW89_KCC][0][46] = 127,
+ [1][0][2][0][RTW89_ACMA][1][46] = 127,
+ [1][0][2][0][RTW89_ACMA][0][46] = 127,
+ [1][0][2][0][RTW89_CHILE][1][46] = 34,
+ [1][0][2][0][RTW89_QATAR][1][46] = 127,
+ [1][0][2][0][RTW89_QATAR][0][46] = 127,
+ [1][0][2][0][RTW89_UK][1][46] = 127,
+ [1][0][2][0][RTW89_UK][0][46] = 127,
+ [1][0][2][0][RTW89_FCC][1][50] = 34,
+ [1][0][2][0][RTW89_FCC][2][50] = 127,
+ [1][0][2][0][RTW89_ETSI][1][50] = 127,
+ [1][0][2][0][RTW89_ETSI][0][50] = 127,
+ [1][0][2][0][RTW89_MKK][1][50] = 127,
+ [1][0][2][0][RTW89_MKK][0][50] = 127,
+ [1][0][2][0][RTW89_IC][1][50] = 34,
+ [1][0][2][0][RTW89_KCC][1][50] = 40,
+ [1][0][2][0][RTW89_KCC][0][50] = 127,
+ [1][0][2][0][RTW89_ACMA][1][50] = 127,
+ [1][0][2][0][RTW89_ACMA][0][50] = 127,
+ [1][0][2][0][RTW89_CHILE][1][50] = 34,
+ [1][0][2][0][RTW89_QATAR][1][50] = 127,
+ [1][0][2][0][RTW89_QATAR][0][50] = 127,
+ [1][0][2][0][RTW89_UK][1][50] = 127,
+ [1][0][2][0][RTW89_UK][0][50] = 127,
+ [1][0][2][0][RTW89_FCC][1][54] = 36,
+ [1][0][2][0][RTW89_FCC][2][54] = 127,
+ [1][0][2][0][RTW89_ETSI][1][54] = 127,
+ [1][0][2][0][RTW89_ETSI][0][54] = 127,
+ [1][0][2][0][RTW89_MKK][1][54] = 127,
+ [1][0][2][0][RTW89_MKK][0][54] = 127,
+ [1][0][2][0][RTW89_IC][1][54] = 36,
+ [1][0][2][0][RTW89_KCC][1][54] = 40,
+ [1][0][2][0][RTW89_KCC][0][54] = 127,
+ [1][0][2][0][RTW89_ACMA][1][54] = 127,
+ [1][0][2][0][RTW89_ACMA][0][54] = 127,
+ [1][0][2][0][RTW89_CHILE][1][54] = 36,
+ [1][0][2][0][RTW89_QATAR][1][54] = 127,
+ [1][0][2][0][RTW89_QATAR][0][54] = 127,
+ [1][0][2][0][RTW89_UK][1][54] = 127,
+ [1][0][2][0][RTW89_UK][0][54] = 127,
+ [1][0][2][0][RTW89_FCC][1][58] = 36,
+ [1][0][2][0][RTW89_FCC][2][58] = 66,
+ [1][0][2][0][RTW89_ETSI][1][58] = 127,
+ [1][0][2][0][RTW89_ETSI][0][58] = 127,
+ [1][0][2][0][RTW89_MKK][1][58] = 127,
+ [1][0][2][0][RTW89_MKK][0][58] = 127,
+ [1][0][2][0][RTW89_IC][1][58] = 36,
+ [1][0][2][0][RTW89_KCC][1][58] = 40,
+ [1][0][2][0][RTW89_KCC][0][58] = 127,
+ [1][0][2][0][RTW89_ACMA][1][58] = 127,
+ [1][0][2][0][RTW89_ACMA][0][58] = 127,
+ [1][0][2][0][RTW89_CHILE][1][58] = 36,
+ [1][0][2][0][RTW89_QATAR][1][58] = 127,
+ [1][0][2][0][RTW89_QATAR][0][58] = 127,
+ [1][0][2][0][RTW89_UK][1][58] = 127,
+ [1][0][2][0][RTW89_UK][0][58] = 127,
+ [1][0][2][0][RTW89_FCC][1][61] = 34,
+ [1][0][2][0][RTW89_FCC][2][61] = 66,
+ [1][0][2][0][RTW89_ETSI][1][61] = 127,
+ [1][0][2][0][RTW89_ETSI][0][61] = 127,
+ [1][0][2][0][RTW89_MKK][1][61] = 127,
+ [1][0][2][0][RTW89_MKK][0][61] = 127,
+ [1][0][2][0][RTW89_IC][1][61] = 34,
+ [1][0][2][0][RTW89_KCC][1][61] = 40,
+ [1][0][2][0][RTW89_KCC][0][61] = 127,
+ [1][0][2][0][RTW89_ACMA][1][61] = 127,
+ [1][0][2][0][RTW89_ACMA][0][61] = 127,
+ [1][0][2][0][RTW89_CHILE][1][61] = 34,
+ [1][0][2][0][RTW89_QATAR][1][61] = 127,
+ [1][0][2][0][RTW89_QATAR][0][61] = 127,
+ [1][0][2][0][RTW89_UK][1][61] = 127,
+ [1][0][2][0][RTW89_UK][0][61] = 127,
+ [1][0][2][0][RTW89_FCC][1][65] = 34,
+ [1][0][2][0][RTW89_FCC][2][65] = 66,
+ [1][0][2][0][RTW89_ETSI][1][65] = 127,
+ [1][0][2][0][RTW89_ETSI][0][65] = 127,
+ [1][0][2][0][RTW89_MKK][1][65] = 127,
+ [1][0][2][0][RTW89_MKK][0][65] = 127,
+ [1][0][2][0][RTW89_IC][1][65] = 34,
+ [1][0][2][0][RTW89_KCC][1][65] = 40,
+ [1][0][2][0][RTW89_KCC][0][65] = 127,
+ [1][0][2][0][RTW89_ACMA][1][65] = 127,
+ [1][0][2][0][RTW89_ACMA][0][65] = 127,
+ [1][0][2][0][RTW89_CHILE][1][65] = 34,
+ [1][0][2][0][RTW89_QATAR][1][65] = 127,
+ [1][0][2][0][RTW89_QATAR][0][65] = 127,
+ [1][0][2][0][RTW89_UK][1][65] = 127,
+ [1][0][2][0][RTW89_UK][0][65] = 127,
+ [1][0][2][0][RTW89_FCC][1][69] = 34,
+ [1][0][2][0][RTW89_FCC][2][69] = 66,
+ [1][0][2][0][RTW89_ETSI][1][69] = 127,
+ [1][0][2][0][RTW89_ETSI][0][69] = 127,
+ [1][0][2][0][RTW89_MKK][1][69] = 127,
+ [1][0][2][0][RTW89_MKK][0][69] = 127,
+ [1][0][2][0][RTW89_IC][1][69] = 34,
+ [1][0][2][0][RTW89_KCC][1][69] = 40,
+ [1][0][2][0][RTW89_KCC][0][69] = 127,
+ [1][0][2][0][RTW89_ACMA][1][69] = 127,
+ [1][0][2][0][RTW89_ACMA][0][69] = 127,
+ [1][0][2][0][RTW89_CHILE][1][69] = 34,
+ [1][0][2][0][RTW89_QATAR][1][69] = 127,
+ [1][0][2][0][RTW89_QATAR][0][69] = 127,
+ [1][0][2][0][RTW89_UK][1][69] = 127,
+ [1][0][2][0][RTW89_UK][0][69] = 127,
+ [1][0][2][0][RTW89_FCC][1][73] = 34,
+ [1][0][2][0][RTW89_FCC][2][73] = 66,
+ [1][0][2][0][RTW89_ETSI][1][73] = 127,
+ [1][0][2][0][RTW89_ETSI][0][73] = 127,
+ [1][0][2][0][RTW89_MKK][1][73] = 127,
+ [1][0][2][0][RTW89_MKK][0][73] = 127,
+ [1][0][2][0][RTW89_IC][1][73] = 34,
+ [1][0][2][0][RTW89_KCC][1][73] = 40,
+ [1][0][2][0][RTW89_KCC][0][73] = 127,
+ [1][0][2][0][RTW89_ACMA][1][73] = 127,
+ [1][0][2][0][RTW89_ACMA][0][73] = 127,
+ [1][0][2][0][RTW89_CHILE][1][73] = 34,
+ [1][0][2][0][RTW89_QATAR][1][73] = 127,
+ [1][0][2][0][RTW89_QATAR][0][73] = 127,
+ [1][0][2][0][RTW89_UK][1][73] = 127,
+ [1][0][2][0][RTW89_UK][0][73] = 127,
+ [1][0][2][0][RTW89_FCC][1][76] = 34,
+ [1][0][2][0][RTW89_FCC][2][76] = 66,
+ [1][0][2][0][RTW89_ETSI][1][76] = 127,
+ [1][0][2][0][RTW89_ETSI][0][76] = 127,
+ [1][0][2][0][RTW89_MKK][1][76] = 127,
+ [1][0][2][0][RTW89_MKK][0][76] = 127,
+ [1][0][2][0][RTW89_IC][1][76] = 34,
+ [1][0][2][0][RTW89_KCC][1][76] = 40,
+ [1][0][2][0][RTW89_KCC][0][76] = 127,
+ [1][0][2][0][RTW89_ACMA][1][76] = 127,
+ [1][0][2][0][RTW89_ACMA][0][76] = 127,
+ [1][0][2][0][RTW89_CHILE][1][76] = 34,
+ [1][0][2][0][RTW89_QATAR][1][76] = 127,
+ [1][0][2][0][RTW89_QATAR][0][76] = 127,
+ [1][0][2][0][RTW89_UK][1][76] = 127,
+ [1][0][2][0][RTW89_UK][0][76] = 127,
+ [1][0][2][0][RTW89_FCC][1][80] = 34,
+ [1][0][2][0][RTW89_FCC][2][80] = 66,
+ [1][0][2][0][RTW89_ETSI][1][80] = 127,
+ [1][0][2][0][RTW89_ETSI][0][80] = 127,
+ [1][0][2][0][RTW89_MKK][1][80] = 127,
+ [1][0][2][0][RTW89_MKK][0][80] = 127,
+ [1][0][2][0][RTW89_IC][1][80] = 34,
+ [1][0][2][0][RTW89_KCC][1][80] = 42,
+ [1][0][2][0][RTW89_KCC][0][80] = 127,
+ [1][0][2][0][RTW89_ACMA][1][80] = 127,
+ [1][0][2][0][RTW89_ACMA][0][80] = 127,
+ [1][0][2][0][RTW89_CHILE][1][80] = 34,
+ [1][0][2][0][RTW89_QATAR][1][80] = 127,
+ [1][0][2][0][RTW89_QATAR][0][80] = 127,
+ [1][0][2][0][RTW89_UK][1][80] = 127,
+ [1][0][2][0][RTW89_UK][0][80] = 127,
+ [1][0][2][0][RTW89_FCC][1][84] = 34,
+ [1][0][2][0][RTW89_FCC][2][84] = 66,
+ [1][0][2][0][RTW89_ETSI][1][84] = 127,
+ [1][0][2][0][RTW89_ETSI][0][84] = 127,
+ [1][0][2][0][RTW89_MKK][1][84] = 127,
+ [1][0][2][0][RTW89_MKK][0][84] = 127,
+ [1][0][2][0][RTW89_IC][1][84] = 34,
+ [1][0][2][0][RTW89_KCC][1][84] = 42,
+ [1][0][2][0][RTW89_KCC][0][84] = 127,
+ [1][0][2][0][RTW89_ACMA][1][84] = 127,
+ [1][0][2][0][RTW89_ACMA][0][84] = 127,
+ [1][0][2][0][RTW89_CHILE][1][84] = 34,
+ [1][0][2][0][RTW89_QATAR][1][84] = 127,
+ [1][0][2][0][RTW89_QATAR][0][84] = 127,
+ [1][0][2][0][RTW89_UK][1][84] = 127,
+ [1][0][2][0][RTW89_UK][0][84] = 127,
+ [1][0][2][0][RTW89_FCC][1][88] = 34,
+ [1][0][2][0][RTW89_FCC][2][88] = 127,
+ [1][0][2][0][RTW89_ETSI][1][88] = 127,
+ [1][0][2][0][RTW89_ETSI][0][88] = 127,
+ [1][0][2][0][RTW89_MKK][1][88] = 127,
+ [1][0][2][0][RTW89_MKK][0][88] = 127,
+ [1][0][2][0][RTW89_IC][1][88] = 34,
+ [1][0][2][0][RTW89_KCC][1][88] = 42,
+ [1][0][2][0][RTW89_KCC][0][88] = 127,
+ [1][0][2][0][RTW89_ACMA][1][88] = 127,
+ [1][0][2][0][RTW89_ACMA][0][88] = 127,
+ [1][0][2][0][RTW89_CHILE][1][88] = 34,
+ [1][0][2][0][RTW89_QATAR][1][88] = 127,
+ [1][0][2][0][RTW89_QATAR][0][88] = 127,
+ [1][0][2][0][RTW89_UK][1][88] = 127,
+ [1][0][2][0][RTW89_UK][0][88] = 127,
+ [1][0][2][0][RTW89_FCC][1][91] = 36,
+ [1][0][2][0][RTW89_FCC][2][91] = 127,
+ [1][0][2][0][RTW89_ETSI][1][91] = 127,
+ [1][0][2][0][RTW89_ETSI][0][91] = 127,
+ [1][0][2][0][RTW89_MKK][1][91] = 127,
+ [1][0][2][0][RTW89_MKK][0][91] = 127,
+ [1][0][2][0][RTW89_IC][1][91] = 36,
+ [1][0][2][0][RTW89_KCC][1][91] = 42,
+ [1][0][2][0][RTW89_KCC][0][91] = 127,
+ [1][0][2][0][RTW89_ACMA][1][91] = 127,
+ [1][0][2][0][RTW89_ACMA][0][91] = 127,
+ [1][0][2][0][RTW89_CHILE][1][91] = 36,
+ [1][0][2][0][RTW89_QATAR][1][91] = 127,
+ [1][0][2][0][RTW89_QATAR][0][91] = 127,
+ [1][0][2][0][RTW89_UK][1][91] = 127,
+ [1][0][2][0][RTW89_UK][0][91] = 127,
+ [1][0][2][0][RTW89_FCC][1][95] = 34,
+ [1][0][2][0][RTW89_FCC][2][95] = 127,
+ [1][0][2][0][RTW89_ETSI][1][95] = 127,
+ [1][0][2][0][RTW89_ETSI][0][95] = 127,
+ [1][0][2][0][RTW89_MKK][1][95] = 127,
+ [1][0][2][0][RTW89_MKK][0][95] = 127,
+ [1][0][2][0][RTW89_IC][1][95] = 34,
+ [1][0][2][0][RTW89_KCC][1][95] = 42,
+ [1][0][2][0][RTW89_KCC][0][95] = 127,
+ [1][0][2][0][RTW89_ACMA][1][95] = 127,
+ [1][0][2][0][RTW89_ACMA][0][95] = 127,
+ [1][0][2][0][RTW89_CHILE][1][95] = 34,
+ [1][0][2][0][RTW89_QATAR][1][95] = 127,
+ [1][0][2][0][RTW89_QATAR][0][95] = 127,
+ [1][0][2][0][RTW89_UK][1][95] = 127,
+ [1][0][2][0][RTW89_UK][0][95] = 127,
+ [1][0][2][0][RTW89_FCC][1][99] = 34,
+ [1][0][2][0][RTW89_FCC][2][99] = 127,
+ [1][0][2][0][RTW89_ETSI][1][99] = 127,
+ [1][0][2][0][RTW89_ETSI][0][99] = 127,
+ [1][0][2][0][RTW89_MKK][1][99] = 127,
+ [1][0][2][0][RTW89_MKK][0][99] = 127,
+ [1][0][2][0][RTW89_IC][1][99] = 34,
+ [1][0][2][0][RTW89_KCC][1][99] = 42,
+ [1][0][2][0][RTW89_KCC][0][99] = 127,
+ [1][0][2][0][RTW89_ACMA][1][99] = 127,
+ [1][0][2][0][RTW89_ACMA][0][99] = 127,
+ [1][0][2][0][RTW89_CHILE][1][99] = 34,
+ [1][0][2][0][RTW89_QATAR][1][99] = 127,
+ [1][0][2][0][RTW89_QATAR][0][99] = 127,
+ [1][0][2][0][RTW89_UK][1][99] = 127,
+ [1][0][2][0][RTW89_UK][0][99] = 127,
+ [1][0][2][0][RTW89_FCC][1][103] = 34,
+ [1][0][2][0][RTW89_FCC][2][103] = 127,
+ [1][0][2][0][RTW89_ETSI][1][103] = 127,
+ [1][0][2][0][RTW89_ETSI][0][103] = 127,
+ [1][0][2][0][RTW89_MKK][1][103] = 127,
+ [1][0][2][0][RTW89_MKK][0][103] = 127,
+ [1][0][2][0][RTW89_IC][1][103] = 34,
+ [1][0][2][0][RTW89_KCC][1][103] = 42,
+ [1][0][2][0][RTW89_KCC][0][103] = 127,
+ [1][0][2][0][RTW89_ACMA][1][103] = 127,
+ [1][0][2][0][RTW89_ACMA][0][103] = 127,
+ [1][0][2][0][RTW89_CHILE][1][103] = 34,
+ [1][0][2][0][RTW89_QATAR][1][103] = 127,
+ [1][0][2][0][RTW89_QATAR][0][103] = 127,
+ [1][0][2][0][RTW89_UK][1][103] = 127,
+ [1][0][2][0][RTW89_UK][0][103] = 127,
+ [1][0][2][0][RTW89_FCC][1][106] = 36,
+ [1][0][2][0][RTW89_FCC][2][106] = 127,
+ [1][0][2][0][RTW89_ETSI][1][106] = 127,
+ [1][0][2][0][RTW89_ETSI][0][106] = 127,
+ [1][0][2][0][RTW89_MKK][1][106] = 127,
+ [1][0][2][0][RTW89_MKK][0][106] = 127,
+ [1][0][2][0][RTW89_IC][1][106] = 36,
+ [1][0][2][0][RTW89_KCC][1][106] = 42,
+ [1][0][2][0][RTW89_KCC][0][106] = 127,
+ [1][0][2][0][RTW89_ACMA][1][106] = 127,
+ [1][0][2][0][RTW89_ACMA][0][106] = 127,
+ [1][0][2][0][RTW89_CHILE][1][106] = 36,
+ [1][0][2][0][RTW89_QATAR][1][106] = 127,
+ [1][0][2][0][RTW89_QATAR][0][106] = 127,
+ [1][0][2][0][RTW89_UK][1][106] = 127,
+ [1][0][2][0][RTW89_UK][0][106] = 127,
+ [1][0][2][0][RTW89_FCC][1][110] = 127,
+ [1][0][2][0][RTW89_FCC][2][110] = 127,
+ [1][0][2][0][RTW89_ETSI][1][110] = 127,
+ [1][0][2][0][RTW89_ETSI][0][110] = 127,
+ [1][0][2][0][RTW89_MKK][1][110] = 127,
+ [1][0][2][0][RTW89_MKK][0][110] = 127,
+ [1][0][2][0][RTW89_IC][1][110] = 127,
+ [1][0][2][0][RTW89_KCC][1][110] = 127,
+ [1][0][2][0][RTW89_KCC][0][110] = 127,
+ [1][0][2][0][RTW89_ACMA][1][110] = 127,
+ [1][0][2][0][RTW89_ACMA][0][110] = 127,
+ [1][0][2][0][RTW89_CHILE][1][110] = 127,
+ [1][0][2][0][RTW89_QATAR][1][110] = 127,
+ [1][0][2][0][RTW89_QATAR][0][110] = 127,
+ [1][0][2][0][RTW89_UK][1][110] = 127,
+ [1][0][2][0][RTW89_UK][0][110] = 127,
+ [1][0][2][0][RTW89_FCC][1][114] = 127,
+ [1][0][2][0][RTW89_FCC][2][114] = 127,
+ [1][0][2][0][RTW89_ETSI][1][114] = 127,
+ [1][0][2][0][RTW89_ETSI][0][114] = 127,
+ [1][0][2][0][RTW89_MKK][1][114] = 127,
+ [1][0][2][0][RTW89_MKK][0][114] = 127,
+ [1][0][2][0][RTW89_IC][1][114] = 127,
+ [1][0][2][0][RTW89_KCC][1][114] = 127,
+ [1][0][2][0][RTW89_KCC][0][114] = 127,
+ [1][0][2][0][RTW89_ACMA][1][114] = 127,
+ [1][0][2][0][RTW89_ACMA][0][114] = 127,
+ [1][0][2][0][RTW89_CHILE][1][114] = 127,
+ [1][0][2][0][RTW89_QATAR][1][114] = 127,
+ [1][0][2][0][RTW89_QATAR][0][114] = 127,
+ [1][0][2][0][RTW89_UK][1][114] = 127,
+ [1][0][2][0][RTW89_UK][0][114] = 127,
+ [1][0][2][0][RTW89_FCC][1][118] = 127,
+ [1][0][2][0][RTW89_FCC][2][118] = 127,
+ [1][0][2][0][RTW89_ETSI][1][118] = 127,
+ [1][0][2][0][RTW89_ETSI][0][118] = 127,
+ [1][0][2][0][RTW89_MKK][1][118] = 127,
+ [1][0][2][0][RTW89_MKK][0][118] = 127,
+ [1][0][2][0][RTW89_IC][1][118] = 127,
+ [1][0][2][0][RTW89_KCC][1][118] = 127,
+ [1][0][2][0][RTW89_KCC][0][118] = 127,
+ [1][0][2][0][RTW89_ACMA][1][118] = 127,
+ [1][0][2][0][RTW89_ACMA][0][118] = 127,
+ [1][0][2][0][RTW89_CHILE][1][118] = 127,
+ [1][0][2][0][RTW89_QATAR][1][118] = 127,
+ [1][0][2][0][RTW89_QATAR][0][118] = 127,
+ [1][0][2][0][RTW89_UK][1][118] = 127,
+ [1][0][2][0][RTW89_UK][0][118] = 127,
+ [1][1][2][0][RTW89_FCC][1][1] = 10,
+ [1][1][2][0][RTW89_FCC][2][1] = 58,
+ [1][1][2][0][RTW89_ETSI][1][1] = 54,
+ [1][1][2][0][RTW89_ETSI][0][1] = 18,
+ [1][1][2][0][RTW89_MKK][1][1] = 52,
+ [1][1][2][0][RTW89_MKK][0][1] = 12,
+ [1][1][2][0][RTW89_IC][1][1] = 10,
+ [1][1][2][0][RTW89_KCC][1][1] = 28,
+ [1][1][2][0][RTW89_KCC][0][1] = 12,
+ [1][1][2][0][RTW89_ACMA][1][1] = 54,
+ [1][1][2][0][RTW89_ACMA][0][1] = 18,
+ [1][1][2][0][RTW89_CHILE][1][1] = 10,
+ [1][1][2][0][RTW89_QATAR][1][1] = 54,
+ [1][1][2][0][RTW89_QATAR][0][1] = 18,
+ [1][1][2][0][RTW89_UK][1][1] = 54,
+ [1][1][2][0][RTW89_UK][0][1] = 18,
+ [1][1][2][0][RTW89_FCC][1][5] = 10,
+ [1][1][2][0][RTW89_FCC][2][5] = 58,
+ [1][1][2][0][RTW89_ETSI][1][5] = 54,
+ [1][1][2][0][RTW89_ETSI][0][5] = 16,
+ [1][1][2][0][RTW89_MKK][1][5] = 52,
+ [1][1][2][0][RTW89_MKK][0][5] = 12,
+ [1][1][2][0][RTW89_IC][1][5] = 10,
+ [1][1][2][0][RTW89_KCC][1][5] = 28,
+ [1][1][2][0][RTW89_KCC][0][5] = 12,
+ [1][1][2][0][RTW89_ACMA][1][5] = 54,
+ [1][1][2][0][RTW89_ACMA][0][5] = 16,
+ [1][1][2][0][RTW89_CHILE][1][5] = 10,
+ [1][1][2][0][RTW89_QATAR][1][5] = 54,
+ [1][1][2][0][RTW89_QATAR][0][5] = 16,
+ [1][1][2][0][RTW89_UK][1][5] = 54,
+ [1][1][2][0][RTW89_UK][0][5] = 16,
+ [1][1][2][0][RTW89_FCC][1][9] = 10,
+ [1][1][2][0][RTW89_FCC][2][9] = 58,
+ [1][1][2][0][RTW89_ETSI][1][9] = 54,
+ [1][1][2][0][RTW89_ETSI][0][9] = 16,
+ [1][1][2][0][RTW89_MKK][1][9] = 52,
+ [1][1][2][0][RTW89_MKK][0][9] = 12,
+ [1][1][2][0][RTW89_IC][1][9] = 10,
+ [1][1][2][0][RTW89_KCC][1][9] = 28,
+ [1][1][2][0][RTW89_KCC][0][9] = 12,
+ [1][1][2][0][RTW89_ACMA][1][9] = 54,
+ [1][1][2][0][RTW89_ACMA][0][9] = 16,
+ [1][1][2][0][RTW89_CHILE][1][9] = 10,
+ [1][1][2][0][RTW89_QATAR][1][9] = 54,
+ [1][1][2][0][RTW89_QATAR][0][9] = 16,
+ [1][1][2][0][RTW89_UK][1][9] = 54,
+ [1][1][2][0][RTW89_UK][0][9] = 16,
+ [1][1][2][0][RTW89_FCC][1][13] = 10,
+ [1][1][2][0][RTW89_FCC][2][13] = 58,
+ [1][1][2][0][RTW89_ETSI][1][13] = 54,
+ [1][1][2][0][RTW89_ETSI][0][13] = 16,
+ [1][1][2][0][RTW89_MKK][1][13] = 52,
+ [1][1][2][0][RTW89_MKK][0][13] = 12,
+ [1][1][2][0][RTW89_IC][1][13] = 10,
+ [1][1][2][0][RTW89_KCC][1][13] = 28,
+ [1][1][2][0][RTW89_KCC][0][13] = 12,
+ [1][1][2][0][RTW89_ACMA][1][13] = 54,
+ [1][1][2][0][RTW89_ACMA][0][13] = 16,
+ [1][1][2][0][RTW89_CHILE][1][13] = 10,
+ [1][1][2][0][RTW89_QATAR][1][13] = 54,
+ [1][1][2][0][RTW89_QATAR][0][13] = 16,
+ [1][1][2][0][RTW89_UK][1][13] = 54,
+ [1][1][2][0][RTW89_UK][0][13] = 16,
+ [1][1][2][0][RTW89_FCC][1][16] = 10,
+ [1][1][2][0][RTW89_FCC][2][16] = 58,
+ [1][1][2][0][RTW89_ETSI][1][16] = 54,
+ [1][1][2][0][RTW89_ETSI][0][16] = 16,
+ [1][1][2][0][RTW89_MKK][1][16] = 52,
+ [1][1][2][0][RTW89_MKK][0][16] = 12,
+ [1][1][2][0][RTW89_IC][1][16] = 10,
+ [1][1][2][0][RTW89_KCC][1][16] = 28,
+ [1][1][2][0][RTW89_KCC][0][16] = 12,
+ [1][1][2][0][RTW89_ACMA][1][16] = 54,
+ [1][1][2][0][RTW89_ACMA][0][16] = 16,
+ [1][1][2][0][RTW89_CHILE][1][16] = 10,
+ [1][1][2][0][RTW89_QATAR][1][16] = 54,
+ [1][1][2][0][RTW89_QATAR][0][16] = 16,
+ [1][1][2][0][RTW89_UK][1][16] = 54,
+ [1][1][2][0][RTW89_UK][0][16] = 16,
+ [1][1][2][0][RTW89_FCC][1][20] = 10,
+ [1][1][2][0][RTW89_FCC][2][20] = 58,
+ [1][1][2][0][RTW89_ETSI][1][20] = 54,
+ [1][1][2][0][RTW89_ETSI][0][20] = 16,
+ [1][1][2][0][RTW89_MKK][1][20] = 52,
+ [1][1][2][0][RTW89_MKK][0][20] = 12,
+ [1][1][2][0][RTW89_IC][1][20] = 10,
+ [1][1][2][0][RTW89_KCC][1][20] = 28,
+ [1][1][2][0][RTW89_KCC][0][20] = 12,
+ [1][1][2][0][RTW89_ACMA][1][20] = 54,
+ [1][1][2][0][RTW89_ACMA][0][20] = 16,
+ [1][1][2][0][RTW89_CHILE][1][20] = 10,
+ [1][1][2][0][RTW89_QATAR][1][20] = 54,
+ [1][1][2][0][RTW89_QATAR][0][20] = 16,
+ [1][1][2][0][RTW89_UK][1][20] = 54,
+ [1][1][2][0][RTW89_UK][0][20] = 16,
+ [1][1][2][0][RTW89_FCC][1][24] = 10,
+ [1][1][2][0][RTW89_FCC][2][24] = 70,
+ [1][1][2][0][RTW89_ETSI][1][24] = 54,
+ [1][1][2][0][RTW89_ETSI][0][24] = 16,
+ [1][1][2][0][RTW89_MKK][1][24] = 54,
+ [1][1][2][0][RTW89_MKK][0][24] = 14,
+ [1][1][2][0][RTW89_IC][1][24] = 10,
+ [1][1][2][0][RTW89_KCC][1][24] = 28,
+ [1][1][2][0][RTW89_KCC][0][24] = 12,
+ [1][1][2][0][RTW89_ACMA][1][24] = 54,
+ [1][1][2][0][RTW89_ACMA][0][24] = 16,
+ [1][1][2][0][RTW89_CHILE][1][24] = 10,
+ [1][1][2][0][RTW89_QATAR][1][24] = 54,
+ [1][1][2][0][RTW89_QATAR][0][24] = 16,
+ [1][1][2][0][RTW89_UK][1][24] = 54,
+ [1][1][2][0][RTW89_UK][0][24] = 16,
+ [1][1][2][0][RTW89_FCC][1][28] = 10,
+ [1][1][2][0][RTW89_FCC][2][28] = 70,
+ [1][1][2][0][RTW89_ETSI][1][28] = 54,
+ [1][1][2][0][RTW89_ETSI][0][28] = 16,
+ [1][1][2][0][RTW89_MKK][1][28] = 52,
+ [1][1][2][0][RTW89_MKK][0][28] = 14,
+ [1][1][2][0][RTW89_IC][1][28] = 10,
+ [1][1][2][0][RTW89_KCC][1][28] = 28,
+ [1][1][2][0][RTW89_KCC][0][28] = 14,
+ [1][1][2][0][RTW89_ACMA][1][28] = 54,
+ [1][1][2][0][RTW89_ACMA][0][28] = 16,
+ [1][1][2][0][RTW89_CHILE][1][28] = 10,
+ [1][1][2][0][RTW89_QATAR][1][28] = 54,
+ [1][1][2][0][RTW89_QATAR][0][28] = 16,
+ [1][1][2][0][RTW89_UK][1][28] = 54,
+ [1][1][2][0][RTW89_UK][0][28] = 16,
+ [1][1][2][0][RTW89_FCC][1][31] = 10,
+ [1][1][2][0][RTW89_FCC][2][31] = 70,
+ [1][1][2][0][RTW89_ETSI][1][31] = 54,
+ [1][1][2][0][RTW89_ETSI][0][31] = 16,
+ [1][1][2][0][RTW89_MKK][1][31] = 52,
+ [1][1][2][0][RTW89_MKK][0][31] = 14,
+ [1][1][2][0][RTW89_IC][1][31] = 10,
+ [1][1][2][0][RTW89_KCC][1][31] = 28,
+ [1][1][2][0][RTW89_KCC][0][31] = 14,
+ [1][1][2][0][RTW89_ACMA][1][31] = 54,
+ [1][1][2][0][RTW89_ACMA][0][31] = 16,
+ [1][1][2][0][RTW89_CHILE][1][31] = 10,
+ [1][1][2][0][RTW89_QATAR][1][31] = 54,
+ [1][1][2][0][RTW89_QATAR][0][31] = 16,
+ [1][1][2][0][RTW89_UK][1][31] = 54,
+ [1][1][2][0][RTW89_UK][0][31] = 16,
+ [1][1][2][0][RTW89_FCC][1][35] = 10,
+ [1][1][2][0][RTW89_FCC][2][35] = 70,
+ [1][1][2][0][RTW89_ETSI][1][35] = 54,
+ [1][1][2][0][RTW89_ETSI][0][35] = 16,
+ [1][1][2][0][RTW89_MKK][1][35] = 52,
+ [1][1][2][0][RTW89_MKK][0][35] = 14,
+ [1][1][2][0][RTW89_IC][1][35] = 10,
+ [1][1][2][0][RTW89_KCC][1][35] = 28,
+ [1][1][2][0][RTW89_KCC][0][35] = 14,
+ [1][1][2][0][RTW89_ACMA][1][35] = 54,
+ [1][1][2][0][RTW89_ACMA][0][35] = 16,
+ [1][1][2][0][RTW89_CHILE][1][35] = 10,
+ [1][1][2][0][RTW89_QATAR][1][35] = 54,
+ [1][1][2][0][RTW89_QATAR][0][35] = 16,
+ [1][1][2][0][RTW89_UK][1][35] = 54,
+ [1][1][2][0][RTW89_UK][0][35] = 16,
+ [1][1][2][0][RTW89_FCC][1][39] = 10,
+ [1][1][2][0][RTW89_FCC][2][39] = 70,
+ [1][1][2][0][RTW89_ETSI][1][39] = 54,
+ [1][1][2][0][RTW89_ETSI][0][39] = 16,
+ [1][1][2][0][RTW89_MKK][1][39] = 52,
+ [1][1][2][0][RTW89_MKK][0][39] = 14,
+ [1][1][2][0][RTW89_IC][1][39] = 10,
+ [1][1][2][0][RTW89_KCC][1][39] = 28,
+ [1][1][2][0][RTW89_KCC][0][39] = 14,
+ [1][1][2][0][RTW89_ACMA][1][39] = 54,
+ [1][1][2][0][RTW89_ACMA][0][39] = 16,
+ [1][1][2][0][RTW89_CHILE][1][39] = 10,
+ [1][1][2][0][RTW89_QATAR][1][39] = 54,
+ [1][1][2][0][RTW89_QATAR][0][39] = 16,
+ [1][1][2][0][RTW89_UK][1][39] = 54,
+ [1][1][2][0][RTW89_UK][0][39] = 16,
+ [1][1][2][0][RTW89_FCC][1][43] = 10,
+ [1][1][2][0][RTW89_FCC][2][43] = 70,
+ [1][1][2][0][RTW89_ETSI][1][43] = 54,
+ [1][1][2][0][RTW89_ETSI][0][43] = 16,
+ [1][1][2][0][RTW89_MKK][1][43] = 52,
+ [1][1][2][0][RTW89_MKK][0][43] = 14,
+ [1][1][2][0][RTW89_IC][1][43] = 10,
+ [1][1][2][0][RTW89_KCC][1][43] = 28,
+ [1][1][2][0][RTW89_KCC][0][43] = 14,
+ [1][1][2][0][RTW89_ACMA][1][43] = 54,
+ [1][1][2][0][RTW89_ACMA][0][43] = 16,
+ [1][1][2][0][RTW89_CHILE][1][43] = 10,
+ [1][1][2][0][RTW89_QATAR][1][43] = 54,
+ [1][1][2][0][RTW89_QATAR][0][43] = 16,
+ [1][1][2][0][RTW89_UK][1][43] = 54,
+ [1][1][2][0][RTW89_UK][0][43] = 16,
+ [1][1][2][0][RTW89_FCC][1][46] = 12,
+ [1][1][2][0][RTW89_FCC][2][46] = 127,
+ [1][1][2][0][RTW89_ETSI][1][46] = 127,
+ [1][1][2][0][RTW89_ETSI][0][46] = 127,
+ [1][1][2][0][RTW89_MKK][1][46] = 127,
+ [1][1][2][0][RTW89_MKK][0][46] = 127,
+ [1][1][2][0][RTW89_IC][1][46] = 12,
+ [1][1][2][0][RTW89_KCC][1][46] = 28,
+ [1][1][2][0][RTW89_KCC][0][46] = 127,
+ [1][1][2][0][RTW89_ACMA][1][46] = 127,
+ [1][1][2][0][RTW89_ACMA][0][46] = 127,
+ [1][1][2][0][RTW89_CHILE][1][46] = 12,
+ [1][1][2][0][RTW89_QATAR][1][46] = 127,
+ [1][1][2][0][RTW89_QATAR][0][46] = 127,
+ [1][1][2][0][RTW89_UK][1][46] = 127,
+ [1][1][2][0][RTW89_UK][0][46] = 127,
+ [1][1][2][0][RTW89_FCC][1][50] = 12,
+ [1][1][2][0][RTW89_FCC][2][50] = 127,
+ [1][1][2][0][RTW89_ETSI][1][50] = 127,
+ [1][1][2][0][RTW89_ETSI][0][50] = 127,
+ [1][1][2][0][RTW89_MKK][1][50] = 127,
+ [1][1][2][0][RTW89_MKK][0][50] = 127,
+ [1][1][2][0][RTW89_IC][1][50] = 12,
+ [1][1][2][0][RTW89_KCC][1][50] = 28,
+ [1][1][2][0][RTW89_KCC][0][50] = 127,
+ [1][1][2][0][RTW89_ACMA][1][50] = 127,
+ [1][1][2][0][RTW89_ACMA][0][50] = 127,
+ [1][1][2][0][RTW89_CHILE][1][50] = 12,
+ [1][1][2][0][RTW89_QATAR][1][50] = 127,
+ [1][1][2][0][RTW89_QATAR][0][50] = 127,
+ [1][1][2][0][RTW89_UK][1][50] = 127,
+ [1][1][2][0][RTW89_UK][0][50] = 127,
+ [1][1][2][0][RTW89_FCC][1][54] = 10,
+ [1][1][2][0][RTW89_FCC][2][54] = 127,
+ [1][1][2][0][RTW89_ETSI][1][54] = 127,
+ [1][1][2][0][RTW89_ETSI][0][54] = 127,
+ [1][1][2][0][RTW89_MKK][1][54] = 127,
+ [1][1][2][0][RTW89_MKK][0][54] = 127,
+ [1][1][2][0][RTW89_IC][1][54] = 10,
+ [1][1][2][0][RTW89_KCC][1][54] = 28,
+ [1][1][2][0][RTW89_KCC][0][54] = 127,
+ [1][1][2][0][RTW89_ACMA][1][54] = 127,
+ [1][1][2][0][RTW89_ACMA][0][54] = 127,
+ [1][1][2][0][RTW89_CHILE][1][54] = 10,
+ [1][1][2][0][RTW89_QATAR][1][54] = 127,
+ [1][1][2][0][RTW89_QATAR][0][54] = 127,
+ [1][1][2][0][RTW89_UK][1][54] = 127,
+ [1][1][2][0][RTW89_UK][0][54] = 127,
+ [1][1][2][0][RTW89_FCC][1][58] = 10,
+ [1][1][2][0][RTW89_FCC][2][58] = 66,
+ [1][1][2][0][RTW89_ETSI][1][58] = 127,
+ [1][1][2][0][RTW89_ETSI][0][58] = 127,
+ [1][1][2][0][RTW89_MKK][1][58] = 127,
+ [1][1][2][0][RTW89_MKK][0][58] = 127,
+ [1][1][2][0][RTW89_IC][1][58] = 10,
+ [1][1][2][0][RTW89_KCC][1][58] = 28,
+ [1][1][2][0][RTW89_KCC][0][58] = 127,
+ [1][1][2][0][RTW89_ACMA][1][58] = 127,
+ [1][1][2][0][RTW89_ACMA][0][58] = 127,
+ [1][1][2][0][RTW89_CHILE][1][58] = 10,
+ [1][1][2][0][RTW89_QATAR][1][58] = 127,
+ [1][1][2][0][RTW89_QATAR][0][58] = 127,
+ [1][1][2][0][RTW89_UK][1][58] = 127,
+ [1][1][2][0][RTW89_UK][0][58] = 127,
+ [1][1][2][0][RTW89_FCC][1][61] = 10,
+ [1][1][2][0][RTW89_FCC][2][61] = 66,
+ [1][1][2][0][RTW89_ETSI][1][61] = 127,
+ [1][1][2][0][RTW89_ETSI][0][61] = 127,
+ [1][1][2][0][RTW89_MKK][1][61] = 127,
+ [1][1][2][0][RTW89_MKK][0][61] = 127,
+ [1][1][2][0][RTW89_IC][1][61] = 10,
+ [1][1][2][0][RTW89_KCC][1][61] = 28,
+ [1][1][2][0][RTW89_KCC][0][61] = 127,
+ [1][1][2][0][RTW89_ACMA][1][61] = 127,
+ [1][1][2][0][RTW89_ACMA][0][61] = 127,
+ [1][1][2][0][RTW89_CHILE][1][61] = 10,
+ [1][1][2][0][RTW89_QATAR][1][61] = 127,
+ [1][1][2][0][RTW89_QATAR][0][61] = 127,
+ [1][1][2][0][RTW89_UK][1][61] = 127,
+ [1][1][2][0][RTW89_UK][0][61] = 127,
+ [1][1][2][0][RTW89_FCC][1][65] = 10,
+ [1][1][2][0][RTW89_FCC][2][65] = 66,
+ [1][1][2][0][RTW89_ETSI][1][65] = 127,
+ [1][1][2][0][RTW89_ETSI][0][65] = 127,
+ [1][1][2][0][RTW89_MKK][1][65] = 127,
+ [1][1][2][0][RTW89_MKK][0][65] = 127,
+ [1][1][2][0][RTW89_IC][1][65] = 10,
+ [1][1][2][0][RTW89_KCC][1][65] = 28,
+ [1][1][2][0][RTW89_KCC][0][65] = 127,
+ [1][1][2][0][RTW89_ACMA][1][65] = 127,
+ [1][1][2][0][RTW89_ACMA][0][65] = 127,
+ [1][1][2][0][RTW89_CHILE][1][65] = 10,
+ [1][1][2][0][RTW89_QATAR][1][65] = 127,
+ [1][1][2][0][RTW89_QATAR][0][65] = 127,
+ [1][1][2][0][RTW89_UK][1][65] = 127,
+ [1][1][2][0][RTW89_UK][0][65] = 127,
+ [1][1][2][0][RTW89_FCC][1][69] = 10,
+ [1][1][2][0][RTW89_FCC][2][69] = 66,
+ [1][1][2][0][RTW89_ETSI][1][69] = 127,
+ [1][1][2][0][RTW89_ETSI][0][69] = 127,
+ [1][1][2][0][RTW89_MKK][1][69] = 127,
+ [1][1][2][0][RTW89_MKK][0][69] = 127,
+ [1][1][2][0][RTW89_IC][1][69] = 10,
+ [1][1][2][0][RTW89_KCC][1][69] = 28,
+ [1][1][2][0][RTW89_KCC][0][69] = 127,
+ [1][1][2][0][RTW89_ACMA][1][69] = 127,
+ [1][1][2][0][RTW89_ACMA][0][69] = 127,
+ [1][1][2][0][RTW89_CHILE][1][69] = 10,
+ [1][1][2][0][RTW89_QATAR][1][69] = 127,
+ [1][1][2][0][RTW89_QATAR][0][69] = 127,
+ [1][1][2][0][RTW89_UK][1][69] = 127,
+ [1][1][2][0][RTW89_UK][0][69] = 127,
+ [1][1][2][0][RTW89_FCC][1][73] = 10,
+ [1][1][2][0][RTW89_FCC][2][73] = 66,
+ [1][1][2][0][RTW89_ETSI][1][73] = 127,
+ [1][1][2][0][RTW89_ETSI][0][73] = 127,
+ [1][1][2][0][RTW89_MKK][1][73] = 127,
+ [1][1][2][0][RTW89_MKK][0][73] = 127,
+ [1][1][2][0][RTW89_IC][1][73] = 10,
+ [1][1][2][0][RTW89_KCC][1][73] = 28,
+ [1][1][2][0][RTW89_KCC][0][73] = 127,
+ [1][1][2][0][RTW89_ACMA][1][73] = 127,
+ [1][1][2][0][RTW89_ACMA][0][73] = 127,
+ [1][1][2][0][RTW89_CHILE][1][73] = 10,
+ [1][1][2][0][RTW89_QATAR][1][73] = 127,
+ [1][1][2][0][RTW89_QATAR][0][73] = 127,
+ [1][1][2][0][RTW89_UK][1][73] = 127,
+ [1][1][2][0][RTW89_UK][0][73] = 127,
+ [1][1][2][0][RTW89_FCC][1][76] = 10,
+ [1][1][2][0][RTW89_FCC][2][76] = 66,
+ [1][1][2][0][RTW89_ETSI][1][76] = 127,
+ [1][1][2][0][RTW89_ETSI][0][76] = 127,
+ [1][1][2][0][RTW89_MKK][1][76] = 127,
+ [1][1][2][0][RTW89_MKK][0][76] = 127,
+ [1][1][2][0][RTW89_IC][1][76] = 10,
+ [1][1][2][0][RTW89_KCC][1][76] = 28,
+ [1][1][2][0][RTW89_KCC][0][76] = 127,
+ [1][1][2][0][RTW89_ACMA][1][76] = 127,
+ [1][1][2][0][RTW89_ACMA][0][76] = 127,
+ [1][1][2][0][RTW89_CHILE][1][76] = 10,
+ [1][1][2][0][RTW89_QATAR][1][76] = 127,
+ [1][1][2][0][RTW89_QATAR][0][76] = 127,
+ [1][1][2][0][RTW89_UK][1][76] = 127,
+ [1][1][2][0][RTW89_UK][0][76] = 127,
+ [1][1][2][0][RTW89_FCC][1][80] = 10,
+ [1][1][2][0][RTW89_FCC][2][80] = 66,
+ [1][1][2][0][RTW89_ETSI][1][80] = 127,
+ [1][1][2][0][RTW89_ETSI][0][80] = 127,
+ [1][1][2][0][RTW89_MKK][1][80] = 127,
+ [1][1][2][0][RTW89_MKK][0][80] = 127,
+ [1][1][2][0][RTW89_IC][1][80] = 10,
+ [1][1][2][0][RTW89_KCC][1][80] = 32,
+ [1][1][2][0][RTW89_KCC][0][80] = 127,
+ [1][1][2][0][RTW89_ACMA][1][80] = 127,
+ [1][1][2][0][RTW89_ACMA][0][80] = 127,
+ [1][1][2][0][RTW89_CHILE][1][80] = 10,
+ [1][1][2][0][RTW89_QATAR][1][80] = 127,
+ [1][1][2][0][RTW89_QATAR][0][80] = 127,
+ [1][1][2][0][RTW89_UK][1][80] = 127,
+ [1][1][2][0][RTW89_UK][0][80] = 127,
+ [1][1][2][0][RTW89_FCC][1][84] = 10,
+ [1][1][2][0][RTW89_FCC][2][84] = 66,
+ [1][1][2][0][RTW89_ETSI][1][84] = 127,
+ [1][1][2][0][RTW89_ETSI][0][84] = 127,
+ [1][1][2][0][RTW89_MKK][1][84] = 127,
+ [1][1][2][0][RTW89_MKK][0][84] = 127,
+ [1][1][2][0][RTW89_IC][1][84] = 10,
+ [1][1][2][0][RTW89_KCC][1][84] = 32,
+ [1][1][2][0][RTW89_KCC][0][84] = 127,
+ [1][1][2][0][RTW89_ACMA][1][84] = 127,
+ [1][1][2][0][RTW89_ACMA][0][84] = 127,
+ [1][1][2][0][RTW89_CHILE][1][84] = 10,
+ [1][1][2][0][RTW89_QATAR][1][84] = 127,
+ [1][1][2][0][RTW89_QATAR][0][84] = 127,
+ [1][1][2][0][RTW89_UK][1][84] = 127,
+ [1][1][2][0][RTW89_UK][0][84] = 127,
+ [1][1][2][0][RTW89_FCC][1][88] = 10,
+ [1][1][2][0][RTW89_FCC][2][88] = 127,
+ [1][1][2][0][RTW89_ETSI][1][88] = 127,
+ [1][1][2][0][RTW89_ETSI][0][88] = 127,
+ [1][1][2][0][RTW89_MKK][1][88] = 127,
+ [1][1][2][0][RTW89_MKK][0][88] = 127,
+ [1][1][2][0][RTW89_IC][1][88] = 10,
+ [1][1][2][0][RTW89_KCC][1][88] = 32,
+ [1][1][2][0][RTW89_KCC][0][88] = 127,
+ [1][1][2][0][RTW89_ACMA][1][88] = 127,
+ [1][1][2][0][RTW89_ACMA][0][88] = 127,
+ [1][1][2][0][RTW89_CHILE][1][88] = 10,
+ [1][1][2][0][RTW89_QATAR][1][88] = 127,
+ [1][1][2][0][RTW89_QATAR][0][88] = 127,
+ [1][1][2][0][RTW89_UK][1][88] = 127,
+ [1][1][2][0][RTW89_UK][0][88] = 127,
+ [1][1][2][0][RTW89_FCC][1][91] = 12,
+ [1][1][2][0][RTW89_FCC][2][91] = 127,
+ [1][1][2][0][RTW89_ETSI][1][91] = 127,
+ [1][1][2][0][RTW89_ETSI][0][91] = 127,
+ [1][1][2][0][RTW89_MKK][1][91] = 127,
+ [1][1][2][0][RTW89_MKK][0][91] = 127,
+ [1][1][2][0][RTW89_IC][1][91] = 12,
+ [1][1][2][0][RTW89_KCC][1][91] = 32,
+ [1][1][2][0][RTW89_KCC][0][91] = 127,
+ [1][1][2][0][RTW89_ACMA][1][91] = 127,
+ [1][1][2][0][RTW89_ACMA][0][91] = 127,
+ [1][1][2][0][RTW89_CHILE][1][91] = 12,
+ [1][1][2][0][RTW89_QATAR][1][91] = 127,
+ [1][1][2][0][RTW89_QATAR][0][91] = 127,
+ [1][1][2][0][RTW89_UK][1][91] = 127,
+ [1][1][2][0][RTW89_UK][0][91] = 127,
+ [1][1][2][0][RTW89_FCC][1][95] = 10,
+ [1][1][2][0][RTW89_FCC][2][95] = 127,
+ [1][1][2][0][RTW89_ETSI][1][95] = 127,
+ [1][1][2][0][RTW89_ETSI][0][95] = 127,
+ [1][1][2][0][RTW89_MKK][1][95] = 127,
+ [1][1][2][0][RTW89_MKK][0][95] = 127,
+ [1][1][2][0][RTW89_IC][1][95] = 10,
+ [1][1][2][0][RTW89_KCC][1][95] = 32,
+ [1][1][2][0][RTW89_KCC][0][95] = 127,
+ [1][1][2][0][RTW89_ACMA][1][95] = 127,
+ [1][1][2][0][RTW89_ACMA][0][95] = 127,
+ [1][1][2][0][RTW89_CHILE][1][95] = 10,
+ [1][1][2][0][RTW89_QATAR][1][95] = 127,
+ [1][1][2][0][RTW89_QATAR][0][95] = 127,
+ [1][1][2][0][RTW89_UK][1][95] = 127,
+ [1][1][2][0][RTW89_UK][0][95] = 127,
+ [1][1][2][0][RTW89_FCC][1][99] = 10,
+ [1][1][2][0][RTW89_FCC][2][99] = 127,
+ [1][1][2][0][RTW89_ETSI][1][99] = 127,
+ [1][1][2][0][RTW89_ETSI][0][99] = 127,
+ [1][1][2][0][RTW89_MKK][1][99] = 127,
+ [1][1][2][0][RTW89_MKK][0][99] = 127,
+ [1][1][2][0][RTW89_IC][1][99] = 10,
+ [1][1][2][0][RTW89_KCC][1][99] = 32,
+ [1][1][2][0][RTW89_KCC][0][99] = 127,
+ [1][1][2][0][RTW89_ACMA][1][99] = 127,
+ [1][1][2][0][RTW89_ACMA][0][99] = 127,
+ [1][1][2][0][RTW89_CHILE][1][99] = 10,
+ [1][1][2][0][RTW89_QATAR][1][99] = 127,
+ [1][1][2][0][RTW89_QATAR][0][99] = 127,
+ [1][1][2][0][RTW89_UK][1][99] = 127,
+ [1][1][2][0][RTW89_UK][0][99] = 127,
+ [1][1][2][0][RTW89_FCC][1][103] = 10,
+ [1][1][2][0][RTW89_FCC][2][103] = 127,
+ [1][1][2][0][RTW89_ETSI][1][103] = 127,
+ [1][1][2][0][RTW89_ETSI][0][103] = 127,
+ [1][1][2][0][RTW89_MKK][1][103] = 127,
+ [1][1][2][0][RTW89_MKK][0][103] = 127,
+ [1][1][2][0][RTW89_IC][1][103] = 10,
+ [1][1][2][0][RTW89_KCC][1][103] = 32,
+ [1][1][2][0][RTW89_KCC][0][103] = 127,
+ [1][1][2][0][RTW89_ACMA][1][103] = 127,
+ [1][1][2][0][RTW89_ACMA][0][103] = 127,
+ [1][1][2][0][RTW89_CHILE][1][103] = 10,
+ [1][1][2][0][RTW89_QATAR][1][103] = 127,
+ [1][1][2][0][RTW89_QATAR][0][103] = 127,
+ [1][1][2][0][RTW89_UK][1][103] = 127,
+ [1][1][2][0][RTW89_UK][0][103] = 127,
+ [1][1][2][0][RTW89_FCC][1][106] = 12,
+ [1][1][2][0][RTW89_FCC][2][106] = 127,
+ [1][1][2][0][RTW89_ETSI][1][106] = 127,
+ [1][1][2][0][RTW89_ETSI][0][106] = 127,
+ [1][1][2][0][RTW89_MKK][1][106] = 127,
+ [1][1][2][0][RTW89_MKK][0][106] = 127,
+ [1][1][2][0][RTW89_IC][1][106] = 12,
+ [1][1][2][0][RTW89_KCC][1][106] = 32,
+ [1][1][2][0][RTW89_KCC][0][106] = 127,
+ [1][1][2][0][RTW89_ACMA][1][106] = 127,
+ [1][1][2][0][RTW89_ACMA][0][106] = 127,
+ [1][1][2][0][RTW89_CHILE][1][106] = 12,
+ [1][1][2][0][RTW89_QATAR][1][106] = 127,
+ [1][1][2][0][RTW89_QATAR][0][106] = 127,
+ [1][1][2][0][RTW89_UK][1][106] = 127,
+ [1][1][2][0][RTW89_UK][0][106] = 127,
+ [1][1][2][0][RTW89_FCC][1][110] = 127,
+ [1][1][2][0][RTW89_FCC][2][110] = 127,
+ [1][1][2][0][RTW89_ETSI][1][110] = 127,
+ [1][1][2][0][RTW89_ETSI][0][110] = 127,
+ [1][1][2][0][RTW89_MKK][1][110] = 127,
+ [1][1][2][0][RTW89_MKK][0][110] = 127,
+ [1][1][2][0][RTW89_IC][1][110] = 127,
+ [1][1][2][0][RTW89_KCC][1][110] = 127,
+ [1][1][2][0][RTW89_KCC][0][110] = 127,
+ [1][1][2][0][RTW89_ACMA][1][110] = 127,
+ [1][1][2][0][RTW89_ACMA][0][110] = 127,
+ [1][1][2][0][RTW89_CHILE][1][110] = 127,
+ [1][1][2][0][RTW89_QATAR][1][110] = 127,
+ [1][1][2][0][RTW89_QATAR][0][110] = 127,
+ [1][1][2][0][RTW89_UK][1][110] = 127,
+ [1][1][2][0][RTW89_UK][0][110] = 127,
+ [1][1][2][0][RTW89_FCC][1][114] = 127,
+ [1][1][2][0][RTW89_FCC][2][114] = 127,
+ [1][1][2][0][RTW89_ETSI][1][114] = 127,
+ [1][1][2][0][RTW89_ETSI][0][114] = 127,
+ [1][1][2][0][RTW89_MKK][1][114] = 127,
+ [1][1][2][0][RTW89_MKK][0][114] = 127,
+ [1][1][2][0][RTW89_IC][1][114] = 127,
+ [1][1][2][0][RTW89_KCC][1][114] = 127,
+ [1][1][2][0][RTW89_KCC][0][114] = 127,
+ [1][1][2][0][RTW89_ACMA][1][114] = 127,
+ [1][1][2][0][RTW89_ACMA][0][114] = 127,
+ [1][1][2][0][RTW89_CHILE][1][114] = 127,
+ [1][1][2][0][RTW89_QATAR][1][114] = 127,
+ [1][1][2][0][RTW89_QATAR][0][114] = 127,
+ [1][1][2][0][RTW89_UK][1][114] = 127,
+ [1][1][2][0][RTW89_UK][0][114] = 127,
+ [1][1][2][0][RTW89_FCC][1][118] = 127,
+ [1][1][2][0][RTW89_FCC][2][118] = 127,
+ [1][1][2][0][RTW89_ETSI][1][118] = 127,
+ [1][1][2][0][RTW89_ETSI][0][118] = 127,
+ [1][1][2][0][RTW89_MKK][1][118] = 127,
+ [1][1][2][0][RTW89_MKK][0][118] = 127,
+ [1][1][2][0][RTW89_IC][1][118] = 127,
+ [1][1][2][0][RTW89_KCC][1][118] = 127,
+ [1][1][2][0][RTW89_KCC][0][118] = 127,
+ [1][1][2][0][RTW89_ACMA][1][118] = 127,
+ [1][1][2][0][RTW89_ACMA][0][118] = 127,
+ [1][1][2][0][RTW89_CHILE][1][118] = 127,
+ [1][1][2][0][RTW89_QATAR][1][118] = 127,
+ [1][1][2][0][RTW89_QATAR][0][118] = 127,
+ [1][1][2][0][RTW89_UK][1][118] = 127,
+ [1][1][2][0][RTW89_UK][0][118] = 127,
+ [1][1][2][1][RTW89_FCC][1][1] = 10,
+ [1][1][2][1][RTW89_FCC][2][1] = 58,
+ [1][1][2][1][RTW89_ETSI][1][1] = 42,
+ [1][1][2][1][RTW89_ETSI][0][1] = 6,
+ [1][1][2][1][RTW89_MKK][1][1] = 52,
+ [1][1][2][1][RTW89_MKK][0][1] = 12,
+ [1][1][2][1][RTW89_IC][1][1] = 10,
+ [1][1][2][1][RTW89_KCC][1][1] = 28,
+ [1][1][2][1][RTW89_KCC][0][1] = 12,
+ [1][1][2][1][RTW89_ACMA][1][1] = 42,
+ [1][1][2][1][RTW89_ACMA][0][1] = 6,
+ [1][1][2][1][RTW89_CHILE][1][1] = 10,
+ [1][1][2][1][RTW89_QATAR][1][1] = 42,
+ [1][1][2][1][RTW89_QATAR][0][1] = 6,
+ [1][1][2][1][RTW89_UK][1][1] = 42,
+ [1][1][2][1][RTW89_UK][0][1] = 6,
+ [1][1][2][1][RTW89_FCC][1][5] = 10,
+ [1][1][2][1][RTW89_FCC][2][5] = 58,
+ [1][1][2][1][RTW89_ETSI][1][5] = 42,
+ [1][1][2][1][RTW89_ETSI][0][5] = 6,
+ [1][1][2][1][RTW89_MKK][1][5] = 52,
+ [1][1][2][1][RTW89_MKK][0][5] = 12,
+ [1][1][2][1][RTW89_IC][1][5] = 10,
+ [1][1][2][1][RTW89_KCC][1][5] = 28,
+ [1][1][2][1][RTW89_KCC][0][5] = 12,
+ [1][1][2][1][RTW89_ACMA][1][5] = 42,
+ [1][1][2][1][RTW89_ACMA][0][5] = 6,
+ [1][1][2][1][RTW89_CHILE][1][5] = 10,
+ [1][1][2][1][RTW89_QATAR][1][5] = 42,
+ [1][1][2][1][RTW89_QATAR][0][5] = 6,
+ [1][1][2][1][RTW89_UK][1][5] = 42,
+ [1][1][2][1][RTW89_UK][0][5] = 6,
+ [1][1][2][1][RTW89_FCC][1][9] = 10,
+ [1][1][2][1][RTW89_FCC][2][9] = 58,
+ [1][1][2][1][RTW89_ETSI][1][9] = 42,
+ [1][1][2][1][RTW89_ETSI][0][9] = 6,
+ [1][1][2][1][RTW89_MKK][1][9] = 52,
+ [1][1][2][1][RTW89_MKK][0][9] = 12,
+ [1][1][2][1][RTW89_IC][1][9] = 10,
+ [1][1][2][1][RTW89_KCC][1][9] = 28,
+ [1][1][2][1][RTW89_KCC][0][9] = 12,
+ [1][1][2][1][RTW89_ACMA][1][9] = 42,
+ [1][1][2][1][RTW89_ACMA][0][9] = 6,
+ [1][1][2][1][RTW89_CHILE][1][9] = 10,
+ [1][1][2][1][RTW89_QATAR][1][9] = 42,
+ [1][1][2][1][RTW89_QATAR][0][9] = 6,
+ [1][1][2][1][RTW89_UK][1][9] = 42,
+ [1][1][2][1][RTW89_UK][0][9] = 6,
+ [1][1][2][1][RTW89_FCC][1][13] = 10,
+ [1][1][2][1][RTW89_FCC][2][13] = 58,
+ [1][1][2][1][RTW89_ETSI][1][13] = 42,
+ [1][1][2][1][RTW89_ETSI][0][13] = 6,
+ [1][1][2][1][RTW89_MKK][1][13] = 52,
+ [1][1][2][1][RTW89_MKK][0][13] = 12,
+ [1][1][2][1][RTW89_IC][1][13] = 10,
+ [1][1][2][1][RTW89_KCC][1][13] = 28,
+ [1][1][2][1][RTW89_KCC][0][13] = 12,
+ [1][1][2][1][RTW89_ACMA][1][13] = 42,
+ [1][1][2][1][RTW89_ACMA][0][13] = 6,
+ [1][1][2][1][RTW89_CHILE][1][13] = 10,
+ [1][1][2][1][RTW89_QATAR][1][13] = 42,
+ [1][1][2][1][RTW89_QATAR][0][13] = 6,
+ [1][1][2][1][RTW89_UK][1][13] = 42,
+ [1][1][2][1][RTW89_UK][0][13] = 6,
+ [1][1][2][1][RTW89_FCC][1][16] = 10,
+ [1][1][2][1][RTW89_FCC][2][16] = 58,
+ [1][1][2][1][RTW89_ETSI][1][16] = 42,
+ [1][1][2][1][RTW89_ETSI][0][16] = 6,
+ [1][1][2][1][RTW89_MKK][1][16] = 52,
+ [1][1][2][1][RTW89_MKK][0][16] = 12,
+ [1][1][2][1][RTW89_IC][1][16] = 10,
+ [1][1][2][1][RTW89_KCC][1][16] = 28,
+ [1][1][2][1][RTW89_KCC][0][16] = 12,
+ [1][1][2][1][RTW89_ACMA][1][16] = 42,
+ [1][1][2][1][RTW89_ACMA][0][16] = 6,
+ [1][1][2][1][RTW89_CHILE][1][16] = 10,
+ [1][1][2][1][RTW89_QATAR][1][16] = 42,
+ [1][1][2][1][RTW89_QATAR][0][16] = 6,
+ [1][1][2][1][RTW89_UK][1][16] = 42,
+ [1][1][2][1][RTW89_UK][0][16] = 6,
+ [1][1][2][1][RTW89_FCC][1][20] = 10,
+ [1][1][2][1][RTW89_FCC][2][20] = 58,
+ [1][1][2][1][RTW89_ETSI][1][20] = 42,
+ [1][1][2][1][RTW89_ETSI][0][20] = 6,
+ [1][1][2][1][RTW89_MKK][1][20] = 52,
+ [1][1][2][1][RTW89_MKK][0][20] = 12,
+ [1][1][2][1][RTW89_IC][1][20] = 10,
+ [1][1][2][1][RTW89_KCC][1][20] = 28,
+ [1][1][2][1][RTW89_KCC][0][20] = 12,
+ [1][1][2][1][RTW89_ACMA][1][20] = 42,
+ [1][1][2][1][RTW89_ACMA][0][20] = 6,
+ [1][1][2][1][RTW89_CHILE][1][20] = 10,
+ [1][1][2][1][RTW89_QATAR][1][20] = 42,
+ [1][1][2][1][RTW89_QATAR][0][20] = 6,
+ [1][1][2][1][RTW89_UK][1][20] = 42,
+ [1][1][2][1][RTW89_UK][0][20] = 6,
+ [1][1][2][1][RTW89_FCC][1][24] = 10,
+ [1][1][2][1][RTW89_FCC][2][24] = 70,
+ [1][1][2][1][RTW89_ETSI][1][24] = 42,
+ [1][1][2][1][RTW89_ETSI][0][24] = 6,
+ [1][1][2][1][RTW89_MKK][1][24] = 54,
+ [1][1][2][1][RTW89_MKK][0][24] = 14,
+ [1][1][2][1][RTW89_IC][1][24] = 10,
+ [1][1][2][1][RTW89_KCC][1][24] = 28,
+ [1][1][2][1][RTW89_KCC][0][24] = 12,
+ [1][1][2][1][RTW89_ACMA][1][24] = 42,
+ [1][1][2][1][RTW89_ACMA][0][24] = 6,
+ [1][1][2][1][RTW89_CHILE][1][24] = 10,
+ [1][1][2][1][RTW89_QATAR][1][24] = 42,
+ [1][1][2][1][RTW89_QATAR][0][24] = 6,
+ [1][1][2][1][RTW89_UK][1][24] = 42,
+ [1][1][2][1][RTW89_UK][0][24] = 6,
+ [1][1][2][1][RTW89_FCC][1][28] = 10,
+ [1][1][2][1][RTW89_FCC][2][28] = 70,
+ [1][1][2][1][RTW89_ETSI][1][28] = 42,
+ [1][1][2][1][RTW89_ETSI][0][28] = 6,
+ [1][1][2][1][RTW89_MKK][1][28] = 52,
+ [1][1][2][1][RTW89_MKK][0][28] = 14,
+ [1][1][2][1][RTW89_IC][1][28] = 10,
+ [1][1][2][1][RTW89_KCC][1][28] = 28,
+ [1][1][2][1][RTW89_KCC][0][28] = 14,
+ [1][1][2][1][RTW89_ACMA][1][28] = 42,
+ [1][1][2][1][RTW89_ACMA][0][28] = 6,
+ [1][1][2][1][RTW89_CHILE][1][28] = 10,
+ [1][1][2][1][RTW89_QATAR][1][28] = 42,
+ [1][1][2][1][RTW89_QATAR][0][28] = 6,
+ [1][1][2][1][RTW89_UK][1][28] = 42,
+ [1][1][2][1][RTW89_UK][0][28] = 6,
+ [1][1][2][1][RTW89_FCC][1][31] = 10,
+ [1][1][2][1][RTW89_FCC][2][31] = 70,
+ [1][1][2][1][RTW89_ETSI][1][31] = 42,
+ [1][1][2][1][RTW89_ETSI][0][31] = 6,
+ [1][1][2][1][RTW89_MKK][1][31] = 52,
+ [1][1][2][1][RTW89_MKK][0][31] = 14,
+ [1][1][2][1][RTW89_IC][1][31] = 10,
+ [1][1][2][1][RTW89_KCC][1][31] = 28,
+ [1][1][2][1][RTW89_KCC][0][31] = 14,
+ [1][1][2][1][RTW89_ACMA][1][31] = 42,
+ [1][1][2][1][RTW89_ACMA][0][31] = 6,
+ [1][1][2][1][RTW89_CHILE][1][31] = 10,
+ [1][1][2][1][RTW89_QATAR][1][31] = 42,
+ [1][1][2][1][RTW89_QATAR][0][31] = 6,
+ [1][1][2][1][RTW89_UK][1][31] = 42,
+ [1][1][2][1][RTW89_UK][0][31] = 6,
+ [1][1][2][1][RTW89_FCC][1][35] = 10,
+ [1][1][2][1][RTW89_FCC][2][35] = 70,
+ [1][1][2][1][RTW89_ETSI][1][35] = 42,
+ [1][1][2][1][RTW89_ETSI][0][35] = 6,
+ [1][1][2][1][RTW89_MKK][1][35] = 52,
+ [1][1][2][1][RTW89_MKK][0][35] = 14,
+ [1][1][2][1][RTW89_IC][1][35] = 10,
+ [1][1][2][1][RTW89_KCC][1][35] = 28,
+ [1][1][2][1][RTW89_KCC][0][35] = 14,
+ [1][1][2][1][RTW89_ACMA][1][35] = 42,
+ [1][1][2][1][RTW89_ACMA][0][35] = 6,
+ [1][1][2][1][RTW89_CHILE][1][35] = 10,
+ [1][1][2][1][RTW89_QATAR][1][35] = 42,
+ [1][1][2][1][RTW89_QATAR][0][35] = 6,
+ [1][1][2][1][RTW89_UK][1][35] = 42,
+ [1][1][2][1][RTW89_UK][0][35] = 6,
+ [1][1][2][1][RTW89_FCC][1][39] = 10,
+ [1][1][2][1][RTW89_FCC][2][39] = 70,
+ [1][1][2][1][RTW89_ETSI][1][39] = 42,
+ [1][1][2][1][RTW89_ETSI][0][39] = 6,
+ [1][1][2][1][RTW89_MKK][1][39] = 52,
+ [1][1][2][1][RTW89_MKK][0][39] = 14,
+ [1][1][2][1][RTW89_IC][1][39] = 10,
+ [1][1][2][1][RTW89_KCC][1][39] = 28,
+ [1][1][2][1][RTW89_KCC][0][39] = 14,
+ [1][1][2][1][RTW89_ACMA][1][39] = 42,
+ [1][1][2][1][RTW89_ACMA][0][39] = 6,
+ [1][1][2][1][RTW89_CHILE][1][39] = 10,
+ [1][1][2][1][RTW89_QATAR][1][39] = 42,
+ [1][1][2][1][RTW89_QATAR][0][39] = 6,
+ [1][1][2][1][RTW89_UK][1][39] = 42,
+ [1][1][2][1][RTW89_UK][0][39] = 6,
+ [1][1][2][1][RTW89_FCC][1][43] = 10,
+ [1][1][2][1][RTW89_FCC][2][43] = 70,
+ [1][1][2][1][RTW89_ETSI][1][43] = 42,
+ [1][1][2][1][RTW89_ETSI][0][43] = 6,
+ [1][1][2][1][RTW89_MKK][1][43] = 52,
+ [1][1][2][1][RTW89_MKK][0][43] = 14,
+ [1][1][2][1][RTW89_IC][1][43] = 10,
+ [1][1][2][1][RTW89_KCC][1][43] = 28,
+ [1][1][2][1][RTW89_KCC][0][43] = 14,
+ [1][1][2][1][RTW89_ACMA][1][43] = 42,
+ [1][1][2][1][RTW89_ACMA][0][43] = 6,
+ [1][1][2][1][RTW89_CHILE][1][43] = 10,
+ [1][1][2][1][RTW89_QATAR][1][43] = 42,
+ [1][1][2][1][RTW89_QATAR][0][43] = 6,
+ [1][1][2][1][RTW89_UK][1][43] = 42,
+ [1][1][2][1][RTW89_UK][0][43] = 6,
+ [1][1][2][1][RTW89_FCC][1][46] = 12,
+ [1][1][2][1][RTW89_FCC][2][46] = 127,
+ [1][1][2][1][RTW89_ETSI][1][46] = 127,
+ [1][1][2][1][RTW89_ETSI][0][46] = 127,
+ [1][1][2][1][RTW89_MKK][1][46] = 127,
+ [1][1][2][1][RTW89_MKK][0][46] = 127,
+ [1][1][2][1][RTW89_IC][1][46] = 12,
+ [1][1][2][1][RTW89_KCC][1][46] = 28,
+ [1][1][2][1][RTW89_KCC][0][46] = 127,
+ [1][1][2][1][RTW89_ACMA][1][46] = 127,
+ [1][1][2][1][RTW89_ACMA][0][46] = 127,
+ [1][1][2][1][RTW89_CHILE][1][46] = 12,
+ [1][1][2][1][RTW89_QATAR][1][46] = 127,
+ [1][1][2][1][RTW89_QATAR][0][46] = 127,
+ [1][1][2][1][RTW89_UK][1][46] = 127,
+ [1][1][2][1][RTW89_UK][0][46] = 127,
+ [1][1][2][1][RTW89_FCC][1][50] = 12,
+ [1][1][2][1][RTW89_FCC][2][50] = 127,
+ [1][1][2][1][RTW89_ETSI][1][50] = 127,
+ [1][1][2][1][RTW89_ETSI][0][50] = 127,
+ [1][1][2][1][RTW89_MKK][1][50] = 127,
+ [1][1][2][1][RTW89_MKK][0][50] = 127,
+ [1][1][2][1][RTW89_IC][1][50] = 12,
+ [1][1][2][1][RTW89_KCC][1][50] = 28,
+ [1][1][2][1][RTW89_KCC][0][50] = 127,
+ [1][1][2][1][RTW89_ACMA][1][50] = 127,
+ [1][1][2][1][RTW89_ACMA][0][50] = 127,
+ [1][1][2][1][RTW89_CHILE][1][50] = 12,
+ [1][1][2][1][RTW89_QATAR][1][50] = 127,
+ [1][1][2][1][RTW89_QATAR][0][50] = 127,
+ [1][1][2][1][RTW89_UK][1][50] = 127,
+ [1][1][2][1][RTW89_UK][0][50] = 127,
+ [1][1][2][1][RTW89_FCC][1][54] = 10,
+ [1][1][2][1][RTW89_FCC][2][54] = 127,
+ [1][1][2][1][RTW89_ETSI][1][54] = 127,
+ [1][1][2][1][RTW89_ETSI][0][54] = 127,
+ [1][1][2][1][RTW89_MKK][1][54] = 127,
+ [1][1][2][1][RTW89_MKK][0][54] = 127,
+ [1][1][2][1][RTW89_IC][1][54] = 10,
+ [1][1][2][1][RTW89_KCC][1][54] = 28,
+ [1][1][2][1][RTW89_KCC][0][54] = 127,
+ [1][1][2][1][RTW89_ACMA][1][54] = 127,
+ [1][1][2][1][RTW89_ACMA][0][54] = 127,
+ [1][1][2][1][RTW89_CHILE][1][54] = 10,
+ [1][1][2][1][RTW89_QATAR][1][54] = 127,
+ [1][1][2][1][RTW89_QATAR][0][54] = 127,
+ [1][1][2][1][RTW89_UK][1][54] = 127,
+ [1][1][2][1][RTW89_UK][0][54] = 127,
+ [1][1][2][1][RTW89_FCC][1][58] = 10,
+ [1][1][2][1][RTW89_FCC][2][58] = 66,
+ [1][1][2][1][RTW89_ETSI][1][58] = 127,
+ [1][1][2][1][RTW89_ETSI][0][58] = 127,
+ [1][1][2][1][RTW89_MKK][1][58] = 127,
+ [1][1][2][1][RTW89_MKK][0][58] = 127,
+ [1][1][2][1][RTW89_IC][1][58] = 10,
+ [1][1][2][1][RTW89_KCC][1][58] = 28,
+ [1][1][2][1][RTW89_KCC][0][58] = 127,
+ [1][1][2][1][RTW89_ACMA][1][58] = 127,
+ [1][1][2][1][RTW89_ACMA][0][58] = 127,
+ [1][1][2][1][RTW89_CHILE][1][58] = 10,
+ [1][1][2][1][RTW89_QATAR][1][58] = 127,
+ [1][1][2][1][RTW89_QATAR][0][58] = 127,
+ [1][1][2][1][RTW89_UK][1][58] = 127,
+ [1][1][2][1][RTW89_UK][0][58] = 127,
+ [1][1][2][1][RTW89_FCC][1][61] = 10,
+ [1][1][2][1][RTW89_FCC][2][61] = 66,
+ [1][1][2][1][RTW89_ETSI][1][61] = 127,
+ [1][1][2][1][RTW89_ETSI][0][61] = 127,
+ [1][1][2][1][RTW89_MKK][1][61] = 127,
+ [1][1][2][1][RTW89_MKK][0][61] = 127,
+ [1][1][2][1][RTW89_IC][1][61] = 10,
+ [1][1][2][1][RTW89_KCC][1][61] = 28,
+ [1][1][2][1][RTW89_KCC][0][61] = 127,
+ [1][1][2][1][RTW89_ACMA][1][61] = 127,
+ [1][1][2][1][RTW89_ACMA][0][61] = 127,
+ [1][1][2][1][RTW89_CHILE][1][61] = 10,
+ [1][1][2][1][RTW89_QATAR][1][61] = 127,
+ [1][1][2][1][RTW89_QATAR][0][61] = 127,
+ [1][1][2][1][RTW89_UK][1][61] = 127,
+ [1][1][2][1][RTW89_UK][0][61] = 127,
+ [1][1][2][1][RTW89_FCC][1][65] = 10,
+ [1][1][2][1][RTW89_FCC][2][65] = 66,
+ [1][1][2][1][RTW89_ETSI][1][65] = 127,
+ [1][1][2][1][RTW89_ETSI][0][65] = 127,
+ [1][1][2][1][RTW89_MKK][1][65] = 127,
+ [1][1][2][1][RTW89_MKK][0][65] = 127,
+ [1][1][2][1][RTW89_IC][1][65] = 10,
+ [1][1][2][1][RTW89_KCC][1][65] = 28,
+ [1][1][2][1][RTW89_KCC][0][65] = 127,
+ [1][1][2][1][RTW89_ACMA][1][65] = 127,
+ [1][1][2][1][RTW89_ACMA][0][65] = 127,
+ [1][1][2][1][RTW89_CHILE][1][65] = 10,
+ [1][1][2][1][RTW89_QATAR][1][65] = 127,
+ [1][1][2][1][RTW89_QATAR][0][65] = 127,
+ [1][1][2][1][RTW89_UK][1][65] = 127,
+ [1][1][2][1][RTW89_UK][0][65] = 127,
+ [1][1][2][1][RTW89_FCC][1][69] = 10,
+ [1][1][2][1][RTW89_FCC][2][69] = 66,
+ [1][1][2][1][RTW89_ETSI][1][69] = 127,
+ [1][1][2][1][RTW89_ETSI][0][69] = 127,
+ [1][1][2][1][RTW89_MKK][1][69] = 127,
+ [1][1][2][1][RTW89_MKK][0][69] = 127,
+ [1][1][2][1][RTW89_IC][1][69] = 10,
+ [1][1][2][1][RTW89_KCC][1][69] = 28,
+ [1][1][2][1][RTW89_KCC][0][69] = 127,
+ [1][1][2][1][RTW89_ACMA][1][69] = 127,
+ [1][1][2][1][RTW89_ACMA][0][69] = 127,
+ [1][1][2][1][RTW89_CHILE][1][69] = 10,
+ [1][1][2][1][RTW89_QATAR][1][69] = 127,
+ [1][1][2][1][RTW89_QATAR][0][69] = 127,
+ [1][1][2][1][RTW89_UK][1][69] = 127,
+ [1][1][2][1][RTW89_UK][0][69] = 127,
+ [1][1][2][1][RTW89_FCC][1][73] = 10,
+ [1][1][2][1][RTW89_FCC][2][73] = 66,
+ [1][1][2][1][RTW89_ETSI][1][73] = 127,
+ [1][1][2][1][RTW89_ETSI][0][73] = 127,
+ [1][1][2][1][RTW89_MKK][1][73] = 127,
+ [1][1][2][1][RTW89_MKK][0][73] = 127,
+ [1][1][2][1][RTW89_IC][1][73] = 10,
+ [1][1][2][1][RTW89_KCC][1][73] = 28,
+ [1][1][2][1][RTW89_KCC][0][73] = 127,
+ [1][1][2][1][RTW89_ACMA][1][73] = 127,
+ [1][1][2][1][RTW89_ACMA][0][73] = 127,
+ [1][1][2][1][RTW89_CHILE][1][73] = 10,
+ [1][1][2][1][RTW89_QATAR][1][73] = 127,
+ [1][1][2][1][RTW89_QATAR][0][73] = 127,
+ [1][1][2][1][RTW89_UK][1][73] = 127,
+ [1][1][2][1][RTW89_UK][0][73] = 127,
+ [1][1][2][1][RTW89_FCC][1][76] = 10,
+ [1][1][2][1][RTW89_FCC][2][76] = 66,
+ [1][1][2][1][RTW89_ETSI][1][76] = 127,
+ [1][1][2][1][RTW89_ETSI][0][76] = 127,
+ [1][1][2][1][RTW89_MKK][1][76] = 127,
+ [1][1][2][1][RTW89_MKK][0][76] = 127,
+ [1][1][2][1][RTW89_IC][1][76] = 10,
+ [1][1][2][1][RTW89_KCC][1][76] = 28,
+ [1][1][2][1][RTW89_KCC][0][76] = 127,
+ [1][1][2][1][RTW89_ACMA][1][76] = 127,
+ [1][1][2][1][RTW89_ACMA][0][76] = 127,
+ [1][1][2][1][RTW89_CHILE][1][76] = 10,
+ [1][1][2][1][RTW89_QATAR][1][76] = 127,
+ [1][1][2][1][RTW89_QATAR][0][76] = 127,
+ [1][1][2][1][RTW89_UK][1][76] = 127,
+ [1][1][2][1][RTW89_UK][0][76] = 127,
+ [1][1][2][1][RTW89_FCC][1][80] = 10,
+ [1][1][2][1][RTW89_FCC][2][80] = 66,
+ [1][1][2][1][RTW89_ETSI][1][80] = 127,
+ [1][1][2][1][RTW89_ETSI][0][80] = 127,
+ [1][1][2][1][RTW89_MKK][1][80] = 127,
+ [1][1][2][1][RTW89_MKK][0][80] = 127,
+ [1][1][2][1][RTW89_IC][1][80] = 10,
+ [1][1][2][1][RTW89_KCC][1][80] = 32,
+ [1][1][2][1][RTW89_KCC][0][80] = 127,
+ [1][1][2][1][RTW89_ACMA][1][80] = 127,
+ [1][1][2][1][RTW89_ACMA][0][80] = 127,
+ [1][1][2][1][RTW89_CHILE][1][80] = 10,
+ [1][1][2][1][RTW89_QATAR][1][80] = 127,
+ [1][1][2][1][RTW89_QATAR][0][80] = 127,
+ [1][1][2][1][RTW89_UK][1][80] = 127,
+ [1][1][2][1][RTW89_UK][0][80] = 127,
+ [1][1][2][1][RTW89_FCC][1][84] = 10,
+ [1][1][2][1][RTW89_FCC][2][84] = 66,
+ [1][1][2][1][RTW89_ETSI][1][84] = 127,
+ [1][1][2][1][RTW89_ETSI][0][84] = 127,
+ [1][1][2][1][RTW89_MKK][1][84] = 127,
+ [1][1][2][1][RTW89_MKK][0][84] = 127,
+ [1][1][2][1][RTW89_IC][1][84] = 10,
+ [1][1][2][1][RTW89_KCC][1][84] = 32,
+ [1][1][2][1][RTW89_KCC][0][84] = 127,
+ [1][1][2][1][RTW89_ACMA][1][84] = 127,
+ [1][1][2][1][RTW89_ACMA][0][84] = 127,
+ [1][1][2][1][RTW89_CHILE][1][84] = 10,
+ [1][1][2][1][RTW89_QATAR][1][84] = 127,
+ [1][1][2][1][RTW89_QATAR][0][84] = 127,
+ [1][1][2][1][RTW89_UK][1][84] = 127,
+ [1][1][2][1][RTW89_UK][0][84] = 127,
+ [1][1][2][1][RTW89_FCC][1][88] = 10,
+ [1][1][2][1][RTW89_FCC][2][88] = 127,
+ [1][1][2][1][RTW89_ETSI][1][88] = 127,
+ [1][1][2][1][RTW89_ETSI][0][88] = 127,
+ [1][1][2][1][RTW89_MKK][1][88] = 127,
+ [1][1][2][1][RTW89_MKK][0][88] = 127,
+ [1][1][2][1][RTW89_IC][1][88] = 10,
+ [1][1][2][1][RTW89_KCC][1][88] = 32,
+ [1][1][2][1][RTW89_KCC][0][88] = 127,
+ [1][1][2][1][RTW89_ACMA][1][88] = 127,
+ [1][1][2][1][RTW89_ACMA][0][88] = 127,
+ [1][1][2][1][RTW89_CHILE][1][88] = 10,
+ [1][1][2][1][RTW89_QATAR][1][88] = 127,
+ [1][1][2][1][RTW89_QATAR][0][88] = 127,
+ [1][1][2][1][RTW89_UK][1][88] = 127,
+ [1][1][2][1][RTW89_UK][0][88] = 127,
+ [1][1][2][1][RTW89_FCC][1][91] = 12,
+ [1][1][2][1][RTW89_FCC][2][91] = 127,
+ [1][1][2][1][RTW89_ETSI][1][91] = 127,
+ [1][1][2][1][RTW89_ETSI][0][91] = 127,
+ [1][1][2][1][RTW89_MKK][1][91] = 127,
+ [1][1][2][1][RTW89_MKK][0][91] = 127,
+ [1][1][2][1][RTW89_IC][1][91] = 12,
+ [1][1][2][1][RTW89_KCC][1][91] = 32,
+ [1][1][2][1][RTW89_KCC][0][91] = 127,
+ [1][1][2][1][RTW89_ACMA][1][91] = 127,
+ [1][1][2][1][RTW89_ACMA][0][91] = 127,
+ [1][1][2][1][RTW89_CHILE][1][91] = 12,
+ [1][1][2][1][RTW89_QATAR][1][91] = 127,
+ [1][1][2][1][RTW89_QATAR][0][91] = 127,
+ [1][1][2][1][RTW89_UK][1][91] = 127,
+ [1][1][2][1][RTW89_UK][0][91] = 127,
+ [1][1][2][1][RTW89_FCC][1][95] = 10,
+ [1][1][2][1][RTW89_FCC][2][95] = 127,
+ [1][1][2][1][RTW89_ETSI][1][95] = 127,
+ [1][1][2][1][RTW89_ETSI][0][95] = 127,
+ [1][1][2][1][RTW89_MKK][1][95] = 127,
+ [1][1][2][1][RTW89_MKK][0][95] = 127,
+ [1][1][2][1][RTW89_IC][1][95] = 10,
+ [1][1][2][1][RTW89_KCC][1][95] = 32,
+ [1][1][2][1][RTW89_KCC][0][95] = 127,
+ [1][1][2][1][RTW89_ACMA][1][95] = 127,
+ [1][1][2][1][RTW89_ACMA][0][95] = 127,
+ [1][1][2][1][RTW89_CHILE][1][95] = 10,
+ [1][1][2][1][RTW89_QATAR][1][95] = 127,
+ [1][1][2][1][RTW89_QATAR][0][95] = 127,
+ [1][1][2][1][RTW89_UK][1][95] = 127,
+ [1][1][2][1][RTW89_UK][0][95] = 127,
+ [1][1][2][1][RTW89_FCC][1][99] = 10,
+ [1][1][2][1][RTW89_FCC][2][99] = 127,
+ [1][1][2][1][RTW89_ETSI][1][99] = 127,
+ [1][1][2][1][RTW89_ETSI][0][99] = 127,
+ [1][1][2][1][RTW89_MKK][1][99] = 127,
+ [1][1][2][1][RTW89_MKK][0][99] = 127,
+ [1][1][2][1][RTW89_IC][1][99] = 10,
+ [1][1][2][1][RTW89_KCC][1][99] = 32,
+ [1][1][2][1][RTW89_KCC][0][99] = 127,
+ [1][1][2][1][RTW89_ACMA][1][99] = 127,
+ [1][1][2][1][RTW89_ACMA][0][99] = 127,
+ [1][1][2][1][RTW89_CHILE][1][99] = 10,
+ [1][1][2][1][RTW89_QATAR][1][99] = 127,
+ [1][1][2][1][RTW89_QATAR][0][99] = 127,
+ [1][1][2][1][RTW89_UK][1][99] = 127,
+ [1][1][2][1][RTW89_UK][0][99] = 127,
+ [1][1][2][1][RTW89_FCC][1][103] = 10,
+ [1][1][2][1][RTW89_FCC][2][103] = 127,
+ [1][1][2][1][RTW89_ETSI][1][103] = 127,
+ [1][1][2][1][RTW89_ETSI][0][103] = 127,
+ [1][1][2][1][RTW89_MKK][1][103] = 127,
+ [1][1][2][1][RTW89_MKK][0][103] = 127,
+ [1][1][2][1][RTW89_IC][1][103] = 10,
+ [1][1][2][1][RTW89_KCC][1][103] = 32,
+ [1][1][2][1][RTW89_KCC][0][103] = 127,
+ [1][1][2][1][RTW89_ACMA][1][103] = 127,
+ [1][1][2][1][RTW89_ACMA][0][103] = 127,
+ [1][1][2][1][RTW89_CHILE][1][103] = 10,
+ [1][1][2][1][RTW89_QATAR][1][103] = 127,
+ [1][1][2][1][RTW89_QATAR][0][103] = 127,
+ [1][1][2][1][RTW89_UK][1][103] = 127,
+ [1][1][2][1][RTW89_UK][0][103] = 127,
+ [1][1][2][1][RTW89_FCC][1][106] = 12,
+ [1][1][2][1][RTW89_FCC][2][106] = 127,
+ [1][1][2][1][RTW89_ETSI][1][106] = 127,
+ [1][1][2][1][RTW89_ETSI][0][106] = 127,
+ [1][1][2][1][RTW89_MKK][1][106] = 127,
+ [1][1][2][1][RTW89_MKK][0][106] = 127,
+ [1][1][2][1][RTW89_IC][1][106] = 12,
+ [1][1][2][1][RTW89_KCC][1][106] = 32,
+ [1][1][2][1][RTW89_KCC][0][106] = 127,
+ [1][1][2][1][RTW89_ACMA][1][106] = 127,
+ [1][1][2][1][RTW89_ACMA][0][106] = 127,
+ [1][1][2][1][RTW89_CHILE][1][106] = 12,
+ [1][1][2][1][RTW89_QATAR][1][106] = 127,
+ [1][1][2][1][RTW89_QATAR][0][106] = 127,
+ [1][1][2][1][RTW89_UK][1][106] = 127,
+ [1][1][2][1][RTW89_UK][0][106] = 127,
+ [1][1][2][1][RTW89_FCC][1][110] = 127,
+ [1][1][2][1][RTW89_FCC][2][110] = 127,
+ [1][1][2][1][RTW89_ETSI][1][110] = 127,
+ [1][1][2][1][RTW89_ETSI][0][110] = 127,
+ [1][1][2][1][RTW89_MKK][1][110] = 127,
+ [1][1][2][1][RTW89_MKK][0][110] = 127,
+ [1][1][2][1][RTW89_IC][1][110] = 127,
+ [1][1][2][1][RTW89_KCC][1][110] = 127,
+ [1][1][2][1][RTW89_KCC][0][110] = 127,
+ [1][1][2][1][RTW89_ACMA][1][110] = 127,
+ [1][1][2][1][RTW89_ACMA][0][110] = 127,
+ [1][1][2][1][RTW89_CHILE][1][110] = 127,
+ [1][1][2][1][RTW89_QATAR][1][110] = 127,
+ [1][1][2][1][RTW89_QATAR][0][110] = 127,
+ [1][1][2][1][RTW89_UK][1][110] = 127,
+ [1][1][2][1][RTW89_UK][0][110] = 127,
+ [1][1][2][1][RTW89_FCC][1][114] = 127,
+ [1][1][2][1][RTW89_FCC][2][114] = 127,
+ [1][1][2][1][RTW89_ETSI][1][114] = 127,
+ [1][1][2][1][RTW89_ETSI][0][114] = 127,
+ [1][1][2][1][RTW89_MKK][1][114] = 127,
+ [1][1][2][1][RTW89_MKK][0][114] = 127,
+ [1][1][2][1][RTW89_IC][1][114] = 127,
+ [1][1][2][1][RTW89_KCC][1][114] = 127,
+ [1][1][2][1][RTW89_KCC][0][114] = 127,
+ [1][1][2][1][RTW89_ACMA][1][114] = 127,
+ [1][1][2][1][RTW89_ACMA][0][114] = 127,
+ [1][1][2][1][RTW89_CHILE][1][114] = 127,
+ [1][1][2][1][RTW89_QATAR][1][114] = 127,
+ [1][1][2][1][RTW89_QATAR][0][114] = 127,
+ [1][1][2][1][RTW89_UK][1][114] = 127,
+ [1][1][2][1][RTW89_UK][0][114] = 127,
+ [1][1][2][1][RTW89_FCC][1][118] = 127,
+ [1][1][2][1][RTW89_FCC][2][118] = 127,
+ [1][1][2][1][RTW89_ETSI][1][118] = 127,
+ [1][1][2][1][RTW89_ETSI][0][118] = 127,
+ [1][1][2][1][RTW89_MKK][1][118] = 127,
+ [1][1][2][1][RTW89_MKK][0][118] = 127,
+ [1][1][2][1][RTW89_IC][1][118] = 127,
+ [1][1][2][1][RTW89_KCC][1][118] = 127,
+ [1][1][2][1][RTW89_KCC][0][118] = 127,
+ [1][1][2][1][RTW89_ACMA][1][118] = 127,
+ [1][1][2][1][RTW89_ACMA][0][118] = 127,
+ [1][1][2][1][RTW89_CHILE][1][118] = 127,
+ [1][1][2][1][RTW89_QATAR][1][118] = 127,
+ [1][1][2][1][RTW89_QATAR][0][118] = 127,
+ [1][1][2][1][RTW89_UK][1][118] = 127,
+ [1][1][2][1][RTW89_UK][0][118] = 127,
+ [2][0][2][0][RTW89_FCC][1][3] = 46,
+ [2][0][2][0][RTW89_FCC][2][3] = 60,
+ [2][0][2][0][RTW89_ETSI][1][3] = 58,
+ [2][0][2][0][RTW89_ETSI][0][3] = 30,
+ [2][0][2][0][RTW89_MKK][1][3] = 58,
+ [2][0][2][0][RTW89_MKK][0][3] = 26,
+ [2][0][2][0][RTW89_IC][1][3] = 46,
+ [2][0][2][0][RTW89_KCC][1][3] = 50,
+ [2][0][2][0][RTW89_KCC][0][3] = 24,
+ [2][0][2][0][RTW89_ACMA][1][3] = 58,
+ [2][0][2][0][RTW89_ACMA][0][3] = 30,
+ [2][0][2][0][RTW89_CHILE][1][3] = 46,
+ [2][0][2][0][RTW89_QATAR][1][3] = 58,
+ [2][0][2][0][RTW89_QATAR][0][3] = 30,
+ [2][0][2][0][RTW89_UK][1][3] = 58,
+ [2][0][2][0][RTW89_UK][0][3] = 30,
+ [2][0][2][0][RTW89_FCC][1][11] = 46,
+ [2][0][2][0][RTW89_FCC][2][11] = 60,
+ [2][0][2][0][RTW89_ETSI][1][11] = 58,
+ [2][0][2][0][RTW89_ETSI][0][11] = 30,
+ [2][0][2][0][RTW89_MKK][1][11] = 58,
+ [2][0][2][0][RTW89_MKK][0][11] = 24,
+ [2][0][2][0][RTW89_IC][1][11] = 46,
+ [2][0][2][0][RTW89_KCC][1][11] = 50,
+ [2][0][2][0][RTW89_KCC][0][11] = 24,
+ [2][0][2][0][RTW89_ACMA][1][11] = 58,
+ [2][0][2][0][RTW89_ACMA][0][11] = 30,
+ [2][0][2][0][RTW89_CHILE][1][11] = 46,
+ [2][0][2][0][RTW89_QATAR][1][11] = 58,
+ [2][0][2][0][RTW89_QATAR][0][11] = 30,
+ [2][0][2][0][RTW89_UK][1][11] = 58,
+ [2][0][2][0][RTW89_UK][0][11] = 30,
+ [2][0][2][0][RTW89_FCC][1][18] = 46,
+ [2][0][2][0][RTW89_FCC][2][18] = 60,
+ [2][0][2][0][RTW89_ETSI][1][18] = 58,
+ [2][0][2][0][RTW89_ETSI][0][18] = 30,
+ [2][0][2][0][RTW89_MKK][1][18] = 58,
+ [2][0][2][0][RTW89_MKK][0][18] = 24,
+ [2][0][2][0][RTW89_IC][1][18] = 46,
+ [2][0][2][0][RTW89_KCC][1][18] = 50,
+ [2][0][2][0][RTW89_KCC][0][18] = 24,
+ [2][0][2][0][RTW89_ACMA][1][18] = 58,
+ [2][0][2][0][RTW89_ACMA][0][18] = 30,
+ [2][0][2][0][RTW89_CHILE][1][18] = 46,
+ [2][0][2][0][RTW89_QATAR][1][18] = 58,
+ [2][0][2][0][RTW89_QATAR][0][18] = 30,
+ [2][0][2][0][RTW89_UK][1][18] = 58,
+ [2][0][2][0][RTW89_UK][0][18] = 30,
+ [2][0][2][0][RTW89_FCC][1][26] = 46,
+ [2][0][2][0][RTW89_FCC][2][26] = 60,
+ [2][0][2][0][RTW89_ETSI][1][26] = 58,
+ [2][0][2][0][RTW89_ETSI][0][26] = 30,
+ [2][0][2][0][RTW89_MKK][1][26] = 58,
+ [2][0][2][0][RTW89_MKK][0][26] = 24,
+ [2][0][2][0][RTW89_IC][1][26] = 46,
+ [2][0][2][0][RTW89_KCC][1][26] = 50,
+ [2][0][2][0][RTW89_KCC][0][26] = 26,
+ [2][0][2][0][RTW89_ACMA][1][26] = 58,
+ [2][0][2][0][RTW89_ACMA][0][26] = 30,
+ [2][0][2][0][RTW89_CHILE][1][26] = 46,
+ [2][0][2][0][RTW89_QATAR][1][26] = 58,
+ [2][0][2][0][RTW89_QATAR][0][26] = 30,
+ [2][0][2][0][RTW89_UK][1][26] = 58,
+ [2][0][2][0][RTW89_UK][0][26] = 30,
+ [2][0][2][0][RTW89_FCC][1][33] = 46,
+ [2][0][2][0][RTW89_FCC][2][33] = 60,
+ [2][0][2][0][RTW89_ETSI][1][33] = 58,
+ [2][0][2][0][RTW89_ETSI][0][33] = 30,
+ [2][0][2][0][RTW89_MKK][1][33] = 58,
+ [2][0][2][0][RTW89_MKK][0][33] = 24,
+ [2][0][2][0][RTW89_IC][1][33] = 46,
+ [2][0][2][0][RTW89_KCC][1][33] = 50,
+ [2][0][2][0][RTW89_KCC][0][33] = 24,
+ [2][0][2][0][RTW89_ACMA][1][33] = 58,
+ [2][0][2][0][RTW89_ACMA][0][33] = 30,
+ [2][0][2][0][RTW89_CHILE][1][33] = 46,
+ [2][0][2][0][RTW89_QATAR][1][33] = 58,
+ [2][0][2][0][RTW89_QATAR][0][33] = 30,
+ [2][0][2][0][RTW89_UK][1][33] = 58,
+ [2][0][2][0][RTW89_UK][0][33] = 30,
+ [2][0][2][0][RTW89_FCC][1][41] = 46,
+ [2][0][2][0][RTW89_FCC][2][41] = 60,
+ [2][0][2][0][RTW89_ETSI][1][41] = 58,
+ [2][0][2][0][RTW89_ETSI][0][41] = 30,
+ [2][0][2][0][RTW89_MKK][1][41] = 58,
+ [2][0][2][0][RTW89_MKK][0][41] = 24,
+ [2][0][2][0][RTW89_IC][1][41] = 46,
+ [2][0][2][0][RTW89_KCC][1][41] = 50,
+ [2][0][2][0][RTW89_KCC][0][41] = 24,
+ [2][0][2][0][RTW89_ACMA][1][41] = 58,
+ [2][0][2][0][RTW89_ACMA][0][41] = 30,
+ [2][0][2][0][RTW89_CHILE][1][41] = 46,
+ [2][0][2][0][RTW89_QATAR][1][41] = 58,
+ [2][0][2][0][RTW89_QATAR][0][41] = 30,
+ [2][0][2][0][RTW89_UK][1][41] = 58,
+ [2][0][2][0][RTW89_UK][0][41] = 30,
+ [2][0][2][0][RTW89_FCC][1][48] = 46,
+ [2][0][2][0][RTW89_FCC][2][48] = 127,
+ [2][0][2][0][RTW89_ETSI][1][48] = 127,
+ [2][0][2][0][RTW89_ETSI][0][48] = 127,
+ [2][0][2][0][RTW89_MKK][1][48] = 127,
+ [2][0][2][0][RTW89_MKK][0][48] = 127,
+ [2][0][2][0][RTW89_IC][1][48] = 46,
+ [2][0][2][0][RTW89_KCC][1][48] = 48,
+ [2][0][2][0][RTW89_KCC][0][48] = 127,
+ [2][0][2][0][RTW89_ACMA][1][48] = 127,
+ [2][0][2][0][RTW89_ACMA][0][48] = 127,
+ [2][0][2][0][RTW89_CHILE][1][48] = 46,
+ [2][0][2][0][RTW89_QATAR][1][48] = 127,
+ [2][0][2][0][RTW89_QATAR][0][48] = 127,
+ [2][0][2][0][RTW89_UK][1][48] = 127,
+ [2][0][2][0][RTW89_UK][0][48] = 127,
+ [2][0][2][0][RTW89_FCC][1][56] = 46,
+ [2][0][2][0][RTW89_FCC][2][56] = 127,
+ [2][0][2][0][RTW89_ETSI][1][56] = 127,
+ [2][0][2][0][RTW89_ETSI][0][56] = 127,
+ [2][0][2][0][RTW89_MKK][1][56] = 127,
+ [2][0][2][0][RTW89_MKK][0][56] = 127,
+ [2][0][2][0][RTW89_IC][1][56] = 46,
+ [2][0][2][0][RTW89_KCC][1][56] = 48,
+ [2][0][2][0][RTW89_KCC][0][56] = 127,
+ [2][0][2][0][RTW89_ACMA][1][56] = 127,
+ [2][0][2][0][RTW89_ACMA][0][56] = 127,
+ [2][0][2][0][RTW89_CHILE][1][56] = 46,
+ [2][0][2][0][RTW89_QATAR][1][56] = 127,
+ [2][0][2][0][RTW89_QATAR][0][56] = 127,
+ [2][0][2][0][RTW89_UK][1][56] = 127,
+ [2][0][2][0][RTW89_UK][0][56] = 127,
+ [2][0][2][0][RTW89_FCC][1][63] = 46,
+ [2][0][2][0][RTW89_FCC][2][63] = 58,
+ [2][0][2][0][RTW89_ETSI][1][63] = 127,
+ [2][0][2][0][RTW89_ETSI][0][63] = 127,
+ [2][0][2][0][RTW89_MKK][1][63] = 127,
+ [2][0][2][0][RTW89_MKK][0][63] = 127,
+ [2][0][2][0][RTW89_IC][1][63] = 46,
+ [2][0][2][0][RTW89_KCC][1][63] = 48,
+ [2][0][2][0][RTW89_KCC][0][63] = 127,
+ [2][0][2][0][RTW89_ACMA][1][63] = 127,
+ [2][0][2][0][RTW89_ACMA][0][63] = 127,
+ [2][0][2][0][RTW89_CHILE][1][63] = 46,
+ [2][0][2][0][RTW89_QATAR][1][63] = 127,
+ [2][0][2][0][RTW89_QATAR][0][63] = 127,
+ [2][0][2][0][RTW89_UK][1][63] = 127,
+ [2][0][2][0][RTW89_UK][0][63] = 127,
+ [2][0][2][0][RTW89_FCC][1][71] = 46,
+ [2][0][2][0][RTW89_FCC][2][71] = 58,
+ [2][0][2][0][RTW89_ETSI][1][71] = 127,
+ [2][0][2][0][RTW89_ETSI][0][71] = 127,
+ [2][0][2][0][RTW89_MKK][1][71] = 127,
+ [2][0][2][0][RTW89_MKK][0][71] = 127,
+ [2][0][2][0][RTW89_IC][1][71] = 46,
+ [2][0][2][0][RTW89_KCC][1][71] = 48,
+ [2][0][2][0][RTW89_KCC][0][71] = 127,
+ [2][0][2][0][RTW89_ACMA][1][71] = 127,
+ [2][0][2][0][RTW89_ACMA][0][71] = 127,
+ [2][0][2][0][RTW89_CHILE][1][71] = 46,
+ [2][0][2][0][RTW89_QATAR][1][71] = 127,
+ [2][0][2][0][RTW89_QATAR][0][71] = 127,
+ [2][0][2][0][RTW89_UK][1][71] = 127,
+ [2][0][2][0][RTW89_UK][0][71] = 127,
+ [2][0][2][0][RTW89_FCC][1][78] = 46,
+ [2][0][2][0][RTW89_FCC][2][78] = 58,
+ [2][0][2][0][RTW89_ETSI][1][78] = 127,
+ [2][0][2][0][RTW89_ETSI][0][78] = 127,
+ [2][0][2][0][RTW89_MKK][1][78] = 127,
+ [2][0][2][0][RTW89_MKK][0][78] = 127,
+ [2][0][2][0][RTW89_IC][1][78] = 46,
+ [2][0][2][0][RTW89_KCC][1][78] = 52,
+ [2][0][2][0][RTW89_KCC][0][78] = 127,
+ [2][0][2][0][RTW89_ACMA][1][78] = 127,
+ [2][0][2][0][RTW89_ACMA][0][78] = 127,
+ [2][0][2][0][RTW89_CHILE][1][78] = 46,
+ [2][0][2][0][RTW89_QATAR][1][78] = 127,
+ [2][0][2][0][RTW89_QATAR][0][78] = 127,
+ [2][0][2][0][RTW89_UK][1][78] = 127,
+ [2][0][2][0][RTW89_UK][0][78] = 127,
+ [2][0][2][0][RTW89_FCC][1][86] = 46,
+ [2][0][2][0][RTW89_FCC][2][86] = 127,
+ [2][0][2][0][RTW89_ETSI][1][86] = 127,
+ [2][0][2][0][RTW89_ETSI][0][86] = 127,
+ [2][0][2][0][RTW89_MKK][1][86] = 127,
+ [2][0][2][0][RTW89_MKK][0][86] = 127,
+ [2][0][2][0][RTW89_IC][1][86] = 46,
+ [2][0][2][0][RTW89_KCC][1][86] = 52,
+ [2][0][2][0][RTW89_KCC][0][86] = 127,
+ [2][0][2][0][RTW89_ACMA][1][86] = 127,
+ [2][0][2][0][RTW89_ACMA][0][86] = 127,
+ [2][0][2][0][RTW89_CHILE][1][86] = 46,
+ [2][0][2][0][RTW89_QATAR][1][86] = 127,
+ [2][0][2][0][RTW89_QATAR][0][86] = 127,
+ [2][0][2][0][RTW89_UK][1][86] = 127,
+ [2][0][2][0][RTW89_UK][0][86] = 127,
+ [2][0][2][0][RTW89_FCC][1][93] = 46,
+ [2][0][2][0][RTW89_FCC][2][93] = 127,
+ [2][0][2][0][RTW89_ETSI][1][93] = 127,
+ [2][0][2][0][RTW89_ETSI][0][93] = 127,
+ [2][0][2][0][RTW89_MKK][1][93] = 127,
+ [2][0][2][0][RTW89_MKK][0][93] = 127,
+ [2][0][2][0][RTW89_IC][1][93] = 46,
+ [2][0][2][0][RTW89_KCC][1][93] = 50,
+ [2][0][2][0][RTW89_KCC][0][93] = 127,
+ [2][0][2][0][RTW89_ACMA][1][93] = 127,
+ [2][0][2][0][RTW89_ACMA][0][93] = 127,
+ [2][0][2][0][RTW89_CHILE][1][93] = 46,
+ [2][0][2][0][RTW89_QATAR][1][93] = 127,
+ [2][0][2][0][RTW89_QATAR][0][93] = 127,
+ [2][0][2][0][RTW89_UK][1][93] = 127,
+ [2][0][2][0][RTW89_UK][0][93] = 127,
+ [2][0][2][0][RTW89_FCC][1][101] = 44,
+ [2][0][2][0][RTW89_FCC][2][101] = 127,
+ [2][0][2][0][RTW89_ETSI][1][101] = 127,
+ [2][0][2][0][RTW89_ETSI][0][101] = 127,
+ [2][0][2][0][RTW89_MKK][1][101] = 127,
+ [2][0][2][0][RTW89_MKK][0][101] = 127,
+ [2][0][2][0][RTW89_IC][1][101] = 44,
+ [2][0][2][0][RTW89_KCC][1][101] = 50,
+ [2][0][2][0][RTW89_KCC][0][101] = 127,
+ [2][0][2][0][RTW89_ACMA][1][101] = 127,
+ [2][0][2][0][RTW89_ACMA][0][101] = 127,
+ [2][0][2][0][RTW89_CHILE][1][101] = 44,
+ [2][0][2][0][RTW89_QATAR][1][101] = 127,
+ [2][0][2][0][RTW89_QATAR][0][101] = 127,
+ [2][0][2][0][RTW89_UK][1][101] = 127,
+ [2][0][2][0][RTW89_UK][0][101] = 127,
+ [2][0][2][0][RTW89_FCC][1][108] = 127,
+ [2][0][2][0][RTW89_FCC][2][108] = 127,
+ [2][0][2][0][RTW89_ETSI][1][108] = 127,
+ [2][0][2][0][RTW89_ETSI][0][108] = 127,
+ [2][0][2][0][RTW89_MKK][1][108] = 127,
+ [2][0][2][0][RTW89_MKK][0][108] = 127,
+ [2][0][2][0][RTW89_IC][1][108] = 127,
+ [2][0][2][0][RTW89_KCC][1][108] = 127,
+ [2][0][2][0][RTW89_KCC][0][108] = 127,
+ [2][0][2][0][RTW89_ACMA][1][108] = 127,
+ [2][0][2][0][RTW89_ACMA][0][108] = 127,
+ [2][0][2][0][RTW89_CHILE][1][108] = 127,
+ [2][0][2][0][RTW89_QATAR][1][108] = 127,
+ [2][0][2][0][RTW89_QATAR][0][108] = 127,
+ [2][0][2][0][RTW89_UK][1][108] = 127,
+ [2][0][2][0][RTW89_UK][0][108] = 127,
+ [2][0][2][0][RTW89_FCC][1][116] = 127,
+ [2][0][2][0][RTW89_FCC][2][116] = 127,
+ [2][0][2][0][RTW89_ETSI][1][116] = 127,
+ [2][0][2][0][RTW89_ETSI][0][116] = 127,
+ [2][0][2][0][RTW89_MKK][1][116] = 127,
+ [2][0][2][0][RTW89_MKK][0][116] = 127,
+ [2][0][2][0][RTW89_IC][1][116] = 127,
+ [2][0][2][0][RTW89_KCC][1][116] = 127,
+ [2][0][2][0][RTW89_KCC][0][116] = 127,
+ [2][0][2][0][RTW89_ACMA][1][116] = 127,
+ [2][0][2][0][RTW89_ACMA][0][116] = 127,
+ [2][0][2][0][RTW89_CHILE][1][116] = 127,
+ [2][0][2][0][RTW89_QATAR][1][116] = 127,
+ [2][0][2][0][RTW89_QATAR][0][116] = 127,
+ [2][0][2][0][RTW89_UK][1][116] = 127,
+ [2][0][2][0][RTW89_UK][0][116] = 127,
+ [2][1][2][0][RTW89_FCC][1][3] = 22,
+ [2][1][2][0][RTW89_FCC][2][3] = 50,
+ [2][1][2][0][RTW89_ETSI][1][3] = 54,
+ [2][1][2][0][RTW89_ETSI][0][3] = 16,
+ [2][1][2][0][RTW89_MKK][1][3] = 52,
+ [2][1][2][0][RTW89_MKK][0][3] = 14,
+ [2][1][2][0][RTW89_IC][1][3] = 22,
+ [2][1][2][0][RTW89_KCC][1][3] = 38,
+ [2][1][2][0][RTW89_KCC][0][3] = 12,
+ [2][1][2][0][RTW89_ACMA][1][3] = 54,
+ [2][1][2][0][RTW89_ACMA][0][3] = 16,
+ [2][1][2][0][RTW89_CHILE][1][3] = 22,
+ [2][1][2][0][RTW89_QATAR][1][3] = 54,
+ [2][1][2][0][RTW89_QATAR][0][3] = 16,
+ [2][1][2][0][RTW89_UK][1][3] = 54,
+ [2][1][2][0][RTW89_UK][0][3] = 16,
+ [2][1][2][0][RTW89_FCC][1][11] = 20,
+ [2][1][2][0][RTW89_FCC][2][11] = 50,
+ [2][1][2][0][RTW89_ETSI][1][11] = 54,
+ [2][1][2][0][RTW89_ETSI][0][11] = 16,
+ [2][1][2][0][RTW89_MKK][1][11] = 52,
+ [2][1][2][0][RTW89_MKK][0][11] = 12,
+ [2][1][2][0][RTW89_IC][1][11] = 20,
+ [2][1][2][0][RTW89_KCC][1][11] = 38,
+ [2][1][2][0][RTW89_KCC][0][11] = 12,
+ [2][1][2][0][RTW89_ACMA][1][11] = 54,
+ [2][1][2][0][RTW89_ACMA][0][11] = 16,
+ [2][1][2][0][RTW89_CHILE][1][11] = 20,
+ [2][1][2][0][RTW89_QATAR][1][11] = 54,
+ [2][1][2][0][RTW89_QATAR][0][11] = 16,
+ [2][1][2][0][RTW89_UK][1][11] = 54,
+ [2][1][2][0][RTW89_UK][0][11] = 16,
+ [2][1][2][0][RTW89_FCC][1][18] = 20,
+ [2][1][2][0][RTW89_FCC][2][18] = 50,
+ [2][1][2][0][RTW89_ETSI][1][18] = 54,
+ [2][1][2][0][RTW89_ETSI][0][18] = 16,
+ [2][1][2][0][RTW89_MKK][1][18] = 52,
+ [2][1][2][0][RTW89_MKK][0][18] = 12,
+ [2][1][2][0][RTW89_IC][1][18] = 20,
+ [2][1][2][0][RTW89_KCC][1][18] = 38,
+ [2][1][2][0][RTW89_KCC][0][18] = 12,
+ [2][1][2][0][RTW89_ACMA][1][18] = 54,
+ [2][1][2][0][RTW89_ACMA][0][18] = 16,
+ [2][1][2][0][RTW89_CHILE][1][18] = 20,
+ [2][1][2][0][RTW89_QATAR][1][18] = 54,
+ [2][1][2][0][RTW89_QATAR][0][18] = 16,
+ [2][1][2][0][RTW89_UK][1][18] = 54,
+ [2][1][2][0][RTW89_UK][0][18] = 16,
+ [2][1][2][0][RTW89_FCC][1][26] = 20,
+ [2][1][2][0][RTW89_FCC][2][26] = 60,
+ [2][1][2][0][RTW89_ETSI][1][26] = 54,
+ [2][1][2][0][RTW89_ETSI][0][26] = 16,
+ [2][1][2][0][RTW89_MKK][1][26] = 52,
+ [2][1][2][0][RTW89_MKK][0][26] = 12,
+ [2][1][2][0][RTW89_IC][1][26] = 20,
+ [2][1][2][0][RTW89_KCC][1][26] = 38,
+ [2][1][2][0][RTW89_KCC][0][26] = 12,
+ [2][1][2][0][RTW89_ACMA][1][26] = 54,
+ [2][1][2][0][RTW89_ACMA][0][26] = 16,
+ [2][1][2][0][RTW89_CHILE][1][26] = 20,
+ [2][1][2][0][RTW89_QATAR][1][26] = 54,
+ [2][1][2][0][RTW89_QATAR][0][26] = 16,
+ [2][1][2][0][RTW89_UK][1][26] = 54,
+ [2][1][2][0][RTW89_UK][0][26] = 16,
+ [2][1][2][0][RTW89_FCC][1][33] = 20,
+ [2][1][2][0][RTW89_FCC][2][33] = 60,
+ [2][1][2][0][RTW89_ETSI][1][33] = 54,
+ [2][1][2][0][RTW89_ETSI][0][33] = 16,
+ [2][1][2][0][RTW89_MKK][1][33] = 48,
+ [2][1][2][0][RTW89_MKK][0][33] = 12,
+ [2][1][2][0][RTW89_IC][1][33] = 20,
+ [2][1][2][0][RTW89_KCC][1][33] = 38,
+ [2][1][2][0][RTW89_KCC][0][33] = 12,
+ [2][1][2][0][RTW89_ACMA][1][33] = 54,
+ [2][1][2][0][RTW89_ACMA][0][33] = 16,
+ [2][1][2][0][RTW89_CHILE][1][33] = 20,
+ [2][1][2][0][RTW89_QATAR][1][33] = 54,
+ [2][1][2][0][RTW89_QATAR][0][33] = 16,
+ [2][1][2][0][RTW89_UK][1][33] = 54,
+ [2][1][2][0][RTW89_UK][0][33] = 16,
+ [2][1][2][0][RTW89_FCC][1][41] = 22,
+ [2][1][2][0][RTW89_FCC][2][41] = 60,
+ [2][1][2][0][RTW89_ETSI][1][41] = 54,
+ [2][1][2][0][RTW89_ETSI][0][41] = 18,
+ [2][1][2][0][RTW89_MKK][1][41] = 48,
+ [2][1][2][0][RTW89_MKK][0][41] = 12,
+ [2][1][2][0][RTW89_IC][1][41] = 22,
+ [2][1][2][0][RTW89_KCC][1][41] = 38,
+ [2][1][2][0][RTW89_KCC][0][41] = 12,
+ [2][1][2][0][RTW89_ACMA][1][41] = 54,
+ [2][1][2][0][RTW89_ACMA][0][41] = 18,
+ [2][1][2][0][RTW89_CHILE][1][41] = 22,
+ [2][1][2][0][RTW89_QATAR][1][41] = 54,
+ [2][1][2][0][RTW89_QATAR][0][41] = 18,
+ [2][1][2][0][RTW89_UK][1][41] = 54,
+ [2][1][2][0][RTW89_UK][0][41] = 18,
+ [2][1][2][0][RTW89_FCC][1][48] = 22,
+ [2][1][2][0][RTW89_FCC][2][48] = 127,
+ [2][1][2][0][RTW89_ETSI][1][48] = 127,
+ [2][1][2][0][RTW89_ETSI][0][48] = 127,
+ [2][1][2][0][RTW89_MKK][1][48] = 127,
+ [2][1][2][0][RTW89_MKK][0][48] = 127,
+ [2][1][2][0][RTW89_IC][1][48] = 22,
+ [2][1][2][0][RTW89_KCC][1][48] = 38,
+ [2][1][2][0][RTW89_KCC][0][48] = 127,
+ [2][1][2][0][RTW89_ACMA][1][48] = 127,
+ [2][1][2][0][RTW89_ACMA][0][48] = 127,
+ [2][1][2][0][RTW89_CHILE][1][48] = 22,
+ [2][1][2][0][RTW89_QATAR][1][48] = 127,
+ [2][1][2][0][RTW89_QATAR][0][48] = 127,
+ [2][1][2][0][RTW89_UK][1][48] = 127,
+ [2][1][2][0][RTW89_UK][0][48] = 127,
+ [2][1][2][0][RTW89_FCC][1][56] = 20,
+ [2][1][2][0][RTW89_FCC][2][56] = 127,
+ [2][1][2][0][RTW89_ETSI][1][56] = 127,
+ [2][1][2][0][RTW89_ETSI][0][56] = 127,
+ [2][1][2][0][RTW89_MKK][1][56] = 127,
+ [2][1][2][0][RTW89_MKK][0][56] = 127,
+ [2][1][2][0][RTW89_IC][1][56] = 20,
+ [2][1][2][0][RTW89_KCC][1][56] = 38,
+ [2][1][2][0][RTW89_KCC][0][56] = 127,
+ [2][1][2][0][RTW89_ACMA][1][56] = 127,
+ [2][1][2][0][RTW89_ACMA][0][56] = 127,
+ [2][1][2][0][RTW89_CHILE][1][56] = 20,
+ [2][1][2][0][RTW89_QATAR][1][56] = 127,
+ [2][1][2][0][RTW89_QATAR][0][56] = 127,
+ [2][1][2][0][RTW89_UK][1][56] = 127,
+ [2][1][2][0][RTW89_UK][0][56] = 127,
+ [2][1][2][0][RTW89_FCC][1][63] = 22,
+ [2][1][2][0][RTW89_FCC][2][63] = 58,
+ [2][1][2][0][RTW89_ETSI][1][63] = 127,
+ [2][1][2][0][RTW89_ETSI][0][63] = 127,
+ [2][1][2][0][RTW89_MKK][1][63] = 127,
+ [2][1][2][0][RTW89_MKK][0][63] = 127,
+ [2][1][2][0][RTW89_IC][1][63] = 22,
+ [2][1][2][0][RTW89_KCC][1][63] = 38,
+ [2][1][2][0][RTW89_KCC][0][63] = 127,
+ [2][1][2][0][RTW89_ACMA][1][63] = 127,
+ [2][1][2][0][RTW89_ACMA][0][63] = 127,
+ [2][1][2][0][RTW89_CHILE][1][63] = 22,
+ [2][1][2][0][RTW89_QATAR][1][63] = 127,
+ [2][1][2][0][RTW89_QATAR][0][63] = 127,
+ [2][1][2][0][RTW89_UK][1][63] = 127,
+ [2][1][2][0][RTW89_UK][0][63] = 127,
+ [2][1][2][0][RTW89_FCC][1][71] = 20,
+ [2][1][2][0][RTW89_FCC][2][71] = 58,
+ [2][1][2][0][RTW89_ETSI][1][71] = 127,
+ [2][1][2][0][RTW89_ETSI][0][71] = 127,
+ [2][1][2][0][RTW89_MKK][1][71] = 127,
+ [2][1][2][0][RTW89_MKK][0][71] = 127,
+ [2][1][2][0][RTW89_IC][1][71] = 20,
+ [2][1][2][0][RTW89_KCC][1][71] = 38,
+ [2][1][2][0][RTW89_KCC][0][71] = 127,
+ [2][1][2][0][RTW89_ACMA][1][71] = 127,
+ [2][1][2][0][RTW89_ACMA][0][71] = 127,
+ [2][1][2][0][RTW89_CHILE][1][71] = 20,
+ [2][1][2][0][RTW89_QATAR][1][71] = 127,
+ [2][1][2][0][RTW89_QATAR][0][71] = 127,
+ [2][1][2][0][RTW89_UK][1][71] = 127,
+ [2][1][2][0][RTW89_UK][0][71] = 127,
+ [2][1][2][0][RTW89_FCC][1][78] = 20,
+ [2][1][2][0][RTW89_FCC][2][78] = 58,
+ [2][1][2][0][RTW89_ETSI][1][78] = 127,
+ [2][1][2][0][RTW89_ETSI][0][78] = 127,
+ [2][1][2][0][RTW89_MKK][1][78] = 127,
+ [2][1][2][0][RTW89_MKK][0][78] = 127,
+ [2][1][2][0][RTW89_IC][1][78] = 20,
+ [2][1][2][0][RTW89_KCC][1][78] = 38,
+ [2][1][2][0][RTW89_KCC][0][78] = 127,
+ [2][1][2][0][RTW89_ACMA][1][78] = 127,
+ [2][1][2][0][RTW89_ACMA][0][78] = 127,
+ [2][1][2][0][RTW89_CHILE][1][78] = 20,
+ [2][1][2][0][RTW89_QATAR][1][78] = 127,
+ [2][1][2][0][RTW89_QATAR][0][78] = 127,
+ [2][1][2][0][RTW89_UK][1][78] = 127,
+ [2][1][2][0][RTW89_UK][0][78] = 127,
+ [2][1][2][0][RTW89_FCC][1][86] = 20,
+ [2][1][2][0][RTW89_FCC][2][86] = 127,
+ [2][1][2][0][RTW89_ETSI][1][86] = 127,
+ [2][1][2][0][RTW89_ETSI][0][86] = 127,
+ [2][1][2][0][RTW89_MKK][1][86] = 127,
+ [2][1][2][0][RTW89_MKK][0][86] = 127,
+ [2][1][2][0][RTW89_IC][1][86] = 20,
+ [2][1][2][0][RTW89_KCC][1][86] = 38,
+ [2][1][2][0][RTW89_KCC][0][86] = 127,
+ [2][1][2][0][RTW89_ACMA][1][86] = 127,
+ [2][1][2][0][RTW89_ACMA][0][86] = 127,
+ [2][1][2][0][RTW89_CHILE][1][86] = 20,
+ [2][1][2][0][RTW89_QATAR][1][86] = 127,
+ [2][1][2][0][RTW89_QATAR][0][86] = 127,
+ [2][1][2][0][RTW89_UK][1][86] = 127,
+ [2][1][2][0][RTW89_UK][0][86] = 127,
+ [2][1][2][0][RTW89_FCC][1][93] = 22,
+ [2][1][2][0][RTW89_FCC][2][93] = 127,
+ [2][1][2][0][RTW89_ETSI][1][93] = 127,
+ [2][1][2][0][RTW89_ETSI][0][93] = 127,
+ [2][1][2][0][RTW89_MKK][1][93] = 127,
+ [2][1][2][0][RTW89_MKK][0][93] = 127,
+ [2][1][2][0][RTW89_IC][1][93] = 22,
+ [2][1][2][0][RTW89_KCC][1][93] = 38,
+ [2][1][2][0][RTW89_KCC][0][93] = 127,
+ [2][1][2][0][RTW89_ACMA][1][93] = 127,
+ [2][1][2][0][RTW89_ACMA][0][93] = 127,
+ [2][1][2][0][RTW89_CHILE][1][93] = 22,
+ [2][1][2][0][RTW89_QATAR][1][93] = 127,
+ [2][1][2][0][RTW89_QATAR][0][93] = 127,
+ [2][1][2][0][RTW89_UK][1][93] = 127,
+ [2][1][2][0][RTW89_UK][0][93] = 127,
+ [2][1][2][0][RTW89_FCC][1][101] = 22,
+ [2][1][2][0][RTW89_FCC][2][101] = 127,
+ [2][1][2][0][RTW89_ETSI][1][101] = 127,
+ [2][1][2][0][RTW89_ETSI][0][101] = 127,
+ [2][1][2][0][RTW89_MKK][1][101] = 127,
+ [2][1][2][0][RTW89_MKK][0][101] = 127,
+ [2][1][2][0][RTW89_IC][1][101] = 22,
+ [2][1][2][0][RTW89_KCC][1][101] = 38,
+ [2][1][2][0][RTW89_KCC][0][101] = 127,
+ [2][1][2][0][RTW89_ACMA][1][101] = 127,
+ [2][1][2][0][RTW89_ACMA][0][101] = 127,
+ [2][1][2][0][RTW89_CHILE][1][101] = 22,
+ [2][1][2][0][RTW89_QATAR][1][101] = 127,
+ [2][1][2][0][RTW89_QATAR][0][101] = 127,
+ [2][1][2][0][RTW89_UK][1][101] = 127,
+ [2][1][2][0][RTW89_UK][0][101] = 127,
+ [2][1][2][0][RTW89_FCC][1][108] = 127,
+ [2][1][2][0][RTW89_FCC][2][108] = 127,
+ [2][1][2][0][RTW89_ETSI][1][108] = 127,
+ [2][1][2][0][RTW89_ETSI][0][108] = 127,
+ [2][1][2][0][RTW89_MKK][1][108] = 127,
+ [2][1][2][0][RTW89_MKK][0][108] = 127,
+ [2][1][2][0][RTW89_IC][1][108] = 127,
+ [2][1][2][0][RTW89_KCC][1][108] = 127,
+ [2][1][2][0][RTW89_KCC][0][108] = 127,
+ [2][1][2][0][RTW89_ACMA][1][108] = 127,
+ [2][1][2][0][RTW89_ACMA][0][108] = 127,
+ [2][1][2][0][RTW89_CHILE][1][108] = 127,
+ [2][1][2][0][RTW89_QATAR][1][108] = 127,
+ [2][1][2][0][RTW89_QATAR][0][108] = 127,
+ [2][1][2][0][RTW89_UK][1][108] = 127,
+ [2][1][2][0][RTW89_UK][0][108] = 127,
+ [2][1][2][0][RTW89_FCC][1][116] = 127,
+ [2][1][2][0][RTW89_FCC][2][116] = 127,
+ [2][1][2][0][RTW89_ETSI][1][116] = 127,
+ [2][1][2][0][RTW89_ETSI][0][116] = 127,
+ [2][1][2][0][RTW89_MKK][1][116] = 127,
+ [2][1][2][0][RTW89_MKK][0][116] = 127,
+ [2][1][2][0][RTW89_IC][1][116] = 127,
+ [2][1][2][0][RTW89_KCC][1][116] = 127,
+ [2][1][2][0][RTW89_KCC][0][116] = 127,
+ [2][1][2][0][RTW89_ACMA][1][116] = 127,
+ [2][1][2][0][RTW89_ACMA][0][116] = 127,
+ [2][1][2][0][RTW89_CHILE][1][116] = 127,
+ [2][1][2][0][RTW89_QATAR][1][116] = 127,
+ [2][1][2][0][RTW89_QATAR][0][116] = 127,
+ [2][1][2][0][RTW89_UK][1][116] = 127,
+ [2][1][2][0][RTW89_UK][0][116] = 127,
+ [2][1][2][1][RTW89_FCC][1][3] = 22,
+ [2][1][2][1][RTW89_FCC][2][3] = 50,
+ [2][1][2][1][RTW89_ETSI][1][3] = 42,
+ [2][1][2][1][RTW89_ETSI][0][3] = 6,
+ [2][1][2][1][RTW89_MKK][1][3] = 52,
+ [2][1][2][1][RTW89_MKK][0][3] = 14,
+ [2][1][2][1][RTW89_IC][1][3] = 22,
+ [2][1][2][1][RTW89_KCC][1][3] = 38,
+ [2][1][2][1][RTW89_KCC][0][3] = 12,
+ [2][1][2][1][RTW89_ACMA][1][3] = 42,
+ [2][1][2][1][RTW89_ACMA][0][3] = 6,
+ [2][1][2][1][RTW89_CHILE][1][3] = 22,
+ [2][1][2][1][RTW89_QATAR][1][3] = 42,
+ [2][1][2][1][RTW89_QATAR][0][3] = 6,
+ [2][1][2][1][RTW89_UK][1][3] = 42,
+ [2][1][2][1][RTW89_UK][0][3] = 6,
+ [2][1][2][1][RTW89_FCC][1][11] = 20,
+ [2][1][2][1][RTW89_FCC][2][11] = 50,
+ [2][1][2][1][RTW89_ETSI][1][11] = 42,
+ [2][1][2][1][RTW89_ETSI][0][11] = 6,
+ [2][1][2][1][RTW89_MKK][1][11] = 52,
+ [2][1][2][1][RTW89_MKK][0][11] = 12,
+ [2][1][2][1][RTW89_IC][1][11] = 20,
+ [2][1][2][1][RTW89_KCC][1][11] = 38,
+ [2][1][2][1][RTW89_KCC][0][11] = 12,
+ [2][1][2][1][RTW89_ACMA][1][11] = 42,
+ [2][1][2][1][RTW89_ACMA][0][11] = 6,
+ [2][1][2][1][RTW89_CHILE][1][11] = 20,
+ [2][1][2][1][RTW89_QATAR][1][11] = 42,
+ [2][1][2][1][RTW89_QATAR][0][11] = 6,
+ [2][1][2][1][RTW89_UK][1][11] = 42,
+ [2][1][2][1][RTW89_UK][0][11] = 6,
+ [2][1][2][1][RTW89_FCC][1][18] = 20,
+ [2][1][2][1][RTW89_FCC][2][18] = 50,
+ [2][1][2][1][RTW89_ETSI][1][18] = 42,
+ [2][1][2][1][RTW89_ETSI][0][18] = 6,
+ [2][1][2][1][RTW89_MKK][1][18] = 52,
+ [2][1][2][1][RTW89_MKK][0][18] = 12,
+ [2][1][2][1][RTW89_IC][1][18] = 20,
+ [2][1][2][1][RTW89_KCC][1][18] = 38,
+ [2][1][2][1][RTW89_KCC][0][18] = 12,
+ [2][1][2][1][RTW89_ACMA][1][18] = 42,
+ [2][1][2][1][RTW89_ACMA][0][18] = 6,
+ [2][1][2][1][RTW89_CHILE][1][18] = 20,
+ [2][1][2][1][RTW89_QATAR][1][18] = 42,
+ [2][1][2][1][RTW89_QATAR][0][18] = 6,
+ [2][1][2][1][RTW89_UK][1][18] = 42,
+ [2][1][2][1][RTW89_UK][0][18] = 6,
+ [2][1][2][1][RTW89_FCC][1][26] = 20,
+ [2][1][2][1][RTW89_FCC][2][26] = 60,
+ [2][1][2][1][RTW89_ETSI][1][26] = 42,
+ [2][1][2][1][RTW89_ETSI][0][26] = 6,
+ [2][1][2][1][RTW89_MKK][1][26] = 52,
+ [2][1][2][1][RTW89_MKK][0][26] = 12,
+ [2][1][2][1][RTW89_IC][1][26] = 20,
+ [2][1][2][1][RTW89_KCC][1][26] = 38,
+ [2][1][2][1][RTW89_KCC][0][26] = 12,
+ [2][1][2][1][RTW89_ACMA][1][26] = 42,
+ [2][1][2][1][RTW89_ACMA][0][26] = 6,
+ [2][1][2][1][RTW89_CHILE][1][26] = 20,
+ [2][1][2][1][RTW89_QATAR][1][26] = 42,
+ [2][1][2][1][RTW89_QATAR][0][26] = 6,
+ [2][1][2][1][RTW89_UK][1][26] = 42,
+ [2][1][2][1][RTW89_UK][0][26] = 6,
+ [2][1][2][1][RTW89_FCC][1][33] = 20,
+ [2][1][2][1][RTW89_FCC][2][33] = 60,
+ [2][1][2][1][RTW89_ETSI][1][33] = 42,
+ [2][1][2][1][RTW89_ETSI][0][33] = 6,
+ [2][1][2][1][RTW89_MKK][1][33] = 48,
+ [2][1][2][1][RTW89_MKK][0][33] = 12,
+ [2][1][2][1][RTW89_IC][1][33] = 20,
+ [2][1][2][1][RTW89_KCC][1][33] = 38,
+ [2][1][2][1][RTW89_KCC][0][33] = 12,
+ [2][1][2][1][RTW89_ACMA][1][33] = 42,
+ [2][1][2][1][RTW89_ACMA][0][33] = 6,
+ [2][1][2][1][RTW89_CHILE][1][33] = 20,
+ [2][1][2][1][RTW89_QATAR][1][33] = 42,
+ [2][1][2][1][RTW89_QATAR][0][33] = 6,
+ [2][1][2][1][RTW89_UK][1][33] = 42,
+ [2][1][2][1][RTW89_UK][0][33] = 6,
+ [2][1][2][1][RTW89_FCC][1][41] = 22,
+ [2][1][2][1][RTW89_FCC][2][41] = 60,
+ [2][1][2][1][RTW89_ETSI][1][41] = 42,
+ [2][1][2][1][RTW89_ETSI][0][41] = 6,
+ [2][1][2][1][RTW89_MKK][1][41] = 48,
+ [2][1][2][1][RTW89_MKK][0][41] = 12,
+ [2][1][2][1][RTW89_IC][1][41] = 22,
+ [2][1][2][1][RTW89_KCC][1][41] = 38,
+ [2][1][2][1][RTW89_KCC][0][41] = 12,
+ [2][1][2][1][RTW89_ACMA][1][41] = 42,
+ [2][1][2][1][RTW89_ACMA][0][41] = 6,
+ [2][1][2][1][RTW89_CHILE][1][41] = 22,
+ [2][1][2][1][RTW89_QATAR][1][41] = 42,
+ [2][1][2][1][RTW89_QATAR][0][41] = 6,
+ [2][1][2][1][RTW89_UK][1][41] = 42,
+ [2][1][2][1][RTW89_UK][0][41] = 6,
+ [2][1][2][1][RTW89_FCC][1][48] = 22,
+ [2][1][2][1][RTW89_FCC][2][48] = 127,
+ [2][1][2][1][RTW89_ETSI][1][48] = 127,
+ [2][1][2][1][RTW89_ETSI][0][48] = 127,
+ [2][1][2][1][RTW89_MKK][1][48] = 127,
+ [2][1][2][1][RTW89_MKK][0][48] = 127,
+ [2][1][2][1][RTW89_IC][1][48] = 22,
+ [2][1][2][1][RTW89_KCC][1][48] = 38,
+ [2][1][2][1][RTW89_KCC][0][48] = 127,
+ [2][1][2][1][RTW89_ACMA][1][48] = 127,
+ [2][1][2][1][RTW89_ACMA][0][48] = 127,
+ [2][1][2][1][RTW89_CHILE][1][48] = 22,
+ [2][1][2][1][RTW89_QATAR][1][48] = 127,
+ [2][1][2][1][RTW89_QATAR][0][48] = 127,
+ [2][1][2][1][RTW89_UK][1][48] = 127,
+ [2][1][2][1][RTW89_UK][0][48] = 127,
+ [2][1][2][1][RTW89_FCC][1][56] = 20,
+ [2][1][2][1][RTW89_FCC][2][56] = 127,
+ [2][1][2][1][RTW89_ETSI][1][56] = 127,
+ [2][1][2][1][RTW89_ETSI][0][56] = 127,
+ [2][1][2][1][RTW89_MKK][1][56] = 127,
+ [2][1][2][1][RTW89_MKK][0][56] = 127,
+ [2][1][2][1][RTW89_IC][1][56] = 20,
+ [2][1][2][1][RTW89_KCC][1][56] = 38,
+ [2][1][2][1][RTW89_KCC][0][56] = 127,
+ [2][1][2][1][RTW89_ACMA][1][56] = 127,
+ [2][1][2][1][RTW89_ACMA][0][56] = 127,
+ [2][1][2][1][RTW89_CHILE][1][56] = 20,
+ [2][1][2][1][RTW89_QATAR][1][56] = 127,
+ [2][1][2][1][RTW89_QATAR][0][56] = 127,
+ [2][1][2][1][RTW89_UK][1][56] = 127,
+ [2][1][2][1][RTW89_UK][0][56] = 127,
+ [2][1][2][1][RTW89_FCC][1][63] = 22,
+ [2][1][2][1][RTW89_FCC][2][63] = 58,
+ [2][1][2][1][RTW89_ETSI][1][63] = 127,
+ [2][1][2][1][RTW89_ETSI][0][63] = 127,
+ [2][1][2][1][RTW89_MKK][1][63] = 127,
+ [2][1][2][1][RTW89_MKK][0][63] = 127,
+ [2][1][2][1][RTW89_IC][1][63] = 22,
+ [2][1][2][1][RTW89_KCC][1][63] = 38,
+ [2][1][2][1][RTW89_KCC][0][63] = 127,
+ [2][1][2][1][RTW89_ACMA][1][63] = 127,
+ [2][1][2][1][RTW89_ACMA][0][63] = 127,
+ [2][1][2][1][RTW89_CHILE][1][63] = 22,
+ [2][1][2][1][RTW89_QATAR][1][63] = 127,
+ [2][1][2][1][RTW89_QATAR][0][63] = 127,
+ [2][1][2][1][RTW89_UK][1][63] = 127,
+ [2][1][2][1][RTW89_UK][0][63] = 127,
+ [2][1][2][1][RTW89_FCC][1][71] = 20,
+ [2][1][2][1][RTW89_FCC][2][71] = 58,
+ [2][1][2][1][RTW89_ETSI][1][71] = 127,
+ [2][1][2][1][RTW89_ETSI][0][71] = 127,
+ [2][1][2][1][RTW89_MKK][1][71] = 127,
+ [2][1][2][1][RTW89_MKK][0][71] = 127,
+ [2][1][2][1][RTW89_IC][1][71] = 20,
+ [2][1][2][1][RTW89_KCC][1][71] = 38,
+ [2][1][2][1][RTW89_KCC][0][71] = 127,
+ [2][1][2][1][RTW89_ACMA][1][71] = 127,
+ [2][1][2][1][RTW89_ACMA][0][71] = 127,
+ [2][1][2][1][RTW89_CHILE][1][71] = 20,
+ [2][1][2][1][RTW89_QATAR][1][71] = 127,
+ [2][1][2][1][RTW89_QATAR][0][71] = 127,
+ [2][1][2][1][RTW89_UK][1][71] = 127,
+ [2][1][2][1][RTW89_UK][0][71] = 127,
+ [2][1][2][1][RTW89_FCC][1][78] = 20,
+ [2][1][2][1][RTW89_FCC][2][78] = 58,
+ [2][1][2][1][RTW89_ETSI][1][78] = 127,
+ [2][1][2][1][RTW89_ETSI][0][78] = 127,
+ [2][1][2][1][RTW89_MKK][1][78] = 127,
+ [2][1][2][1][RTW89_MKK][0][78] = 127,
+ [2][1][2][1][RTW89_IC][1][78] = 20,
+ [2][1][2][1][RTW89_KCC][1][78] = 38,
+ [2][1][2][1][RTW89_KCC][0][78] = 127,
+ [2][1][2][1][RTW89_ACMA][1][78] = 127,
+ [2][1][2][1][RTW89_ACMA][0][78] = 127,
+ [2][1][2][1][RTW89_CHILE][1][78] = 20,
+ [2][1][2][1][RTW89_QATAR][1][78] = 127,
+ [2][1][2][1][RTW89_QATAR][0][78] = 127,
+ [2][1][2][1][RTW89_UK][1][78] = 127,
+ [2][1][2][1][RTW89_UK][0][78] = 127,
+ [2][1][2][1][RTW89_FCC][1][86] = 20,
+ [2][1][2][1][RTW89_FCC][2][86] = 127,
+ [2][1][2][1][RTW89_ETSI][1][86] = 127,
+ [2][1][2][1][RTW89_ETSI][0][86] = 127,
+ [2][1][2][1][RTW89_MKK][1][86] = 127,
+ [2][1][2][1][RTW89_MKK][0][86] = 127,
+ [2][1][2][1][RTW89_IC][1][86] = 20,
+ [2][1][2][1][RTW89_KCC][1][86] = 38,
+ [2][1][2][1][RTW89_KCC][0][86] = 127,
+ [2][1][2][1][RTW89_ACMA][1][86] = 127,
+ [2][1][2][1][RTW89_ACMA][0][86] = 127,
+ [2][1][2][1][RTW89_CHILE][1][86] = 20,
+ [2][1][2][1][RTW89_QATAR][1][86] = 127,
+ [2][1][2][1][RTW89_QATAR][0][86] = 127,
+ [2][1][2][1][RTW89_UK][1][86] = 127,
+ [2][1][2][1][RTW89_UK][0][86] = 127,
+ [2][1][2][1][RTW89_FCC][1][93] = 22,
+ [2][1][2][1][RTW89_FCC][2][93] = 127,
+ [2][1][2][1][RTW89_ETSI][1][93] = 127,
+ [2][1][2][1][RTW89_ETSI][0][93] = 127,
+ [2][1][2][1][RTW89_MKK][1][93] = 127,
+ [2][1][2][1][RTW89_MKK][0][93] = 127,
+ [2][1][2][1][RTW89_IC][1][93] = 22,
+ [2][1][2][1][RTW89_KCC][1][93] = 38,
+ [2][1][2][1][RTW89_KCC][0][93] = 127,
+ [2][1][2][1][RTW89_ACMA][1][93] = 127,
+ [2][1][2][1][RTW89_ACMA][0][93] = 127,
+ [2][1][2][1][RTW89_CHILE][1][93] = 22,
+ [2][1][2][1][RTW89_QATAR][1][93] = 127,
+ [2][1][2][1][RTW89_QATAR][0][93] = 127,
+ [2][1][2][1][RTW89_UK][1][93] = 127,
+ [2][1][2][1][RTW89_UK][0][93] = 127,
+ [2][1][2][1][RTW89_FCC][1][101] = 22,
+ [2][1][2][1][RTW89_FCC][2][101] = 127,
+ [2][1][2][1][RTW89_ETSI][1][101] = 127,
+ [2][1][2][1][RTW89_ETSI][0][101] = 127,
+ [2][1][2][1][RTW89_MKK][1][101] = 127,
+ [2][1][2][1][RTW89_MKK][0][101] = 127,
+ [2][1][2][1][RTW89_IC][1][101] = 22,
+ [2][1][2][1][RTW89_KCC][1][101] = 38,
+ [2][1][2][1][RTW89_KCC][0][101] = 127,
+ [2][1][2][1][RTW89_ACMA][1][101] = 127,
+ [2][1][2][1][RTW89_ACMA][0][101] = 127,
+ [2][1][2][1][RTW89_CHILE][1][101] = 22,
+ [2][1][2][1][RTW89_QATAR][1][101] = 127,
+ [2][1][2][1][RTW89_QATAR][0][101] = 127,
+ [2][1][2][1][RTW89_UK][1][101] = 127,
+ [2][1][2][1][RTW89_UK][0][101] = 127,
+ [2][1][2][1][RTW89_FCC][1][108] = 127,
+ [2][1][2][1][RTW89_FCC][2][108] = 127,
+ [2][1][2][1][RTW89_ETSI][1][108] = 127,
+ [2][1][2][1][RTW89_ETSI][0][108] = 127,
+ [2][1][2][1][RTW89_MKK][1][108] = 127,
+ [2][1][2][1][RTW89_MKK][0][108] = 127,
+ [2][1][2][1][RTW89_IC][1][108] = 127,
+ [2][1][2][1][RTW89_KCC][1][108] = 127,
+ [2][1][2][1][RTW89_KCC][0][108] = 127,
+ [2][1][2][1][RTW89_ACMA][1][108] = 127,
+ [2][1][2][1][RTW89_ACMA][0][108] = 127,
+ [2][1][2][1][RTW89_CHILE][1][108] = 127,
+ [2][1][2][1][RTW89_QATAR][1][108] = 127,
+ [2][1][2][1][RTW89_QATAR][0][108] = 127,
+ [2][1][2][1][RTW89_UK][1][108] = 127,
+ [2][1][2][1][RTW89_UK][0][108] = 127,
+ [2][1][2][1][RTW89_FCC][1][116] = 127,
+ [2][1][2][1][RTW89_FCC][2][116] = 127,
+ [2][1][2][1][RTW89_ETSI][1][116] = 127,
+ [2][1][2][1][RTW89_ETSI][0][116] = 127,
+ [2][1][2][1][RTW89_MKK][1][116] = 127,
+ [2][1][2][1][RTW89_MKK][0][116] = 127,
+ [2][1][2][1][RTW89_IC][1][116] = 127,
+ [2][1][2][1][RTW89_KCC][1][116] = 127,
+ [2][1][2][1][RTW89_KCC][0][116] = 127,
+ [2][1][2][1][RTW89_ACMA][1][116] = 127,
+ [2][1][2][1][RTW89_ACMA][0][116] = 127,
+ [2][1][2][1][RTW89_CHILE][1][116] = 127,
+ [2][1][2][1][RTW89_QATAR][1][116] = 127,
+ [2][1][2][1][RTW89_QATAR][0][116] = 127,
+ [2][1][2][1][RTW89_UK][1][116] = 127,
+ [2][1][2][1][RTW89_UK][0][116] = 127,
+ [3][0][2][0][RTW89_FCC][1][7] = 52,
+ [3][0][2][0][RTW89_FCC][2][7] = 52,
+ [3][0][2][0][RTW89_ETSI][1][7] = 50,
+ [3][0][2][0][RTW89_ETSI][0][7] = 30,
+ [3][0][2][0][RTW89_MKK][1][7] = 50,
+ [3][0][2][0][RTW89_MKK][0][7] = 22,
+ [3][0][2][0][RTW89_IC][1][7] = 52,
+ [3][0][2][0][RTW89_KCC][1][7] = 42,
+ [3][0][2][0][RTW89_KCC][0][7] = 24,
+ [3][0][2][0][RTW89_ACMA][1][7] = 50,
+ [3][0][2][0][RTW89_ACMA][0][7] = 30,
+ [3][0][2][0][RTW89_CHILE][1][7] = 52,
+ [3][0][2][0][RTW89_QATAR][1][7] = 50,
+ [3][0][2][0][RTW89_QATAR][0][7] = 30,
+ [3][0][2][0][RTW89_UK][1][7] = 50,
+ [3][0][2][0][RTW89_UK][0][7] = 30,
+ [3][0][2][0][RTW89_FCC][1][22] = 52,
+ [3][0][2][0][RTW89_FCC][2][22] = 52,
+ [3][0][2][0][RTW89_ETSI][1][22] = 50,
+ [3][0][2][0][RTW89_ETSI][0][22] = 30,
+ [3][0][2][0][RTW89_MKK][1][22] = 50,
+ [3][0][2][0][RTW89_MKK][0][22] = 20,
+ [3][0][2][0][RTW89_IC][1][22] = 52,
+ [3][0][2][0][RTW89_KCC][1][22] = 42,
+ [3][0][2][0][RTW89_KCC][0][22] = 24,
+ [3][0][2][0][RTW89_ACMA][1][22] = 50,
+ [3][0][2][0][RTW89_ACMA][0][22] = 30,
+ [3][0][2][0][RTW89_CHILE][1][22] = 52,
+ [3][0][2][0][RTW89_QATAR][1][22] = 50,
+ [3][0][2][0][RTW89_QATAR][0][22] = 30,
+ [3][0][2][0][RTW89_UK][1][22] = 50,
+ [3][0][2][0][RTW89_UK][0][22] = 30,
+ [3][0][2][0][RTW89_FCC][1][37] = 52,
+ [3][0][2][0][RTW89_FCC][2][37] = 52,
+ [3][0][2][0][RTW89_ETSI][1][37] = 50,
+ [3][0][2][0][RTW89_ETSI][0][37] = 30,
+ [3][0][2][0][RTW89_MKK][1][37] = 50,
+ [3][0][2][0][RTW89_MKK][0][37] = 20,
+ [3][0][2][0][RTW89_IC][1][37] = 52,
+ [3][0][2][0][RTW89_KCC][1][37] = 42,
+ [3][0][2][0][RTW89_KCC][0][37] = 24,
+ [3][0][2][0][RTW89_ACMA][1][37] = 50,
+ [3][0][2][0][RTW89_ACMA][0][37] = 30,
+ [3][0][2][0][RTW89_CHILE][1][37] = 52,
+ [3][0][2][0][RTW89_QATAR][1][37] = 50,
+ [3][0][2][0][RTW89_QATAR][0][37] = 30,
+ [3][0][2][0][RTW89_UK][1][37] = 50,
+ [3][0][2][0][RTW89_UK][0][37] = 30,
+ [3][0][2][0][RTW89_FCC][1][52] = 54,
+ [3][0][2][0][RTW89_FCC][2][52] = 127,
+ [3][0][2][0][RTW89_ETSI][1][52] = 127,
+ [3][0][2][0][RTW89_ETSI][0][52] = 127,
+ [3][0][2][0][RTW89_MKK][1][52] = 127,
+ [3][0][2][0][RTW89_MKK][0][52] = 127,
+ [3][0][2][0][RTW89_IC][1][52] = 54,
+ [3][0][2][0][RTW89_KCC][1][52] = 56,
+ [3][0][2][0][RTW89_KCC][0][52] = 127,
+ [3][0][2][0][RTW89_ACMA][1][52] = 127,
+ [3][0][2][0][RTW89_ACMA][0][52] = 127,
+ [3][0][2][0][RTW89_CHILE][1][52] = 54,
+ [3][0][2][0][RTW89_QATAR][1][52] = 127,
+ [3][0][2][0][RTW89_QATAR][0][52] = 127,
+ [3][0][2][0][RTW89_UK][1][52] = 127,
+ [3][0][2][0][RTW89_UK][0][52] = 127,
+ [3][0][2][0][RTW89_FCC][1][67] = 54,
+ [3][0][2][0][RTW89_FCC][2][67] = 54,
+ [3][0][2][0][RTW89_ETSI][1][67] = 127,
+ [3][0][2][0][RTW89_ETSI][0][67] = 127,
+ [3][0][2][0][RTW89_MKK][1][67] = 127,
+ [3][0][2][0][RTW89_MKK][0][67] = 127,
+ [3][0][2][0][RTW89_IC][1][67] = 54,
+ [3][0][2][0][RTW89_KCC][1][67] = 54,
+ [3][0][2][0][RTW89_KCC][0][67] = 127,
+ [3][0][2][0][RTW89_ACMA][1][67] = 127,
+ [3][0][2][0][RTW89_ACMA][0][67] = 127,
+ [3][0][2][0][RTW89_CHILE][1][67] = 54,
+ [3][0][2][0][RTW89_QATAR][1][67] = 127,
+ [3][0][2][0][RTW89_QATAR][0][67] = 127,
+ [3][0][2][0][RTW89_UK][1][67] = 127,
+ [3][0][2][0][RTW89_UK][0][67] = 127,
+ [3][0][2][0][RTW89_FCC][1][82] = 46,
+ [3][0][2][0][RTW89_FCC][2][82] = 127,
+ [3][0][2][0][RTW89_ETSI][1][82] = 127,
+ [3][0][2][0][RTW89_ETSI][0][82] = 127,
+ [3][0][2][0][RTW89_MKK][1][82] = 127,
+ [3][0][2][0][RTW89_MKK][0][82] = 127,
+ [3][0][2][0][RTW89_IC][1][82] = 46,
+ [3][0][2][0][RTW89_KCC][1][82] = 26,
+ [3][0][2][0][RTW89_KCC][0][82] = 127,
+ [3][0][2][0][RTW89_ACMA][1][82] = 127,
+ [3][0][2][0][RTW89_ACMA][0][82] = 127,
+ [3][0][2][0][RTW89_CHILE][1][82] = 46,
+ [3][0][2][0][RTW89_QATAR][1][82] = 127,
+ [3][0][2][0][RTW89_QATAR][0][82] = 127,
+ [3][0][2][0][RTW89_UK][1][82] = 127,
+ [3][0][2][0][RTW89_UK][0][82] = 127,
+ [3][0][2][0][RTW89_FCC][1][97] = 40,
+ [3][0][2][0][RTW89_FCC][2][97] = 127,
+ [3][0][2][0][RTW89_ETSI][1][97] = 127,
+ [3][0][2][0][RTW89_ETSI][0][97] = 127,
+ [3][0][2][0][RTW89_MKK][1][97] = 127,
+ [3][0][2][0][RTW89_MKK][0][97] = 127,
+ [3][0][2][0][RTW89_IC][1][97] = 40,
+ [3][0][2][0][RTW89_KCC][1][97] = 26,
+ [3][0][2][0][RTW89_KCC][0][97] = 127,
+ [3][0][2][0][RTW89_ACMA][1][97] = 127,
+ [3][0][2][0][RTW89_ACMA][0][97] = 127,
+ [3][0][2][0][RTW89_CHILE][1][97] = 40,
+ [3][0][2][0][RTW89_QATAR][1][97] = 127,
+ [3][0][2][0][RTW89_QATAR][0][97] = 127,
+ [3][0][2][0][RTW89_UK][1][97] = 127,
+ [3][0][2][0][RTW89_UK][0][97] = 127,
+ [3][0][2][0][RTW89_FCC][1][112] = 127,
+ [3][0][2][0][RTW89_FCC][2][112] = 127,
+ [3][0][2][0][RTW89_ETSI][1][112] = 127,
+ [3][0][2][0][RTW89_ETSI][0][112] = 127,
+ [3][0][2][0][RTW89_MKK][1][112] = 127,
+ [3][0][2][0][RTW89_MKK][0][112] = 127,
+ [3][0][2][0][RTW89_IC][1][112] = 127,
+ [3][0][2][0][RTW89_KCC][1][112] = 127,
+ [3][0][2][0][RTW89_KCC][0][112] = 127,
+ [3][0][2][0][RTW89_ACMA][1][112] = 127,
+ [3][0][2][0][RTW89_ACMA][0][112] = 127,
+ [3][0][2][0][RTW89_CHILE][1][112] = 127,
+ [3][0][2][0][RTW89_QATAR][1][112] = 127,
+ [3][0][2][0][RTW89_QATAR][0][112] = 127,
+ [3][0][2][0][RTW89_UK][1][112] = 127,
+ [3][0][2][0][RTW89_UK][0][112] = 127,
+ [3][1][2][0][RTW89_FCC][1][7] = 32,
+ [3][1][2][0][RTW89_FCC][2][7] = 46,
+ [3][1][2][0][RTW89_ETSI][1][7] = 50,
+ [3][1][2][0][RTW89_ETSI][0][7] = 18,
+ [3][1][2][0][RTW89_MKK][1][7] = 38,
+ [3][1][2][0][RTW89_MKK][0][7] = 10,
+ [3][1][2][0][RTW89_IC][1][7] = 32,
+ [3][1][2][0][RTW89_KCC][1][7] = 40,
+ [3][1][2][0][RTW89_KCC][0][7] = 12,
+ [3][1][2][0][RTW89_ACMA][1][7] = 50,
+ [3][1][2][0][RTW89_ACMA][0][7] = 18,
+ [3][1][2][0][RTW89_CHILE][1][7] = 32,
+ [3][1][2][0][RTW89_QATAR][1][7] = 50,
+ [3][1][2][0][RTW89_QATAR][0][7] = 18,
+ [3][1][2][0][RTW89_UK][1][7] = 50,
+ [3][1][2][0][RTW89_UK][0][7] = 18,
+ [3][1][2][0][RTW89_FCC][1][22] = 30,
+ [3][1][2][0][RTW89_FCC][2][22] = 52,
+ [3][1][2][0][RTW89_ETSI][1][22] = 46,
+ [3][1][2][0][RTW89_ETSI][0][22] = 16,
+ [3][1][2][0][RTW89_MKK][1][22] = 48,
+ [3][1][2][0][RTW89_MKK][0][22] = 8,
+ [3][1][2][0][RTW89_IC][1][22] = 30,
+ [3][1][2][0][RTW89_KCC][1][22] = 40,
+ [3][1][2][0][RTW89_KCC][0][22] = 12,
+ [3][1][2][0][RTW89_ACMA][1][22] = 46,
+ [3][1][2][0][RTW89_ACMA][0][22] = 16,
+ [3][1][2][0][RTW89_CHILE][1][22] = 30,
+ [3][1][2][0][RTW89_QATAR][1][22] = 46,
+ [3][1][2][0][RTW89_QATAR][0][22] = 16,
+ [3][1][2][0][RTW89_UK][1][22] = 46,
+ [3][1][2][0][RTW89_UK][0][22] = 16,
+ [3][1][2][0][RTW89_FCC][1][37] = 30,
+ [3][1][2][0][RTW89_FCC][2][37] = 52,
+ [3][1][2][0][RTW89_ETSI][1][37] = 46,
+ [3][1][2][0][RTW89_ETSI][0][37] = 16,
+ [3][1][2][0][RTW89_MKK][1][37] = 48,
+ [3][1][2][0][RTW89_MKK][0][37] = 8,
+ [3][1][2][0][RTW89_IC][1][37] = 30,
+ [3][1][2][0][RTW89_KCC][1][37] = 40,
+ [3][1][2][0][RTW89_KCC][0][37] = 12,
+ [3][1][2][0][RTW89_ACMA][1][37] = 46,
+ [3][1][2][0][RTW89_ACMA][0][37] = 16,
+ [3][1][2][0][RTW89_CHILE][1][37] = 30,
+ [3][1][2][0][RTW89_QATAR][1][37] = 46,
+ [3][1][2][0][RTW89_QATAR][0][37] = 16,
+ [3][1][2][0][RTW89_UK][1][37] = 46,
+ [3][1][2][0][RTW89_UK][0][37] = 16,
+ [3][1][2][0][RTW89_FCC][1][52] = 30,
+ [3][1][2][0][RTW89_FCC][2][52] = 127,
+ [3][1][2][0][RTW89_ETSI][1][52] = 127,
+ [3][1][2][0][RTW89_ETSI][0][52] = 127,
+ [3][1][2][0][RTW89_MKK][1][52] = 127,
+ [3][1][2][0][RTW89_MKK][0][52] = 127,
+ [3][1][2][0][RTW89_IC][1][52] = 30,
+ [3][1][2][0][RTW89_KCC][1][52] = 48,
+ [3][1][2][0][RTW89_KCC][0][52] = 127,
+ [3][1][2][0][RTW89_ACMA][1][52] = 127,
+ [3][1][2][0][RTW89_ACMA][0][52] = 127,
+ [3][1][2][0][RTW89_CHILE][1][52] = 30,
+ [3][1][2][0][RTW89_QATAR][1][52] = 127,
+ [3][1][2][0][RTW89_QATAR][0][52] = 127,
+ [3][1][2][0][RTW89_UK][1][52] = 127,
+ [3][1][2][0][RTW89_UK][0][52] = 127,
+ [3][1][2][0][RTW89_FCC][1][67] = 32,
+ [3][1][2][0][RTW89_FCC][2][67] = 54,
+ [3][1][2][0][RTW89_ETSI][1][67] = 127,
+ [3][1][2][0][RTW89_ETSI][0][67] = 127,
+ [3][1][2][0][RTW89_MKK][1][67] = 127,
+ [3][1][2][0][RTW89_MKK][0][67] = 127,
+ [3][1][2][0][RTW89_IC][1][67] = 32,
+ [3][1][2][0][RTW89_KCC][1][67] = 48,
+ [3][1][2][0][RTW89_KCC][0][67] = 127,
+ [3][1][2][0][RTW89_ACMA][1][67] = 127,
+ [3][1][2][0][RTW89_ACMA][0][67] = 127,
+ [3][1][2][0][RTW89_CHILE][1][67] = 32,
+ [3][1][2][0][RTW89_QATAR][1][67] = 127,
+ [3][1][2][0][RTW89_QATAR][0][67] = 127,
+ [3][1][2][0][RTW89_UK][1][67] = 127,
+ [3][1][2][0][RTW89_UK][0][67] = 127,
+ [3][1][2][0][RTW89_FCC][1][82] = 32,
+ [3][1][2][0][RTW89_FCC][2][82] = 127,
+ [3][1][2][0][RTW89_ETSI][1][82] = 127,
+ [3][1][2][0][RTW89_ETSI][0][82] = 127,
+ [3][1][2][0][RTW89_MKK][1][82] = 127,
+ [3][1][2][0][RTW89_MKK][0][82] = 127,
+ [3][1][2][0][RTW89_IC][1][82] = 32,
+ [3][1][2][0][RTW89_KCC][1][82] = 24,
+ [3][1][2][0][RTW89_KCC][0][82] = 127,
+ [3][1][2][0][RTW89_ACMA][1][82] = 127,
+ [3][1][2][0][RTW89_ACMA][0][82] = 127,
+ [3][1][2][0][RTW89_CHILE][1][82] = 32,
+ [3][1][2][0][RTW89_QATAR][1][82] = 127,
+ [3][1][2][0][RTW89_QATAR][0][82] = 127,
+ [3][1][2][0][RTW89_UK][1][82] = 127,
+ [3][1][2][0][RTW89_UK][0][82] = 127,
+ [3][1][2][0][RTW89_FCC][1][97] = 32,
+ [3][1][2][0][RTW89_FCC][2][97] = 127,
+ [3][1][2][0][RTW89_ETSI][1][97] = 127,
+ [3][1][2][0][RTW89_ETSI][0][97] = 127,
+ [3][1][2][0][RTW89_MKK][1][97] = 127,
+ [3][1][2][0][RTW89_MKK][0][97] = 127,
+ [3][1][2][0][RTW89_IC][1][97] = 32,
+ [3][1][2][0][RTW89_KCC][1][97] = 24,
+ [3][1][2][0][RTW89_KCC][0][97] = 127,
+ [3][1][2][0][RTW89_ACMA][1][97] = 127,
+ [3][1][2][0][RTW89_ACMA][0][97] = 127,
+ [3][1][2][0][RTW89_CHILE][1][97] = 32,
+ [3][1][2][0][RTW89_QATAR][1][97] = 127,
+ [3][1][2][0][RTW89_QATAR][0][97] = 127,
+ [3][1][2][0][RTW89_UK][1][97] = 127,
+ [3][1][2][0][RTW89_UK][0][97] = 127,
+ [3][1][2][0][RTW89_FCC][1][112] = 127,
+ [3][1][2][0][RTW89_FCC][2][112] = 127,
+ [3][1][2][0][RTW89_ETSI][1][112] = 127,
+ [3][1][2][0][RTW89_ETSI][0][112] = 127,
+ [3][1][2][0][RTW89_MKK][1][112] = 127,
+ [3][1][2][0][RTW89_MKK][0][112] = 127,
+ [3][1][2][0][RTW89_IC][1][112] = 127,
+ [3][1][2][0][RTW89_KCC][1][112] = 127,
+ [3][1][2][0][RTW89_KCC][0][112] = 127,
+ [3][1][2][0][RTW89_ACMA][1][112] = 127,
+ [3][1][2][0][RTW89_ACMA][0][112] = 127,
+ [3][1][2][0][RTW89_CHILE][1][112] = 127,
+ [3][1][2][0][RTW89_QATAR][1][112] = 127,
+ [3][1][2][0][RTW89_QATAR][0][112] = 127,
+ [3][1][2][0][RTW89_UK][1][112] = 127,
+ [3][1][2][0][RTW89_UK][0][112] = 127,
+ [3][1][2][1][RTW89_FCC][1][7] = 32,
+ [3][1][2][1][RTW89_FCC][2][7] = 46,
+ [3][1][2][1][RTW89_ETSI][1][7] = 42,
+ [3][1][2][1][RTW89_ETSI][0][7] = 6,
+ [3][1][2][1][RTW89_MKK][1][7] = 38,
+ [3][1][2][1][RTW89_MKK][0][7] = 10,
+ [3][1][2][1][RTW89_IC][1][7] = 32,
+ [3][1][2][1][RTW89_KCC][1][7] = 40,
+ [3][1][2][1][RTW89_KCC][0][7] = 12,
+ [3][1][2][1][RTW89_ACMA][1][7] = 42,
+ [3][1][2][1][RTW89_ACMA][0][7] = 6,
+ [3][1][2][1][RTW89_CHILE][1][7] = 32,
+ [3][1][2][1][RTW89_QATAR][1][7] = 42,
+ [3][1][2][1][RTW89_QATAR][0][7] = 6,
+ [3][1][2][1][RTW89_UK][1][7] = 42,
+ [3][1][2][1][RTW89_UK][0][7] = 6,
+ [3][1][2][1][RTW89_FCC][1][22] = 30,
+ [3][1][2][1][RTW89_FCC][2][22] = 52,
+ [3][1][2][1][RTW89_ETSI][1][22] = 42,
+ [3][1][2][1][RTW89_ETSI][0][22] = 6,
+ [3][1][2][1][RTW89_MKK][1][22] = 48,
+ [3][1][2][1][RTW89_MKK][0][22] = 8,
+ [3][1][2][1][RTW89_IC][1][22] = 30,
+ [3][1][2][1][RTW89_KCC][1][22] = 40,
+ [3][1][2][1][RTW89_KCC][0][22] = 12,
+ [3][1][2][1][RTW89_ACMA][1][22] = 42,
+ [3][1][2][1][RTW89_ACMA][0][22] = 6,
+ [3][1][2][1][RTW89_CHILE][1][22] = 30,
+ [3][1][2][1][RTW89_QATAR][1][22] = 42,
+ [3][1][2][1][RTW89_QATAR][0][22] = 6,
+ [3][1][2][1][RTW89_UK][1][22] = 42,
+ [3][1][2][1][RTW89_UK][0][22] = 6,
+ [3][1][2][1][RTW89_FCC][1][37] = 30,
+ [3][1][2][1][RTW89_FCC][2][37] = 52,
+ [3][1][2][1][RTW89_ETSI][1][37] = 42,
+ [3][1][2][1][RTW89_ETSI][0][37] = 6,
+ [3][1][2][1][RTW89_MKK][1][37] = 48,
+ [3][1][2][1][RTW89_MKK][0][37] = 8,
+ [3][1][2][1][RTW89_IC][1][37] = 30,
+ [3][1][2][1][RTW89_KCC][1][37] = 40,
+ [3][1][2][1][RTW89_KCC][0][37] = 12,
+ [3][1][2][1][RTW89_ACMA][1][37] = 42,
+ [3][1][2][1][RTW89_ACMA][0][37] = 6,
+ [3][1][2][1][RTW89_CHILE][1][37] = 30,
+ [3][1][2][1][RTW89_QATAR][1][37] = 42,
+ [3][1][2][1][RTW89_QATAR][0][37] = 6,
+ [3][1][2][1][RTW89_UK][1][37] = 42,
+ [3][1][2][1][RTW89_UK][0][37] = 6,
+ [3][1][2][1][RTW89_FCC][1][52] = 30,
+ [3][1][2][1][RTW89_FCC][2][52] = 127,
+ [3][1][2][1][RTW89_ETSI][1][52] = 127,
+ [3][1][2][1][RTW89_ETSI][0][52] = 127,
+ [3][1][2][1][RTW89_MKK][1][52] = 127,
+ [3][1][2][1][RTW89_MKK][0][52] = 127,
+ [3][1][2][1][RTW89_IC][1][52] = 30,
+ [3][1][2][1][RTW89_KCC][1][52] = 48,
+ [3][1][2][1][RTW89_KCC][0][52] = 127,
+ [3][1][2][1][RTW89_ACMA][1][52] = 127,
+ [3][1][2][1][RTW89_ACMA][0][52] = 127,
+ [3][1][2][1][RTW89_CHILE][1][52] = 30,
+ [3][1][2][1][RTW89_QATAR][1][52] = 127,
+ [3][1][2][1][RTW89_QATAR][0][52] = 127,
+ [3][1][2][1][RTW89_UK][1][52] = 127,
+ [3][1][2][1][RTW89_UK][0][52] = 127,
+ [3][1][2][1][RTW89_FCC][1][67] = 32,
+ [3][1][2][1][RTW89_FCC][2][67] = 54,
+ [3][1][2][1][RTW89_ETSI][1][67] = 127,
+ [3][1][2][1][RTW89_ETSI][0][67] = 127,
+ [3][1][2][1][RTW89_MKK][1][67] = 127,
+ [3][1][2][1][RTW89_MKK][0][67] = 127,
+ [3][1][2][1][RTW89_IC][1][67] = 32,
+ [3][1][2][1][RTW89_KCC][1][67] = 48,
+ [3][1][2][1][RTW89_KCC][0][67] = 127,
+ [3][1][2][1][RTW89_ACMA][1][67] = 127,
+ [3][1][2][1][RTW89_ACMA][0][67] = 127,
+ [3][1][2][1][RTW89_CHILE][1][67] = 32,
+ [3][1][2][1][RTW89_QATAR][1][67] = 127,
+ [3][1][2][1][RTW89_QATAR][0][67] = 127,
+ [3][1][2][1][RTW89_UK][1][67] = 127,
+ [3][1][2][1][RTW89_UK][0][67] = 127,
+ [3][1][2][1][RTW89_FCC][1][82] = 32,
+ [3][1][2][1][RTW89_FCC][2][82] = 127,
+ [3][1][2][1][RTW89_ETSI][1][82] = 127,
+ [3][1][2][1][RTW89_ETSI][0][82] = 127,
+ [3][1][2][1][RTW89_MKK][1][82] = 127,
+ [3][1][2][1][RTW89_MKK][0][82] = 127,
+ [3][1][2][1][RTW89_IC][1][82] = 32,
+ [3][1][2][1][RTW89_KCC][1][82] = 24,
+ [3][1][2][1][RTW89_KCC][0][82] = 127,
+ [3][1][2][1][RTW89_ACMA][1][82] = 127,
+ [3][1][2][1][RTW89_ACMA][0][82] = 127,
+ [3][1][2][1][RTW89_CHILE][1][82] = 32,
+ [3][1][2][1][RTW89_QATAR][1][82] = 127,
+ [3][1][2][1][RTW89_QATAR][0][82] = 127,
+ [3][1][2][1][RTW89_UK][1][82] = 127,
+ [3][1][2][1][RTW89_UK][0][82] = 127,
+ [3][1][2][1][RTW89_FCC][1][97] = 32,
+ [3][1][2][1][RTW89_FCC][2][97] = 127,
+ [3][1][2][1][RTW89_ETSI][1][97] = 127,
+ [3][1][2][1][RTW89_ETSI][0][97] = 127,
+ [3][1][2][1][RTW89_MKK][1][97] = 127,
+ [3][1][2][1][RTW89_MKK][0][97] = 127,
+ [3][1][2][1][RTW89_IC][1][97] = 32,
+ [3][1][2][1][RTW89_KCC][1][97] = 24,
+ [3][1][2][1][RTW89_KCC][0][97] = 127,
+ [3][1][2][1][RTW89_ACMA][1][97] = 127,
+ [3][1][2][1][RTW89_ACMA][0][97] = 127,
+ [3][1][2][1][RTW89_CHILE][1][97] = 32,
+ [3][1][2][1][RTW89_QATAR][1][97] = 127,
+ [3][1][2][1][RTW89_QATAR][0][97] = 127,
+ [3][1][2][1][RTW89_UK][1][97] = 127,
+ [3][1][2][1][RTW89_UK][0][97] = 127,
+ [3][1][2][1][RTW89_FCC][1][112] = 127,
+ [3][1][2][1][RTW89_FCC][2][112] = 127,
+ [3][1][2][1][RTW89_ETSI][1][112] = 127,
+ [3][1][2][1][RTW89_ETSI][0][112] = 127,
+ [3][1][2][1][RTW89_MKK][1][112] = 127,
+ [3][1][2][1][RTW89_MKK][0][112] = 127,
+ [3][1][2][1][RTW89_IC][1][112] = 127,
+ [3][1][2][1][RTW89_KCC][1][112] = 127,
+ [3][1][2][1][RTW89_KCC][0][112] = 127,
+ [3][1][2][1][RTW89_ACMA][1][112] = 127,
+ [3][1][2][1][RTW89_ACMA][0][112] = 127,
+ [3][1][2][1][RTW89_CHILE][1][112] = 127,
+ [3][1][2][1][RTW89_QATAR][1][112] = 127,
+ [3][1][2][1][RTW89_QATAR][0][112] = 127,
+ [3][1][2][1][RTW89_UK][1][112] = 127,
+ [3][1][2][1][RTW89_UK][0][112] = 127,
};
static
@@ -34017,10 +45842,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_WW][3] = 44,
[1][0][RTW89_WW][4] = 44,
[1][0][RTW89_WW][5] = 44,
- [1][0][RTW89_WW][6] = 44,
- [1][0][RTW89_WW][7] = 44,
- [1][0][RTW89_WW][8] = 44,
- [1][0][RTW89_WW][9] = 44,
+ [1][0][RTW89_WW][6] = 40,
+ [1][0][RTW89_WW][7] = 40,
+ [1][0][RTW89_WW][8] = 40,
+ [1][0][RTW89_WW][9] = 40,
[1][0][RTW89_WW][10] = 44,
[1][0][RTW89_WW][11] = 36,
[1][0][RTW89_WW][12] = 4,
@@ -34031,24 +45856,24 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_WW][3] = 32,
[1][1][RTW89_WW][4] = 32,
[1][1][RTW89_WW][5] = 32,
- [1][1][RTW89_WW][6] = 32,
- [1][1][RTW89_WW][7] = 32,
- [1][1][RTW89_WW][8] = 32,
- [1][1][RTW89_WW][9] = 32,
+ [1][1][RTW89_WW][6] = 30,
+ [1][1][RTW89_WW][7] = 30,
+ [1][1][RTW89_WW][8] = 30,
+ [1][1][RTW89_WW][9] = 30,
[1][1][RTW89_WW][10] = 32,
[1][1][RTW89_WW][11] = 30,
[1][1][RTW89_WW][12] = -6,
[1][1][RTW89_WW][13] = 0,
[2][0][RTW89_WW][0] = 56,
- [2][0][RTW89_WW][1] = 56,
- [2][0][RTW89_WW][2] = 56,
- [2][0][RTW89_WW][3] = 56,
- [2][0][RTW89_WW][4] = 56,
+ [2][0][RTW89_WW][1] = 54,
+ [2][0][RTW89_WW][2] = 54,
+ [2][0][RTW89_WW][3] = 54,
+ [2][0][RTW89_WW][4] = 54,
[2][0][RTW89_WW][5] = 56,
- [2][0][RTW89_WW][6] = 56,
- [2][0][RTW89_WW][7] = 56,
- [2][0][RTW89_WW][8] = 56,
- [2][0][RTW89_WW][9] = 56,
+ [2][0][RTW89_WW][6] = 48,
+ [2][0][RTW89_WW][7] = 48,
+ [2][0][RTW89_WW][8] = 48,
+ [2][0][RTW89_WW][9] = 48,
[2][0][RTW89_WW][10] = 56,
[2][0][RTW89_WW][11] = 48,
[2][0][RTW89_WW][12] = 16,
@@ -34059,10 +45884,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_WW][3] = 44,
[2][1][RTW89_WW][4] = 44,
[2][1][RTW89_WW][5] = 44,
- [2][1][RTW89_WW][6] = 44,
- [2][1][RTW89_WW][7] = 44,
- [2][1][RTW89_WW][8] = 44,
- [2][1][RTW89_WW][9] = 44,
+ [2][1][RTW89_WW][6] = 42,
+ [2][1][RTW89_WW][7] = 42,
+ [2][1][RTW89_WW][8] = 42,
+ [2][1][RTW89_WW][9] = 42,
[2][1][RTW89_WW][10] = 44,
[2][1][RTW89_WW][11] = 44,
[2][1][RTW89_WW][12] = 6,
@@ -34075,6 +45900,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][0] = 34,
[0][0][RTW89_CN][0] = 32,
[0][0][RTW89_UK][0] = 34,
+ [0][0][RTW89_MEXICO][0] = 60,
+ [0][0][RTW89_UKRAINE][0] = 34,
+ [0][0][RTW89_CHILE][0] = 60,
+ [0][0][RTW89_QATAR][0] = 34,
[0][0][RTW89_FCC][1] = 60,
[0][0][RTW89_ETSI][1] = 38,
[0][0][RTW89_MKK][1] = 40,
@@ -34083,6 +45912,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][1] = 38,
[0][0][RTW89_CN][1] = 32,
[0][0][RTW89_UK][1] = 38,
+ [0][0][RTW89_MEXICO][1] = 60,
+ [0][0][RTW89_UKRAINE][1] = 38,
+ [0][0][RTW89_CHILE][1] = 50,
+ [0][0][RTW89_QATAR][1] = 38,
[0][0][RTW89_FCC][2] = 64,
[0][0][RTW89_ETSI][2] = 38,
[0][0][RTW89_MKK][2] = 40,
@@ -34091,6 +45924,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][2] = 38,
[0][0][RTW89_CN][2] = 32,
[0][0][RTW89_UK][2] = 38,
+ [0][0][RTW89_MEXICO][2] = 64,
+ [0][0][RTW89_UKRAINE][2] = 38,
+ [0][0][RTW89_CHILE][2] = 50,
+ [0][0][RTW89_QATAR][2] = 38,
[0][0][RTW89_FCC][3] = 68,
[0][0][RTW89_ETSI][3] = 38,
[0][0][RTW89_MKK][3] = 40,
@@ -34099,78 +45936,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][3] = 38,
[0][0][RTW89_CN][3] = 32,
[0][0][RTW89_UK][3] = 38,
+ [0][0][RTW89_MEXICO][3] = 68,
+ [0][0][RTW89_UKRAINE][3] = 38,
+ [0][0][RTW89_CHILE][3] = 50,
+ [0][0][RTW89_QATAR][3] = 38,
[0][0][RTW89_FCC][4] = 68,
[0][0][RTW89_ETSI][4] = 38,
[0][0][RTW89_MKK][4] = 40,
[0][0][RTW89_IC][4] = 68,
- [0][0][RTW89_KCC][4] = 42,
+ [0][0][RTW89_KCC][4] = 44,
[0][0][RTW89_ACMA][4] = 38,
[0][0][RTW89_CN][4] = 32,
[0][0][RTW89_UK][4] = 38,
+ [0][0][RTW89_MEXICO][4] = 68,
+ [0][0][RTW89_UKRAINE][4] = 38,
+ [0][0][RTW89_CHILE][4] = 50,
+ [0][0][RTW89_QATAR][4] = 38,
[0][0][RTW89_FCC][5] = 78,
[0][0][RTW89_ETSI][5] = 38,
[0][0][RTW89_MKK][5] = 40,
[0][0][RTW89_IC][5] = 78,
- [0][0][RTW89_KCC][5] = 42,
+ [0][0][RTW89_KCC][5] = 44,
[0][0][RTW89_ACMA][5] = 38,
[0][0][RTW89_CN][5] = 32,
[0][0][RTW89_UK][5] = 38,
+ [0][0][RTW89_MEXICO][5] = 78,
+ [0][0][RTW89_UKRAINE][5] = 38,
+ [0][0][RTW89_CHILE][5] = 78,
+ [0][0][RTW89_QATAR][5] = 38,
[0][0][RTW89_FCC][6] = 54,
[0][0][RTW89_ETSI][6] = 38,
[0][0][RTW89_MKK][6] = 40,
[0][0][RTW89_IC][6] = 54,
- [0][0][RTW89_KCC][6] = 42,
+ [0][0][RTW89_KCC][6] = 44,
[0][0][RTW89_ACMA][6] = 38,
[0][0][RTW89_CN][6] = 32,
[0][0][RTW89_UK][6] = 38,
+ [0][0][RTW89_MEXICO][6] = 54,
+ [0][0][RTW89_UKRAINE][6] = 38,
+ [0][0][RTW89_CHILE][6] = 36,
+ [0][0][RTW89_QATAR][6] = 38,
[0][0][RTW89_FCC][7] = 54,
[0][0][RTW89_ETSI][7] = 38,
[0][0][RTW89_MKK][7] = 40,
[0][0][RTW89_IC][7] = 54,
- [0][0][RTW89_KCC][7] = 42,
+ [0][0][RTW89_KCC][7] = 44,
[0][0][RTW89_ACMA][7] = 38,
[0][0][RTW89_CN][7] = 32,
[0][0][RTW89_UK][7] = 38,
+ [0][0][RTW89_MEXICO][7] = 54,
+ [0][0][RTW89_UKRAINE][7] = 38,
+ [0][0][RTW89_CHILE][7] = 36,
+ [0][0][RTW89_QATAR][7] = 38,
[0][0][RTW89_FCC][8] = 50,
[0][0][RTW89_ETSI][8] = 38,
[0][0][RTW89_MKK][8] = 40,
[0][0][RTW89_IC][8] = 50,
- [0][0][RTW89_KCC][8] = 42,
+ [0][0][RTW89_KCC][8] = 44,
[0][0][RTW89_ACMA][8] = 38,
[0][0][RTW89_CN][8] = 32,
[0][0][RTW89_UK][8] = 38,
+ [0][0][RTW89_MEXICO][8] = 50,
+ [0][0][RTW89_UKRAINE][8] = 38,
+ [0][0][RTW89_CHILE][8] = 36,
+ [0][0][RTW89_QATAR][8] = 38,
[0][0][RTW89_FCC][9] = 46,
[0][0][RTW89_ETSI][9] = 38,
[0][0][RTW89_MKK][9] = 40,
[0][0][RTW89_IC][9] = 46,
- [0][0][RTW89_KCC][9] = 40,
+ [0][0][RTW89_KCC][9] = 42,
[0][0][RTW89_ACMA][9] = 38,
[0][0][RTW89_CN][9] = 32,
[0][0][RTW89_UK][9] = 38,
+ [0][0][RTW89_MEXICO][9] = 46,
+ [0][0][RTW89_UKRAINE][9] = 38,
+ [0][0][RTW89_CHILE][9] = 36,
+ [0][0][RTW89_QATAR][9] = 38,
[0][0][RTW89_FCC][10] = 46,
[0][0][RTW89_ETSI][10] = 38,
[0][0][RTW89_MKK][10] = 40,
[0][0][RTW89_IC][10] = 46,
- [0][0][RTW89_KCC][10] = 40,
+ [0][0][RTW89_KCC][10] = 42,
[0][0][RTW89_ACMA][10] = 38,
[0][0][RTW89_CN][10] = 32,
[0][0][RTW89_UK][10] = 38,
+ [0][0][RTW89_MEXICO][10] = 46,
+ [0][0][RTW89_UKRAINE][10] = 38,
+ [0][0][RTW89_CHILE][10] = 46,
+ [0][0][RTW89_QATAR][10] = 38,
[0][0][RTW89_FCC][11] = 26,
[0][0][RTW89_ETSI][11] = 38,
[0][0][RTW89_MKK][11] = 40,
[0][0][RTW89_IC][11] = 26,
- [0][0][RTW89_KCC][11] = 40,
+ [0][0][RTW89_KCC][11] = 42,
[0][0][RTW89_ACMA][11] = 38,
[0][0][RTW89_CN][11] = 32,
[0][0][RTW89_UK][11] = 38,
+ [0][0][RTW89_MEXICO][11] = 26,
+ [0][0][RTW89_UKRAINE][11] = 38,
+ [0][0][RTW89_CHILE][11] = 26,
+ [0][0][RTW89_QATAR][11] = 38,
[0][0][RTW89_FCC][12] = -20,
[0][0][RTW89_ETSI][12] = 34,
[0][0][RTW89_MKK][12] = 36,
[0][0][RTW89_IC][12] = -20,
- [0][0][RTW89_KCC][12] = 40,
+ [0][0][RTW89_KCC][12] = 42,
[0][0][RTW89_ACMA][12] = 34,
[0][0][RTW89_CN][12] = 32,
[0][0][RTW89_UK][12] = 34,
+ [0][0][RTW89_MEXICO][12] = -20,
+ [0][0][RTW89_UKRAINE][12] = 34,
+ [0][0][RTW89_CHILE][12] = -20,
+ [0][0][RTW89_QATAR][12] = 34,
[0][0][RTW89_FCC][13] = 127,
[0][0][RTW89_ETSI][13] = 127,
[0][0][RTW89_MKK][13] = 127,
@@ -34179,6 +46056,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][13] = 127,
[0][0][RTW89_CN][13] = 127,
[0][0][RTW89_UK][13] = 127,
+ [0][0][RTW89_MEXICO][13] = 127,
+ [0][0][RTW89_UKRAINE][13] = 127,
+ [0][0][RTW89_CHILE][13] = 127,
+ [0][0][RTW89_QATAR][13] = 127,
[0][1][RTW89_FCC][0] = 56,
[0][1][RTW89_ETSI][0] = 22,
[0][1][RTW89_MKK][0] = 24,
@@ -34187,6 +46068,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][0] = 22,
[0][1][RTW89_CN][0] = 20,
[0][1][RTW89_UK][0] = 22,
+ [0][1][RTW89_MEXICO][0] = 56,
+ [0][1][RTW89_UKRAINE][0] = 22,
+ [0][1][RTW89_CHILE][0] = 56,
+ [0][1][RTW89_QATAR][0] = 22,
[0][1][RTW89_FCC][1] = 56,
[0][1][RTW89_ETSI][1] = 24,
[0][1][RTW89_MKK][1] = 30,
@@ -34195,6 +46080,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][1] = 24,
[0][1][RTW89_CN][1] = 22,
[0][1][RTW89_UK][1] = 24,
+ [0][1][RTW89_MEXICO][1] = 56,
+ [0][1][RTW89_UKRAINE][1] = 24,
+ [0][1][RTW89_CHILE][1] = 40,
+ [0][1][RTW89_QATAR][1] = 24,
[0][1][RTW89_FCC][2] = 60,
[0][1][RTW89_ETSI][2] = 24,
[0][1][RTW89_MKK][2] = 30,
@@ -34203,6 +46092,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][2] = 24,
[0][1][RTW89_CN][2] = 22,
[0][1][RTW89_UK][2] = 24,
+ [0][1][RTW89_MEXICO][2] = 60,
+ [0][1][RTW89_UKRAINE][2] = 24,
+ [0][1][RTW89_CHILE][2] = 40,
+ [0][1][RTW89_QATAR][2] = 24,
[0][1][RTW89_FCC][3] = 64,
[0][1][RTW89_ETSI][3] = 24,
[0][1][RTW89_MKK][3] = 30,
@@ -34211,78 +46104,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][3] = 24,
[0][1][RTW89_CN][3] = 22,
[0][1][RTW89_UK][3] = 24,
+ [0][1][RTW89_MEXICO][3] = 64,
+ [0][1][RTW89_UKRAINE][3] = 24,
+ [0][1][RTW89_CHILE][3] = 40,
+ [0][1][RTW89_QATAR][3] = 24,
[0][1][RTW89_FCC][4] = 68,
[0][1][RTW89_ETSI][4] = 24,
[0][1][RTW89_MKK][4] = 30,
[0][1][RTW89_IC][4] = 68,
- [0][1][RTW89_KCC][4] = 28,
+ [0][1][RTW89_KCC][4] = 34,
[0][1][RTW89_ACMA][4] = 24,
[0][1][RTW89_CN][4] = 22,
[0][1][RTW89_UK][4] = 24,
+ [0][1][RTW89_MEXICO][4] = 68,
+ [0][1][RTW89_UKRAINE][4] = 24,
+ [0][1][RTW89_CHILE][4] = 40,
+ [0][1][RTW89_QATAR][4] = 24,
[0][1][RTW89_FCC][5] = 76,
[0][1][RTW89_ETSI][5] = 24,
[0][1][RTW89_MKK][5] = 30,
[0][1][RTW89_IC][5] = 76,
- [0][1][RTW89_KCC][5] = 28,
+ [0][1][RTW89_KCC][5] = 34,
[0][1][RTW89_ACMA][5] = 24,
[0][1][RTW89_CN][5] = 22,
[0][1][RTW89_UK][5] = 24,
+ [0][1][RTW89_MEXICO][5] = 76,
+ [0][1][RTW89_UKRAINE][5] = 24,
+ [0][1][RTW89_CHILE][5] = 76,
+ [0][1][RTW89_QATAR][5] = 24,
[0][1][RTW89_FCC][6] = 54,
[0][1][RTW89_ETSI][6] = 24,
[0][1][RTW89_MKK][6] = 30,
[0][1][RTW89_IC][6] = 54,
- [0][1][RTW89_KCC][6] = 28,
+ [0][1][RTW89_KCC][6] = 34,
[0][1][RTW89_ACMA][6] = 24,
[0][1][RTW89_CN][6] = 22,
[0][1][RTW89_UK][6] = 24,
+ [0][1][RTW89_MEXICO][6] = 54,
+ [0][1][RTW89_UKRAINE][6] = 24,
+ [0][1][RTW89_CHILE][6] = 26,
+ [0][1][RTW89_QATAR][6] = 24,
[0][1][RTW89_FCC][7] = 50,
[0][1][RTW89_ETSI][7] = 24,
[0][1][RTW89_MKK][7] = 30,
[0][1][RTW89_IC][7] = 50,
- [0][1][RTW89_KCC][7] = 28,
+ [0][1][RTW89_KCC][7] = 34,
[0][1][RTW89_ACMA][7] = 24,
[0][1][RTW89_CN][7] = 22,
[0][1][RTW89_UK][7] = 24,
+ [0][1][RTW89_MEXICO][7] = 50,
+ [0][1][RTW89_UKRAINE][7] = 24,
+ [0][1][RTW89_CHILE][7] = 26,
+ [0][1][RTW89_QATAR][7] = 24,
[0][1][RTW89_FCC][8] = 46,
[0][1][RTW89_ETSI][8] = 24,
[0][1][RTW89_MKK][8] = 30,
[0][1][RTW89_IC][8] = 46,
- [0][1][RTW89_KCC][8] = 28,
+ [0][1][RTW89_KCC][8] = 34,
[0][1][RTW89_ACMA][8] = 24,
[0][1][RTW89_CN][8] = 22,
[0][1][RTW89_UK][8] = 24,
+ [0][1][RTW89_MEXICO][8] = 46,
+ [0][1][RTW89_UKRAINE][8] = 24,
+ [0][1][RTW89_CHILE][8] = 26,
+ [0][1][RTW89_QATAR][8] = 24,
[0][1][RTW89_FCC][9] = 42,
[0][1][RTW89_ETSI][9] = 24,
[0][1][RTW89_MKK][9] = 30,
[0][1][RTW89_IC][9] = 42,
- [0][1][RTW89_KCC][9] = 28,
+ [0][1][RTW89_KCC][9] = 32,
[0][1][RTW89_ACMA][9] = 24,
[0][1][RTW89_CN][9] = 22,
[0][1][RTW89_UK][9] = 24,
+ [0][1][RTW89_MEXICO][9] = 42,
+ [0][1][RTW89_UKRAINE][9] = 24,
+ [0][1][RTW89_CHILE][9] = 26,
+ [0][1][RTW89_QATAR][9] = 24,
[0][1][RTW89_FCC][10] = 42,
[0][1][RTW89_ETSI][10] = 24,
[0][1][RTW89_MKK][10] = 30,
[0][1][RTW89_IC][10] = 42,
- [0][1][RTW89_KCC][10] = 28,
+ [0][1][RTW89_KCC][10] = 32,
[0][1][RTW89_ACMA][10] = 24,
[0][1][RTW89_CN][10] = 22,
[0][1][RTW89_UK][10] = 24,
+ [0][1][RTW89_MEXICO][10] = 42,
+ [0][1][RTW89_UKRAINE][10] = 24,
+ [0][1][RTW89_CHILE][10] = 42,
+ [0][1][RTW89_QATAR][10] = 24,
[0][1][RTW89_FCC][11] = 22,
[0][1][RTW89_ETSI][11] = 24,
[0][1][RTW89_MKK][11] = 30,
[0][1][RTW89_IC][11] = 22,
- [0][1][RTW89_KCC][11] = 28,
+ [0][1][RTW89_KCC][11] = 32,
[0][1][RTW89_ACMA][11] = 24,
[0][1][RTW89_CN][11] = 22,
[0][1][RTW89_UK][11] = 24,
+ [0][1][RTW89_MEXICO][11] = 22,
+ [0][1][RTW89_UKRAINE][11] = 24,
+ [0][1][RTW89_CHILE][11] = 22,
+ [0][1][RTW89_QATAR][11] = 24,
[0][1][RTW89_FCC][12] = -30,
[0][1][RTW89_ETSI][12] = 20,
[0][1][RTW89_MKK][12] = 24,
[0][1][RTW89_IC][12] = -30,
- [0][1][RTW89_KCC][12] = 28,
+ [0][1][RTW89_KCC][12] = 32,
[0][1][RTW89_ACMA][12] = 20,
[0][1][RTW89_CN][12] = 20,
[0][1][RTW89_UK][12] = 20,
+ [0][1][RTW89_MEXICO][12] = -30,
+ [0][1][RTW89_UKRAINE][12] = 20,
+ [0][1][RTW89_CHILE][12] = -30,
+ [0][1][RTW89_QATAR][12] = 20,
[0][1][RTW89_FCC][13] = 127,
[0][1][RTW89_ETSI][13] = 127,
[0][1][RTW89_MKK][13] = 127,
@@ -34291,110 +46224,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][13] = 127,
[0][1][RTW89_CN][13] = 127,
[0][1][RTW89_UK][13] = 127,
+ [0][1][RTW89_MEXICO][13] = 127,
+ [0][1][RTW89_UKRAINE][13] = 127,
+ [0][1][RTW89_CHILE][13] = 127,
+ [0][1][RTW89_QATAR][13] = 127,
[1][0][RTW89_FCC][0] = 66,
[1][0][RTW89_ETSI][0] = 46,
[1][0][RTW89_MKK][0] = 48,
[1][0][RTW89_IC][0] = 66,
- [1][0][RTW89_KCC][0] = 50,
+ [1][0][RTW89_KCC][0] = 54,
[1][0][RTW89_ACMA][0] = 46,
[1][0][RTW89_CN][0] = 42,
[1][0][RTW89_UK][0] = 46,
+ [1][0][RTW89_MEXICO][0] = 66,
+ [1][0][RTW89_UKRAINE][0] = 46,
+ [1][0][RTW89_CHILE][0] = 66,
+ [1][0][RTW89_QATAR][0] = 46,
[1][0][RTW89_FCC][1] = 66,
[1][0][RTW89_ETSI][1] = 46,
[1][0][RTW89_MKK][1] = 48,
[1][0][RTW89_IC][1] = 66,
- [1][0][RTW89_KCC][1] = 50,
+ [1][0][RTW89_KCC][1] = 54,
[1][0][RTW89_ACMA][1] = 46,
[1][0][RTW89_CN][1] = 44,
[1][0][RTW89_UK][1] = 46,
+ [1][0][RTW89_MEXICO][1] = 66,
+ [1][0][RTW89_UKRAINE][1] = 46,
+ [1][0][RTW89_CHILE][1] = 54,
+ [1][0][RTW89_QATAR][1] = 46,
[1][0][RTW89_FCC][2] = 70,
[1][0][RTW89_ETSI][2] = 46,
[1][0][RTW89_MKK][2] = 48,
[1][0][RTW89_IC][2] = 70,
- [1][0][RTW89_KCC][2] = 50,
+ [1][0][RTW89_KCC][2] = 54,
[1][0][RTW89_ACMA][2] = 46,
[1][0][RTW89_CN][2] = 44,
[1][0][RTW89_UK][2] = 46,
+ [1][0][RTW89_MEXICO][2] = 70,
+ [1][0][RTW89_UKRAINE][2] = 46,
+ [1][0][RTW89_CHILE][2] = 54,
+ [1][0][RTW89_QATAR][2] = 46,
[1][0][RTW89_FCC][3] = 72,
[1][0][RTW89_ETSI][3] = 46,
[1][0][RTW89_MKK][3] = 48,
[1][0][RTW89_IC][3] = 72,
- [1][0][RTW89_KCC][3] = 50,
+ [1][0][RTW89_KCC][3] = 54,
[1][0][RTW89_ACMA][3] = 46,
[1][0][RTW89_CN][3] = 44,
[1][0][RTW89_UK][3] = 46,
+ [1][0][RTW89_MEXICO][3] = 72,
+ [1][0][RTW89_UKRAINE][3] = 46,
+ [1][0][RTW89_CHILE][3] = 54,
+ [1][0][RTW89_QATAR][3] = 46,
[1][0][RTW89_FCC][4] = 72,
[1][0][RTW89_ETSI][4] = 46,
[1][0][RTW89_MKK][4] = 48,
[1][0][RTW89_IC][4] = 72,
- [1][0][RTW89_KCC][4] = 50,
+ [1][0][RTW89_KCC][4] = 56,
[1][0][RTW89_ACMA][4] = 46,
[1][0][RTW89_CN][4] = 44,
[1][0][RTW89_UK][4] = 46,
+ [1][0][RTW89_MEXICO][4] = 72,
+ [1][0][RTW89_UKRAINE][4] = 46,
+ [1][0][RTW89_CHILE][4] = 54,
+ [1][0][RTW89_QATAR][4] = 46,
[1][0][RTW89_FCC][5] = 82,
[1][0][RTW89_ETSI][5] = 46,
[1][0][RTW89_MKK][5] = 48,
[1][0][RTW89_IC][5] = 82,
- [1][0][RTW89_KCC][5] = 50,
+ [1][0][RTW89_KCC][5] = 56,
[1][0][RTW89_ACMA][5] = 46,
[1][0][RTW89_CN][5] = 44,
[1][0][RTW89_UK][5] = 46,
+ [1][0][RTW89_MEXICO][5] = 82,
+ [1][0][RTW89_UKRAINE][5] = 46,
+ [1][0][RTW89_CHILE][5] = 82,
+ [1][0][RTW89_QATAR][5] = 46,
[1][0][RTW89_FCC][6] = 58,
[1][0][RTW89_ETSI][6] = 44,
[1][0][RTW89_MKK][6] = 48,
[1][0][RTW89_IC][6] = 58,
- [1][0][RTW89_KCC][6] = 50,
+ [1][0][RTW89_KCC][6] = 56,
[1][0][RTW89_ACMA][6] = 44,
[1][0][RTW89_CN][6] = 44,
[1][0][RTW89_UK][6] = 44,
+ [1][0][RTW89_MEXICO][6] = 58,
+ [1][0][RTW89_UKRAINE][6] = 44,
+ [1][0][RTW89_CHILE][6] = 40,
+ [1][0][RTW89_QATAR][6] = 44,
[1][0][RTW89_FCC][7] = 58,
[1][0][RTW89_ETSI][7] = 46,
[1][0][RTW89_MKK][7] = 48,
[1][0][RTW89_IC][7] = 58,
- [1][0][RTW89_KCC][7] = 50,
+ [1][0][RTW89_KCC][7] = 56,
[1][0][RTW89_ACMA][7] = 46,
[1][0][RTW89_CN][7] = 44,
[1][0][RTW89_UK][7] = 46,
+ [1][0][RTW89_MEXICO][7] = 58,
+ [1][0][RTW89_UKRAINE][7] = 46,
+ [1][0][RTW89_CHILE][7] = 40,
+ [1][0][RTW89_QATAR][7] = 46,
[1][0][RTW89_FCC][8] = 58,
[1][0][RTW89_ETSI][8] = 46,
[1][0][RTW89_MKK][8] = 48,
[1][0][RTW89_IC][8] = 58,
- [1][0][RTW89_KCC][8] = 50,
+ [1][0][RTW89_KCC][8] = 56,
[1][0][RTW89_ACMA][8] = 46,
[1][0][RTW89_CN][8] = 44,
[1][0][RTW89_UK][8] = 46,
+ [1][0][RTW89_MEXICO][8] = 58,
+ [1][0][RTW89_UKRAINE][8] = 46,
+ [1][0][RTW89_CHILE][8] = 40,
+ [1][0][RTW89_QATAR][8] = 46,
[1][0][RTW89_FCC][9] = 54,
[1][0][RTW89_ETSI][9] = 46,
[1][0][RTW89_MKK][9] = 48,
[1][0][RTW89_IC][9] = 54,
- [1][0][RTW89_KCC][9] = 50,
+ [1][0][RTW89_KCC][9] = 56,
[1][0][RTW89_ACMA][9] = 46,
[1][0][RTW89_CN][9] = 44,
[1][0][RTW89_UK][9] = 46,
+ [1][0][RTW89_MEXICO][9] = 54,
+ [1][0][RTW89_UKRAINE][9] = 46,
+ [1][0][RTW89_CHILE][9] = 40,
+ [1][0][RTW89_QATAR][9] = 46,
[1][0][RTW89_FCC][10] = 54,
[1][0][RTW89_ETSI][10] = 46,
[1][0][RTW89_MKK][10] = 48,
[1][0][RTW89_IC][10] = 54,
- [1][0][RTW89_KCC][10] = 50,
+ [1][0][RTW89_KCC][10] = 56,
[1][0][RTW89_ACMA][10] = 46,
[1][0][RTW89_CN][10] = 44,
[1][0][RTW89_UK][10] = 46,
+ [1][0][RTW89_MEXICO][10] = 54,
+ [1][0][RTW89_UKRAINE][10] = 46,
+ [1][0][RTW89_CHILE][10] = 54,
+ [1][0][RTW89_QATAR][10] = 46,
[1][0][RTW89_FCC][11] = 36,
[1][0][RTW89_ETSI][11] = 46,
[1][0][RTW89_MKK][11] = 48,
[1][0][RTW89_IC][11] = 36,
- [1][0][RTW89_KCC][11] = 50,
+ [1][0][RTW89_KCC][11] = 56,
[1][0][RTW89_ACMA][11] = 46,
[1][0][RTW89_CN][11] = 44,
[1][0][RTW89_UK][11] = 46,
+ [1][0][RTW89_MEXICO][11] = 36,
+ [1][0][RTW89_UKRAINE][11] = 46,
+ [1][0][RTW89_CHILE][11] = 36,
+ [1][0][RTW89_QATAR][11] = 46,
[1][0][RTW89_FCC][12] = 4,
[1][0][RTW89_ETSI][12] = 46,
[1][0][RTW89_MKK][12] = 46,
[1][0][RTW89_IC][12] = 4,
- [1][0][RTW89_KCC][12] = 50,
+ [1][0][RTW89_KCC][12] = 56,
[1][0][RTW89_ACMA][12] = 46,
[1][0][RTW89_CN][12] = 42,
[1][0][RTW89_UK][12] = 46,
+ [1][0][RTW89_MEXICO][12] = 4,
+ [1][0][RTW89_UKRAINE][12] = 46,
+ [1][0][RTW89_CHILE][12] = 4,
+ [1][0][RTW89_QATAR][12] = 46,
[1][0][RTW89_FCC][13] = 127,
[1][0][RTW89_ETSI][13] = 127,
[1][0][RTW89_MKK][13] = 127,
@@ -34403,110 +46392,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][13] = 127,
[1][0][RTW89_CN][13] = 127,
[1][0][RTW89_UK][13] = 127,
+ [1][0][RTW89_MEXICO][13] = 127,
+ [1][0][RTW89_UKRAINE][13] = 127,
+ [1][0][RTW89_CHILE][13] = 127,
+ [1][0][RTW89_QATAR][13] = 127,
[1][1][RTW89_FCC][0] = 58,
[1][1][RTW89_ETSI][0] = 32,
[1][1][RTW89_MKK][0] = 34,
[1][1][RTW89_IC][0] = 58,
- [1][1][RTW89_KCC][0] = 38,
+ [1][1][RTW89_KCC][0] = 42,
[1][1][RTW89_ACMA][0] = 32,
[1][1][RTW89_CN][0] = 32,
[1][1][RTW89_UK][0] = 32,
+ [1][1][RTW89_MEXICO][0] = 58,
+ [1][1][RTW89_UKRAINE][0] = 32,
+ [1][1][RTW89_CHILE][0] = 58,
+ [1][1][RTW89_QATAR][0] = 32,
[1][1][RTW89_FCC][1] = 58,
[1][1][RTW89_ETSI][1] = 34,
[1][1][RTW89_MKK][1] = 34,
[1][1][RTW89_IC][1] = 58,
- [1][1][RTW89_KCC][1] = 38,
+ [1][1][RTW89_KCC][1] = 42,
[1][1][RTW89_ACMA][1] = 34,
[1][1][RTW89_CN][1] = 32,
[1][1][RTW89_UK][1] = 34,
+ [1][1][RTW89_MEXICO][1] = 58,
+ [1][1][RTW89_UKRAINE][1] = 34,
+ [1][1][RTW89_CHILE][1] = 40,
+ [1][1][RTW89_QATAR][1] = 34,
[1][1][RTW89_FCC][2] = 62,
[1][1][RTW89_ETSI][2] = 34,
[1][1][RTW89_MKK][2] = 34,
[1][1][RTW89_IC][2] = 62,
- [1][1][RTW89_KCC][2] = 38,
+ [1][1][RTW89_KCC][2] = 42,
[1][1][RTW89_ACMA][2] = 34,
[1][1][RTW89_CN][2] = 32,
[1][1][RTW89_UK][2] = 34,
+ [1][1][RTW89_MEXICO][2] = 62,
+ [1][1][RTW89_UKRAINE][2] = 34,
+ [1][1][RTW89_CHILE][2] = 40,
+ [1][1][RTW89_QATAR][2] = 34,
[1][1][RTW89_FCC][3] = 66,
[1][1][RTW89_ETSI][3] = 34,
[1][1][RTW89_MKK][3] = 34,
[1][1][RTW89_IC][3] = 66,
- [1][1][RTW89_KCC][3] = 38,
+ [1][1][RTW89_KCC][3] = 42,
[1][1][RTW89_ACMA][3] = 34,
[1][1][RTW89_CN][3] = 32,
[1][1][RTW89_UK][3] = 34,
+ [1][1][RTW89_MEXICO][3] = 66,
+ [1][1][RTW89_UKRAINE][3] = 34,
+ [1][1][RTW89_CHILE][3] = 40,
+ [1][1][RTW89_QATAR][3] = 34,
[1][1][RTW89_FCC][4] = 70,
[1][1][RTW89_ETSI][4] = 34,
[1][1][RTW89_MKK][4] = 34,
[1][1][RTW89_IC][4] = 70,
- [1][1][RTW89_KCC][4] = 38,
+ [1][1][RTW89_KCC][4] = 44,
[1][1][RTW89_ACMA][4] = 34,
[1][1][RTW89_CN][4] = 32,
[1][1][RTW89_UK][4] = 34,
+ [1][1][RTW89_MEXICO][4] = 70,
+ [1][1][RTW89_UKRAINE][4] = 34,
+ [1][1][RTW89_CHILE][4] = 40,
+ [1][1][RTW89_QATAR][4] = 34,
[1][1][RTW89_FCC][5] = 82,
[1][1][RTW89_ETSI][5] = 34,
[1][1][RTW89_MKK][5] = 34,
[1][1][RTW89_IC][5] = 82,
- [1][1][RTW89_KCC][5] = 38,
+ [1][1][RTW89_KCC][5] = 44,
[1][1][RTW89_ACMA][5] = 34,
[1][1][RTW89_CN][5] = 32,
[1][1][RTW89_UK][5] = 34,
+ [1][1][RTW89_MEXICO][5] = 82,
+ [1][1][RTW89_UKRAINE][5] = 34,
+ [1][1][RTW89_CHILE][5] = 78,
+ [1][1][RTW89_QATAR][5] = 34,
[1][1][RTW89_FCC][6] = 60,
[1][1][RTW89_ETSI][6] = 34,
[1][1][RTW89_MKK][6] = 34,
[1][1][RTW89_IC][6] = 60,
- [1][1][RTW89_KCC][6] = 38,
+ [1][1][RTW89_KCC][6] = 44,
[1][1][RTW89_ACMA][6] = 34,
[1][1][RTW89_CN][6] = 32,
[1][1][RTW89_UK][6] = 34,
+ [1][1][RTW89_MEXICO][6] = 60,
+ [1][1][RTW89_UKRAINE][6] = 34,
+ [1][1][RTW89_CHILE][6] = 30,
+ [1][1][RTW89_QATAR][6] = 34,
[1][1][RTW89_FCC][7] = 56,
[1][1][RTW89_ETSI][7] = 34,
[1][1][RTW89_MKK][7] = 34,
[1][1][RTW89_IC][7] = 56,
- [1][1][RTW89_KCC][7] = 38,
+ [1][1][RTW89_KCC][7] = 44,
[1][1][RTW89_ACMA][7] = 34,
[1][1][RTW89_CN][7] = 32,
[1][1][RTW89_UK][7] = 34,
+ [1][1][RTW89_MEXICO][7] = 56,
+ [1][1][RTW89_UKRAINE][7] = 34,
+ [1][1][RTW89_CHILE][7] = 30,
+ [1][1][RTW89_QATAR][7] = 34,
[1][1][RTW89_FCC][8] = 52,
[1][1][RTW89_ETSI][8] = 34,
[1][1][RTW89_MKK][8] = 34,
[1][1][RTW89_IC][8] = 52,
- [1][1][RTW89_KCC][8] = 38,
+ [1][1][RTW89_KCC][8] = 44,
[1][1][RTW89_ACMA][8] = 34,
[1][1][RTW89_CN][8] = 32,
[1][1][RTW89_UK][8] = 34,
+ [1][1][RTW89_MEXICO][8] = 52,
+ [1][1][RTW89_UKRAINE][8] = 34,
+ [1][1][RTW89_CHILE][8] = 30,
+ [1][1][RTW89_QATAR][8] = 34,
[1][1][RTW89_FCC][9] = 48,
[1][1][RTW89_ETSI][9] = 34,
[1][1][RTW89_MKK][9] = 34,
[1][1][RTW89_IC][9] = 48,
- [1][1][RTW89_KCC][9] = 38,
+ [1][1][RTW89_KCC][9] = 44,
[1][1][RTW89_ACMA][9] = 34,
[1][1][RTW89_CN][9] = 32,
[1][1][RTW89_UK][9] = 34,
+ [1][1][RTW89_MEXICO][9] = 48,
+ [1][1][RTW89_UKRAINE][9] = 34,
+ [1][1][RTW89_CHILE][9] = 30,
+ [1][1][RTW89_QATAR][9] = 34,
[1][1][RTW89_FCC][10] = 48,
[1][1][RTW89_ETSI][10] = 34,
[1][1][RTW89_MKK][10] = 34,
[1][1][RTW89_IC][10] = 48,
- [1][1][RTW89_KCC][10] = 38,
+ [1][1][RTW89_KCC][10] = 44,
[1][1][RTW89_ACMA][10] = 34,
[1][1][RTW89_CN][10] = 32,
[1][1][RTW89_UK][10] = 34,
+ [1][1][RTW89_MEXICO][10] = 48,
+ [1][1][RTW89_UKRAINE][10] = 34,
+ [1][1][RTW89_CHILE][10] = 48,
+ [1][1][RTW89_QATAR][10] = 34,
[1][1][RTW89_FCC][11] = 30,
[1][1][RTW89_ETSI][11] = 34,
[1][1][RTW89_MKK][11] = 34,
[1][1][RTW89_IC][11] = 30,
- [1][1][RTW89_KCC][11] = 38,
+ [1][1][RTW89_KCC][11] = 44,
[1][1][RTW89_ACMA][11] = 34,
[1][1][RTW89_CN][11] = 32,
[1][1][RTW89_UK][11] = 34,
+ [1][1][RTW89_MEXICO][11] = 30,
+ [1][1][RTW89_UKRAINE][11] = 34,
+ [1][1][RTW89_CHILE][11] = 30,
+ [1][1][RTW89_QATAR][11] = 34,
[1][1][RTW89_FCC][12] = -6,
[1][1][RTW89_ETSI][12] = 34,
[1][1][RTW89_MKK][12] = 34,
[1][1][RTW89_IC][12] = -6,
- [1][1][RTW89_KCC][12] = 38,
+ [1][1][RTW89_KCC][12] = 44,
[1][1][RTW89_ACMA][12] = 34,
[1][1][RTW89_CN][12] = 32,
[1][1][RTW89_UK][12] = 34,
+ [1][1][RTW89_MEXICO][12] = -6,
+ [1][1][RTW89_UKRAINE][12] = 34,
+ [1][1][RTW89_CHILE][12] = -6,
+ [1][1][RTW89_QATAR][12] = 34,
[1][1][RTW89_FCC][13] = 127,
[1][1][RTW89_ETSI][13] = 127,
[1][1][RTW89_MKK][13] = 127,
@@ -34515,110 +46560,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][13] = 127,
[1][1][RTW89_CN][13] = 127,
[1][1][RTW89_UK][13] = 127,
+ [1][1][RTW89_MEXICO][13] = 127,
+ [1][1][RTW89_UKRAINE][13] = 127,
+ [1][1][RTW89_CHILE][13] = 127,
+ [1][1][RTW89_QATAR][13] = 127,
[2][0][RTW89_FCC][0] = 70,
[2][0][RTW89_ETSI][0] = 58,
[2][0][RTW89_MKK][0] = 58,
[2][0][RTW89_IC][0] = 70,
- [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_KCC][0] = 60,
[2][0][RTW89_ACMA][0] = 58,
[2][0][RTW89_CN][0] = 56,
[2][0][RTW89_UK][0] = 58,
+ [2][0][RTW89_MEXICO][0] = 70,
+ [2][0][RTW89_UKRAINE][0] = 58,
+ [2][0][RTW89_CHILE][0] = 70,
+ [2][0][RTW89_QATAR][0] = 58,
[2][0][RTW89_FCC][1] = 70,
[2][0][RTW89_ETSI][1] = 58,
[2][0][RTW89_MKK][1] = 58,
[2][0][RTW89_IC][1] = 70,
- [2][0][RTW89_KCC][1] = 64,
+ [2][0][RTW89_KCC][1] = 60,
[2][0][RTW89_ACMA][1] = 58,
[2][0][RTW89_CN][1] = 56,
[2][0][RTW89_UK][1] = 58,
+ [2][0][RTW89_MEXICO][1] = 70,
+ [2][0][RTW89_UKRAINE][1] = 58,
+ [2][0][RTW89_CHILE][1] = 54,
+ [2][0][RTW89_QATAR][1] = 58,
[2][0][RTW89_FCC][2] = 72,
[2][0][RTW89_ETSI][2] = 58,
[2][0][RTW89_MKK][2] = 58,
[2][0][RTW89_IC][2] = 72,
- [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_KCC][2] = 60,
[2][0][RTW89_ACMA][2] = 58,
[2][0][RTW89_CN][2] = 56,
[2][0][RTW89_UK][2] = 58,
+ [2][0][RTW89_MEXICO][2] = 72,
+ [2][0][RTW89_UKRAINE][2] = 58,
+ [2][0][RTW89_CHILE][2] = 54,
+ [2][0][RTW89_QATAR][2] = 58,
[2][0][RTW89_FCC][3] = 72,
[2][0][RTW89_ETSI][3] = 58,
[2][0][RTW89_MKK][3] = 58,
[2][0][RTW89_IC][3] = 72,
- [2][0][RTW89_KCC][3] = 64,
+ [2][0][RTW89_KCC][3] = 60,
[2][0][RTW89_ACMA][3] = 58,
[2][0][RTW89_CN][3] = 56,
[2][0][RTW89_UK][3] = 58,
+ [2][0][RTW89_MEXICO][3] = 72,
+ [2][0][RTW89_UKRAINE][3] = 58,
+ [2][0][RTW89_CHILE][3] = 54,
+ [2][0][RTW89_QATAR][3] = 58,
[2][0][RTW89_FCC][4] = 72,
[2][0][RTW89_ETSI][4] = 58,
[2][0][RTW89_MKK][4] = 58,
[2][0][RTW89_IC][4] = 72,
- [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_KCC][4] = 60,
[2][0][RTW89_ACMA][4] = 58,
[2][0][RTW89_CN][4] = 56,
[2][0][RTW89_UK][4] = 58,
+ [2][0][RTW89_MEXICO][4] = 72,
+ [2][0][RTW89_UKRAINE][4] = 58,
+ [2][0][RTW89_CHILE][4] = 54,
+ [2][0][RTW89_QATAR][4] = 58,
[2][0][RTW89_FCC][5] = 82,
[2][0][RTW89_ETSI][5] = 58,
[2][0][RTW89_MKK][5] = 58,
[2][0][RTW89_IC][5] = 82,
- [2][0][RTW89_KCC][5] = 64,
+ [2][0][RTW89_KCC][5] = 60,
[2][0][RTW89_ACMA][5] = 58,
[2][0][RTW89_CN][5] = 56,
[2][0][RTW89_UK][5] = 58,
+ [2][0][RTW89_MEXICO][5] = 82,
+ [2][0][RTW89_UKRAINE][5] = 58,
+ [2][0][RTW89_CHILE][5] = 82,
+ [2][0][RTW89_QATAR][5] = 58,
[2][0][RTW89_FCC][6] = 66,
[2][0][RTW89_ETSI][6] = 56,
[2][0][RTW89_MKK][6] = 58,
[2][0][RTW89_IC][6] = 66,
- [2][0][RTW89_KCC][6] = 64,
+ [2][0][RTW89_KCC][6] = 60,
[2][0][RTW89_ACMA][6] = 56,
[2][0][RTW89_CN][6] = 56,
[2][0][RTW89_UK][6] = 56,
+ [2][0][RTW89_MEXICO][6] = 66,
+ [2][0][RTW89_UKRAINE][6] = 56,
+ [2][0][RTW89_CHILE][6] = 48,
+ [2][0][RTW89_QATAR][6] = 56,
[2][0][RTW89_FCC][7] = 66,
[2][0][RTW89_ETSI][7] = 58,
[2][0][RTW89_MKK][7] = 58,
[2][0][RTW89_IC][7] = 66,
- [2][0][RTW89_KCC][7] = 64,
+ [2][0][RTW89_KCC][7] = 60,
[2][0][RTW89_ACMA][7] = 58,
[2][0][RTW89_CN][7] = 56,
[2][0][RTW89_UK][7] = 58,
+ [2][0][RTW89_MEXICO][7] = 66,
+ [2][0][RTW89_UKRAINE][7] = 58,
+ [2][0][RTW89_CHILE][7] = 48,
+ [2][0][RTW89_QATAR][7] = 58,
[2][0][RTW89_FCC][8] = 66,
[2][0][RTW89_ETSI][8] = 58,
[2][0][RTW89_MKK][8] = 58,
[2][0][RTW89_IC][8] = 66,
- [2][0][RTW89_KCC][8] = 64,
+ [2][0][RTW89_KCC][8] = 60,
[2][0][RTW89_ACMA][8] = 58,
[2][0][RTW89_CN][8] = 56,
[2][0][RTW89_UK][8] = 58,
+ [2][0][RTW89_MEXICO][8] = 66,
+ [2][0][RTW89_UKRAINE][8] = 58,
+ [2][0][RTW89_CHILE][8] = 48,
+ [2][0][RTW89_QATAR][8] = 58,
[2][0][RTW89_FCC][9] = 64,
[2][0][RTW89_ETSI][9] = 58,
[2][0][RTW89_MKK][9] = 58,
[2][0][RTW89_IC][9] = 64,
- [2][0][RTW89_KCC][9] = 64,
+ [2][0][RTW89_KCC][9] = 60,
[2][0][RTW89_ACMA][9] = 58,
[2][0][RTW89_CN][9] = 56,
[2][0][RTW89_UK][9] = 58,
+ [2][0][RTW89_MEXICO][9] = 64,
+ [2][0][RTW89_UKRAINE][9] = 58,
+ [2][0][RTW89_CHILE][9] = 48,
+ [2][0][RTW89_QATAR][9] = 58,
[2][0][RTW89_FCC][10] = 64,
[2][0][RTW89_ETSI][10] = 58,
[2][0][RTW89_MKK][10] = 58,
[2][0][RTW89_IC][10] = 64,
- [2][0][RTW89_KCC][10] = 64,
+ [2][0][RTW89_KCC][10] = 60,
[2][0][RTW89_ACMA][10] = 58,
[2][0][RTW89_CN][10] = 56,
[2][0][RTW89_UK][10] = 58,
+ [2][0][RTW89_MEXICO][10] = 64,
+ [2][0][RTW89_UKRAINE][10] = 58,
+ [2][0][RTW89_CHILE][10] = 64,
+ [2][0][RTW89_QATAR][10] = 58,
[2][0][RTW89_FCC][11] = 48,
[2][0][RTW89_ETSI][11] = 58,
[2][0][RTW89_MKK][11] = 58,
[2][0][RTW89_IC][11] = 48,
- [2][0][RTW89_KCC][11] = 64,
+ [2][0][RTW89_KCC][11] = 60,
[2][0][RTW89_ACMA][11] = 58,
[2][0][RTW89_CN][11] = 56,
[2][0][RTW89_UK][11] = 58,
+ [2][0][RTW89_MEXICO][11] = 48,
+ [2][0][RTW89_UKRAINE][11] = 58,
+ [2][0][RTW89_CHILE][11] = 48,
+ [2][0][RTW89_QATAR][11] = 58,
[2][0][RTW89_FCC][12] = 16,
[2][0][RTW89_ETSI][12] = 58,
[2][0][RTW89_MKK][12] = 58,
[2][0][RTW89_IC][12] = 16,
- [2][0][RTW89_KCC][12] = 64,
+ [2][0][RTW89_KCC][12] = 60,
[2][0][RTW89_ACMA][12] = 58,
[2][0][RTW89_CN][12] = 56,
[2][0][RTW89_UK][12] = 58,
+ [2][0][RTW89_MEXICO][12] = 16,
+ [2][0][RTW89_UKRAINE][12] = 58,
+ [2][0][RTW89_CHILE][12] = 16,
+ [2][0][RTW89_QATAR][12] = 58,
[2][0][RTW89_FCC][13] = 127,
[2][0][RTW89_ETSI][13] = 127,
[2][0][RTW89_MKK][13] = 127,
@@ -34627,110 +46728,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][13] = 127,
[2][0][RTW89_CN][13] = 127,
[2][0][RTW89_UK][13] = 127,
+ [2][0][RTW89_MEXICO][13] = 127,
+ [2][0][RTW89_UKRAINE][13] = 127,
+ [2][0][RTW89_CHILE][13] = 127,
+ [2][0][RTW89_QATAR][13] = 127,
[2][1][RTW89_FCC][0] = 64,
[2][1][RTW89_ETSI][0] = 46,
[2][1][RTW89_MKK][0] = 46,
[2][1][RTW89_IC][0] = 64,
- [2][1][RTW89_KCC][0] = 52,
+ [2][1][RTW89_KCC][0] = 48,
[2][1][RTW89_ACMA][0] = 46,
[2][1][RTW89_CN][0] = 44,
[2][1][RTW89_UK][0] = 46,
+ [2][1][RTW89_MEXICO][0] = 64,
+ [2][1][RTW89_UKRAINE][0] = 46,
+ [2][1][RTW89_CHILE][0] = 64,
+ [2][1][RTW89_QATAR][0] = 46,
[2][1][RTW89_FCC][1] = 64,
[2][1][RTW89_ETSI][1] = 46,
[2][1][RTW89_MKK][1] = 46,
[2][1][RTW89_IC][1] = 64,
- [2][1][RTW89_KCC][1] = 52,
+ [2][1][RTW89_KCC][1] = 48,
[2][1][RTW89_ACMA][1] = 46,
[2][1][RTW89_CN][1] = 44,
[2][1][RTW89_UK][1] = 46,
+ [2][1][RTW89_MEXICO][1] = 64,
+ [2][1][RTW89_UKRAINE][1] = 46,
+ [2][1][RTW89_CHILE][1] = 44,
+ [2][1][RTW89_QATAR][1] = 46,
[2][1][RTW89_FCC][2] = 68,
[2][1][RTW89_ETSI][2] = 46,
[2][1][RTW89_MKK][2] = 46,
[2][1][RTW89_IC][2] = 68,
- [2][1][RTW89_KCC][2] = 52,
+ [2][1][RTW89_KCC][2] = 48,
[2][1][RTW89_ACMA][2] = 46,
[2][1][RTW89_CN][2] = 44,
[2][1][RTW89_UK][2] = 46,
+ [2][1][RTW89_MEXICO][2] = 68,
+ [2][1][RTW89_UKRAINE][2] = 46,
+ [2][1][RTW89_CHILE][2] = 44,
+ [2][1][RTW89_QATAR][2] = 46,
[2][1][RTW89_FCC][3] = 72,
[2][1][RTW89_ETSI][3] = 46,
[2][1][RTW89_MKK][3] = 46,
[2][1][RTW89_IC][3] = 72,
- [2][1][RTW89_KCC][3] = 52,
+ [2][1][RTW89_KCC][3] = 48,
[2][1][RTW89_ACMA][3] = 46,
[2][1][RTW89_CN][3] = 44,
[2][1][RTW89_UK][3] = 46,
+ [2][1][RTW89_MEXICO][3] = 72,
+ [2][1][RTW89_UKRAINE][3] = 46,
+ [2][1][RTW89_CHILE][3] = 44,
+ [2][1][RTW89_QATAR][3] = 46,
[2][1][RTW89_FCC][4] = 74,
[2][1][RTW89_ETSI][4] = 46,
[2][1][RTW89_MKK][4] = 46,
[2][1][RTW89_IC][4] = 74,
- [2][1][RTW89_KCC][4] = 50,
+ [2][1][RTW89_KCC][4] = 48,
[2][1][RTW89_ACMA][4] = 46,
[2][1][RTW89_CN][4] = 44,
[2][1][RTW89_UK][4] = 46,
+ [2][1][RTW89_MEXICO][4] = 74,
+ [2][1][RTW89_UKRAINE][4] = 46,
+ [2][1][RTW89_CHILE][4] = 44,
+ [2][1][RTW89_QATAR][4] = 46,
[2][1][RTW89_FCC][5] = 82,
[2][1][RTW89_ETSI][5] = 46,
[2][1][RTW89_MKK][5] = 46,
[2][1][RTW89_IC][5] = 82,
- [2][1][RTW89_KCC][5] = 50,
+ [2][1][RTW89_KCC][5] = 48,
[2][1][RTW89_ACMA][5] = 46,
[2][1][RTW89_CN][5] = 44,
[2][1][RTW89_UK][5] = 46,
+ [2][1][RTW89_MEXICO][5] = 82,
+ [2][1][RTW89_UKRAINE][5] = 46,
+ [2][1][RTW89_CHILE][5] = 78,
+ [2][1][RTW89_QATAR][5] = 46,
[2][1][RTW89_FCC][6] = 72,
[2][1][RTW89_ETSI][6] = 44,
[2][1][RTW89_MKK][6] = 46,
[2][1][RTW89_IC][6] = 72,
- [2][1][RTW89_KCC][6] = 50,
+ [2][1][RTW89_KCC][6] = 48,
[2][1][RTW89_ACMA][6] = 44,
[2][1][RTW89_CN][6] = 44,
[2][1][RTW89_UK][6] = 44,
+ [2][1][RTW89_MEXICO][6] = 72,
+ [2][1][RTW89_UKRAINE][6] = 44,
+ [2][1][RTW89_CHILE][6] = 42,
+ [2][1][RTW89_QATAR][6] = 44,
[2][1][RTW89_FCC][7] = 72,
[2][1][RTW89_ETSI][7] = 46,
[2][1][RTW89_MKK][7] = 46,
[2][1][RTW89_IC][7] = 72,
- [2][1][RTW89_KCC][7] = 50,
+ [2][1][RTW89_KCC][7] = 48,
[2][1][RTW89_ACMA][7] = 46,
[2][1][RTW89_CN][7] = 44,
[2][1][RTW89_UK][7] = 46,
+ [2][1][RTW89_MEXICO][7] = 72,
+ [2][1][RTW89_UKRAINE][7] = 46,
+ [2][1][RTW89_CHILE][7] = 42,
+ [2][1][RTW89_QATAR][7] = 46,
[2][1][RTW89_FCC][8] = 68,
[2][1][RTW89_ETSI][8] = 46,
[2][1][RTW89_MKK][8] = 46,
[2][1][RTW89_IC][8] = 68,
- [2][1][RTW89_KCC][8] = 50,
+ [2][1][RTW89_KCC][8] = 48,
[2][1][RTW89_ACMA][8] = 46,
[2][1][RTW89_CN][8] = 44,
[2][1][RTW89_UK][8] = 46,
+ [2][1][RTW89_MEXICO][8] = 68,
+ [2][1][RTW89_UKRAINE][8] = 46,
+ [2][1][RTW89_CHILE][8] = 42,
+ [2][1][RTW89_QATAR][8] = 46,
[2][1][RTW89_FCC][9] = 64,
[2][1][RTW89_ETSI][9] = 46,
[2][1][RTW89_MKK][9] = 46,
[2][1][RTW89_IC][9] = 64,
- [2][1][RTW89_KCC][9] = 52,
+ [2][1][RTW89_KCC][9] = 48,
[2][1][RTW89_ACMA][9] = 46,
[2][1][RTW89_CN][9] = 44,
[2][1][RTW89_UK][9] = 46,
+ [2][1][RTW89_MEXICO][9] = 64,
+ [2][1][RTW89_UKRAINE][9] = 46,
+ [2][1][RTW89_CHILE][9] = 42,
+ [2][1][RTW89_QATAR][9] = 46,
[2][1][RTW89_FCC][10] = 64,
[2][1][RTW89_ETSI][10] = 46,
[2][1][RTW89_MKK][10] = 46,
[2][1][RTW89_IC][10] = 64,
- [2][1][RTW89_KCC][10] = 52,
+ [2][1][RTW89_KCC][10] = 48,
[2][1][RTW89_ACMA][10] = 46,
[2][1][RTW89_CN][10] = 44,
[2][1][RTW89_UK][10] = 46,
+ [2][1][RTW89_MEXICO][10] = 64,
+ [2][1][RTW89_UKRAINE][10] = 46,
+ [2][1][RTW89_CHILE][10] = 64,
+ [2][1][RTW89_QATAR][10] = 46,
[2][1][RTW89_FCC][11] = 46,
[2][1][RTW89_ETSI][11] = 46,
[2][1][RTW89_MKK][11] = 46,
[2][1][RTW89_IC][11] = 46,
- [2][1][RTW89_KCC][11] = 52,
+ [2][1][RTW89_KCC][11] = 48,
[2][1][RTW89_ACMA][11] = 46,
[2][1][RTW89_CN][11] = 44,
[2][1][RTW89_UK][11] = 46,
+ [2][1][RTW89_MEXICO][11] = 46,
+ [2][1][RTW89_UKRAINE][11] = 46,
+ [2][1][RTW89_CHILE][11] = 46,
+ [2][1][RTW89_QATAR][11] = 46,
[2][1][RTW89_FCC][12] = 6,
[2][1][RTW89_ETSI][12] = 44,
[2][1][RTW89_MKK][12] = 46,
[2][1][RTW89_IC][12] = 6,
- [2][1][RTW89_KCC][12] = 52,
+ [2][1][RTW89_KCC][12] = 48,
[2][1][RTW89_ACMA][12] = 44,
[2][1][RTW89_CN][12] = 42,
[2][1][RTW89_UK][12] = 44,
+ [2][1][RTW89_MEXICO][12] = 6,
+ [2][1][RTW89_UKRAINE][12] = 44,
+ [2][1][RTW89_CHILE][12] = 6,
+ [2][1][RTW89_QATAR][12] = 44,
[2][1][RTW89_FCC][13] = 127,
[2][1][RTW89_ETSI][13] = 127,
[2][1][RTW89_MKK][13] = 127,
@@ -34739,6 +46896,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][13] = 127,
[2][1][RTW89_CN][13] = 127,
[2][1][RTW89_UK][13] = 127,
+ [2][1][RTW89_MEXICO][13] = 127,
+ [2][1][RTW89_UKRAINE][13] = 127,
+ [2][1][RTW89_CHILE][13] = 127,
+ [2][1][RTW89_QATAR][13] = 127,
};
static
@@ -34747,168 +46908,168 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_WW][0] = 16,
[0][0][RTW89_WW][2] = 16,
[0][0][RTW89_WW][4] = 16,
- [0][0][RTW89_WW][6] = 10,
+ [0][0][RTW89_WW][6] = 16,
[0][0][RTW89_WW][8] = 16,
[0][0][RTW89_WW][10] = 16,
[0][0][RTW89_WW][12] = 16,
[0][0][RTW89_WW][14] = 16,
- [0][0][RTW89_WW][15] = 30,
- [0][0][RTW89_WW][17] = 30,
- [0][0][RTW89_WW][19] = 30,
- [0][0][RTW89_WW][21] = 30,
- [0][0][RTW89_WW][23] = 30,
- [0][0][RTW89_WW][25] = 30,
- [0][0][RTW89_WW][27] = 30,
- [0][0][RTW89_WW][29] = 30,
- [0][0][RTW89_WW][31] = 30,
- [0][0][RTW89_WW][33] = 30,
- [0][0][RTW89_WW][35] = 30,
+ [0][0][RTW89_WW][15] = 22,
+ [0][0][RTW89_WW][17] = 22,
+ [0][0][RTW89_WW][19] = 22,
+ [0][0][RTW89_WW][21] = 22,
+ [0][0][RTW89_WW][23] = 22,
+ [0][0][RTW89_WW][25] = 22,
+ [0][0][RTW89_WW][27] = 22,
+ [0][0][RTW89_WW][29] = 22,
+ [0][0][RTW89_WW][31] = 22,
+ [0][0][RTW89_WW][33] = 22,
+ [0][0][RTW89_WW][35] = 22,
[0][0][RTW89_WW][37] = 30,
- [0][0][RTW89_WW][38] = 28,
- [0][0][RTW89_WW][40] = 28,
- [0][0][RTW89_WW][42] = 28,
- [0][0][RTW89_WW][44] = 28,
- [0][0][RTW89_WW][46] = 28,
+ [0][0][RTW89_WW][38] = 26,
+ [0][0][RTW89_WW][40] = 26,
+ [0][0][RTW89_WW][42] = 26,
+ [0][0][RTW89_WW][44] = 26,
+ [0][0][RTW89_WW][46] = 26,
[0][0][RTW89_WW][48] = 46,
[0][0][RTW89_WW][50] = 44,
[0][0][RTW89_WW][52] = 34,
[0][1][RTW89_WW][0] = 4,
[0][1][RTW89_WW][2] = 4,
[0][1][RTW89_WW][4] = 4,
- [0][1][RTW89_WW][6] = 1,
+ [0][1][RTW89_WW][6] = 4,
[0][1][RTW89_WW][8] = 4,
[0][1][RTW89_WW][10] = 4,
[0][1][RTW89_WW][12] = 4,
[0][1][RTW89_WW][14] = 4,
- [0][1][RTW89_WW][15] = 18,
- [0][1][RTW89_WW][17] = 18,
- [0][1][RTW89_WW][19] = 18,
- [0][1][RTW89_WW][21] = 18,
- [0][1][RTW89_WW][23] = 18,
- [0][1][RTW89_WW][25] = 18,
- [0][1][RTW89_WW][27] = 16,
- [0][1][RTW89_WW][29] = 16,
- [0][1][RTW89_WW][31] = 16,
- [0][1][RTW89_WW][33] = 16,
- [0][1][RTW89_WW][35] = 16,
+ [0][1][RTW89_WW][15] = 10,
+ [0][1][RTW89_WW][17] = 10,
+ [0][1][RTW89_WW][19] = 10,
+ [0][1][RTW89_WW][21] = 10,
+ [0][1][RTW89_WW][23] = 10,
+ [0][1][RTW89_WW][25] = 10,
+ [0][1][RTW89_WW][27] = 10,
+ [0][1][RTW89_WW][29] = 10,
+ [0][1][RTW89_WW][31] = 10,
+ [0][1][RTW89_WW][33] = 10,
+ [0][1][RTW89_WW][35] = 10,
[0][1][RTW89_WW][37] = 18,
- [0][1][RTW89_WW][38] = 16,
- [0][1][RTW89_WW][40] = 16,
- [0][1][RTW89_WW][42] = 16,
- [0][1][RTW89_WW][44] = 16,
- [0][1][RTW89_WW][46] = 16,
+ [0][1][RTW89_WW][38] = 14,
+ [0][1][RTW89_WW][40] = 14,
+ [0][1][RTW89_WW][42] = 14,
+ [0][1][RTW89_WW][44] = 14,
+ [0][1][RTW89_WW][46] = 14,
[0][1][RTW89_WW][48] = 20,
[0][1][RTW89_WW][50] = 20,
[0][1][RTW89_WW][52] = 8,
[1][0][RTW89_WW][0] = 26,
[1][0][RTW89_WW][2] = 26,
[1][0][RTW89_WW][4] = 26,
- [1][0][RTW89_WW][6] = 24,
+ [1][0][RTW89_WW][6] = 26,
[1][0][RTW89_WW][8] = 26,
[1][0][RTW89_WW][10] = 26,
[1][0][RTW89_WW][12] = 26,
[1][0][RTW89_WW][14] = 26,
- [1][0][RTW89_WW][15] = 40,
- [1][0][RTW89_WW][17] = 40,
- [1][0][RTW89_WW][19] = 40,
- [1][0][RTW89_WW][21] = 40,
- [1][0][RTW89_WW][23] = 40,
- [1][0][RTW89_WW][25] = 40,
- [1][0][RTW89_WW][27] = 42,
- [1][0][RTW89_WW][29] = 42,
- [1][0][RTW89_WW][31] = 42,
- [1][0][RTW89_WW][33] = 42,
- [1][0][RTW89_WW][35] = 42,
+ [1][0][RTW89_WW][15] = 32,
+ [1][0][RTW89_WW][17] = 32,
+ [1][0][RTW89_WW][19] = 32,
+ [1][0][RTW89_WW][21] = 32,
+ [1][0][RTW89_WW][23] = 32,
+ [1][0][RTW89_WW][25] = 32,
+ [1][0][RTW89_WW][27] = 32,
+ [1][0][RTW89_WW][29] = 32,
+ [1][0][RTW89_WW][31] = 32,
+ [1][0][RTW89_WW][33] = 32,
+ [1][0][RTW89_WW][35] = 32,
[1][0][RTW89_WW][37] = 42,
- [1][0][RTW89_WW][38] = 28,
- [1][0][RTW89_WW][40] = 28,
- [1][0][RTW89_WW][42] = 28,
- [1][0][RTW89_WW][44] = 28,
- [1][0][RTW89_WW][46] = 28,
+ [1][0][RTW89_WW][38] = 26,
+ [1][0][RTW89_WW][40] = 26,
+ [1][0][RTW89_WW][42] = 26,
+ [1][0][RTW89_WW][44] = 26,
+ [1][0][RTW89_WW][46] = 26,
[1][0][RTW89_WW][48] = 56,
[1][0][RTW89_WW][50] = 58,
[1][0][RTW89_WW][52] = 56,
[1][1][RTW89_WW][0] = 14,
[1][1][RTW89_WW][2] = 14,
[1][1][RTW89_WW][4] = 14,
- [1][1][RTW89_WW][6] = 8,
+ [1][1][RTW89_WW][6] = 14,
[1][1][RTW89_WW][8] = 14,
[1][1][RTW89_WW][10] = 14,
[1][1][RTW89_WW][12] = 14,
[1][1][RTW89_WW][14] = 14,
- [1][1][RTW89_WW][15] = 28,
- [1][1][RTW89_WW][17] = 28,
- [1][1][RTW89_WW][19] = 28,
- [1][1][RTW89_WW][21] = 28,
- [1][1][RTW89_WW][23] = 28,
- [1][1][RTW89_WW][25] = 28,
- [1][1][RTW89_WW][27] = 30,
- [1][1][RTW89_WW][29] = 30,
- [1][1][RTW89_WW][31] = 30,
- [1][1][RTW89_WW][33] = 30,
- [1][1][RTW89_WW][35] = 30,
+ [1][1][RTW89_WW][15] = 20,
+ [1][1][RTW89_WW][17] = 20,
+ [1][1][RTW89_WW][19] = 20,
+ [1][1][RTW89_WW][21] = 20,
+ [1][1][RTW89_WW][23] = 20,
+ [1][1][RTW89_WW][25] = 20,
+ [1][1][RTW89_WW][27] = 20,
+ [1][1][RTW89_WW][29] = 20,
+ [1][1][RTW89_WW][31] = 20,
+ [1][1][RTW89_WW][33] = 20,
+ [1][1][RTW89_WW][35] = 20,
[1][1][RTW89_WW][37] = 32,
- [1][1][RTW89_WW][38] = 16,
- [1][1][RTW89_WW][40] = 16,
- [1][1][RTW89_WW][42] = 16,
- [1][1][RTW89_WW][44] = 16,
- [1][1][RTW89_WW][46] = 16,
+ [1][1][RTW89_WW][38] = 14,
+ [1][1][RTW89_WW][40] = 14,
+ [1][1][RTW89_WW][42] = 14,
+ [1][1][RTW89_WW][44] = 14,
+ [1][1][RTW89_WW][46] = 14,
[1][1][RTW89_WW][48] = 34,
[1][1][RTW89_WW][50] = 34,
[1][1][RTW89_WW][52] = 30,
[2][0][RTW89_WW][0] = 40,
[2][0][RTW89_WW][2] = 40,
[2][0][RTW89_WW][4] = 40,
- [2][0][RTW89_WW][6] = 36,
+ [2][0][RTW89_WW][6] = 38,
[2][0][RTW89_WW][8] = 40,
[2][0][RTW89_WW][10] = 40,
[2][0][RTW89_WW][12] = 40,
[2][0][RTW89_WW][14] = 40,
- [2][0][RTW89_WW][15] = 52,
- [2][0][RTW89_WW][17] = 52,
- [2][0][RTW89_WW][19] = 52,
- [2][0][RTW89_WW][21] = 52,
- [2][0][RTW89_WW][23] = 52,
- [2][0][RTW89_WW][25] = 52,
- [2][0][RTW89_WW][27] = 52,
- [2][0][RTW89_WW][29] = 52,
- [2][0][RTW89_WW][31] = 52,
- [2][0][RTW89_WW][33] = 52,
- [2][0][RTW89_WW][35] = 52,
+ [2][0][RTW89_WW][15] = 46,
+ [2][0][RTW89_WW][17] = 46,
+ [2][0][RTW89_WW][19] = 46,
+ [2][0][RTW89_WW][21] = 46,
+ [2][0][RTW89_WW][23] = 46,
+ [2][0][RTW89_WW][25] = 46,
+ [2][0][RTW89_WW][27] = 46,
+ [2][0][RTW89_WW][29] = 46,
+ [2][0][RTW89_WW][31] = 46,
+ [2][0][RTW89_WW][33] = 46,
+ [2][0][RTW89_WW][35] = 46,
[2][0][RTW89_WW][37] = 52,
- [2][0][RTW89_WW][38] = 28,
- [2][0][RTW89_WW][40] = 28,
- [2][0][RTW89_WW][42] = 28,
- [2][0][RTW89_WW][44] = 28,
- [2][0][RTW89_WW][46] = 28,
+ [2][0][RTW89_WW][38] = 26,
+ [2][0][RTW89_WW][40] = 26,
+ [2][0][RTW89_WW][42] = 26,
+ [2][0][RTW89_WW][44] = 26,
+ [2][0][RTW89_WW][46] = 26,
[2][0][RTW89_WW][48] = 64,
[2][0][RTW89_WW][50] = 64,
[2][0][RTW89_WW][52] = 64,
[2][1][RTW89_WW][0] = 26,
[2][1][RTW89_WW][2] = 26,
[2][1][RTW89_WW][4] = 26,
- [2][1][RTW89_WW][6] = 20,
+ [2][1][RTW89_WW][6] = 26,
[2][1][RTW89_WW][8] = 28,
[2][1][RTW89_WW][10] = 28,
[2][1][RTW89_WW][12] = 28,
[2][1][RTW89_WW][14] = 28,
- [2][1][RTW89_WW][15] = 40,
- [2][1][RTW89_WW][17] = 40,
- [2][1][RTW89_WW][19] = 40,
- [2][1][RTW89_WW][21] = 40,
- [2][1][RTW89_WW][23] = 40,
- [2][1][RTW89_WW][25] = 40,
- [2][1][RTW89_WW][27] = 40,
- [2][1][RTW89_WW][29] = 40,
- [2][1][RTW89_WW][31] = 40,
- [2][1][RTW89_WW][33] = 40,
- [2][1][RTW89_WW][35] = 40,
+ [2][1][RTW89_WW][15] = 34,
+ [2][1][RTW89_WW][17] = 34,
+ [2][1][RTW89_WW][19] = 34,
+ [2][1][RTW89_WW][21] = 34,
+ [2][1][RTW89_WW][23] = 34,
+ [2][1][RTW89_WW][25] = 34,
+ [2][1][RTW89_WW][27] = 34,
+ [2][1][RTW89_WW][29] = 34,
+ [2][1][RTW89_WW][31] = 34,
+ [2][1][RTW89_WW][33] = 34,
+ [2][1][RTW89_WW][35] = 34,
[2][1][RTW89_WW][37] = 42,
- [2][1][RTW89_WW][38] = 16,
- [2][1][RTW89_WW][40] = 16,
- [2][1][RTW89_WW][42] = 16,
- [2][1][RTW89_WW][44] = 16,
- [2][1][RTW89_WW][46] = 16,
+ [2][1][RTW89_WW][38] = 14,
+ [2][1][RTW89_WW][40] = 14,
+ [2][1][RTW89_WW][42] = 14,
+ [2][1][RTW89_WW][44] = 14,
+ [2][1][RTW89_WW][46] = 14,
[2][1][RTW89_WW][48] = 40,
[2][1][RTW89_WW][50] = 40,
[2][1][RTW89_WW][52] = 40,
@@ -34920,6 +47081,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][0] = 30,
[0][0][RTW89_CN][0] = 16,
[0][0][RTW89_UK][0] = 30,
+ [0][0][RTW89_MEXICO][0] = 50,
+ [0][0][RTW89_UKRAINE][0] = 22,
+ [0][0][RTW89_CHILE][0] = 50,
+ [0][0][RTW89_QATAR][0] = 30,
[0][0][RTW89_FCC][2] = 50,
[0][0][RTW89_ETSI][2] = 30,
[0][0][RTW89_MKK][2] = 36,
@@ -34928,6 +47093,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][2] = 30,
[0][0][RTW89_CN][2] = 16,
[0][0][RTW89_UK][2] = 30,
+ [0][0][RTW89_MEXICO][2] = 50,
+ [0][0][RTW89_UKRAINE][2] = 22,
+ [0][0][RTW89_CHILE][2] = 50,
+ [0][0][RTW89_QATAR][2] = 30,
[0][0][RTW89_FCC][4] = 50,
[0][0][RTW89_ETSI][4] = 30,
[0][0][RTW89_MKK][4] = 22,
@@ -34936,30 +47105,46 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][4] = 30,
[0][0][RTW89_CN][4] = 16,
[0][0][RTW89_UK][4] = 30,
+ [0][0][RTW89_MEXICO][4] = 50,
+ [0][0][RTW89_UKRAINE][4] = 22,
+ [0][0][RTW89_CHILE][4] = 50,
+ [0][0][RTW89_QATAR][4] = 30,
[0][0][RTW89_FCC][6] = 50,
[0][0][RTW89_ETSI][6] = 30,
[0][0][RTW89_MKK][6] = 22,
[0][0][RTW89_IC][6] = 32,
- [0][0][RTW89_KCC][6] = 10,
+ [0][0][RTW89_KCC][6] = 18,
[0][0][RTW89_ACMA][6] = 30,
[0][0][RTW89_CN][6] = 16,
[0][0][RTW89_UK][6] = 30,
+ [0][0][RTW89_MEXICO][6] = 50,
+ [0][0][RTW89_UKRAINE][6] = 22,
+ [0][0][RTW89_CHILE][6] = 50,
+ [0][0][RTW89_QATAR][6] = 30,
[0][0][RTW89_FCC][8] = 52,
[0][0][RTW89_ETSI][8] = 28,
[0][0][RTW89_MKK][8] = 18,
[0][0][RTW89_IC][8] = 52,
- [0][0][RTW89_KCC][8] = 44,
+ [0][0][RTW89_KCC][8] = 40,
[0][0][RTW89_ACMA][8] = 28,
[0][0][RTW89_CN][8] = 16,
[0][0][RTW89_UK][8] = 28,
+ [0][0][RTW89_MEXICO][8] = 52,
+ [0][0][RTW89_UKRAINE][8] = 22,
+ [0][0][RTW89_CHILE][8] = 52,
+ [0][0][RTW89_QATAR][8] = 28,
[0][0][RTW89_FCC][10] = 52,
[0][0][RTW89_ETSI][10] = 28,
[0][0][RTW89_MKK][10] = 18,
[0][0][RTW89_IC][10] = 52,
- [0][0][RTW89_KCC][10] = 44,
+ [0][0][RTW89_KCC][10] = 40,
[0][0][RTW89_ACMA][10] = 28,
[0][0][RTW89_CN][10] = 16,
[0][0][RTW89_UK][10] = 28,
+ [0][0][RTW89_MEXICO][10] = 52,
+ [0][0][RTW89_UKRAINE][10] = 22,
+ [0][0][RTW89_CHILE][10] = 52,
+ [0][0][RTW89_QATAR][10] = 28,
[0][0][RTW89_FCC][12] = 52,
[0][0][RTW89_ETSI][12] = 28,
[0][0][RTW89_MKK][12] = 34,
@@ -34968,6 +47153,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][12] = 28,
[0][0][RTW89_CN][12] = 16,
[0][0][RTW89_UK][12] = 28,
+ [0][0][RTW89_MEXICO][12] = 52,
+ [0][0][RTW89_UKRAINE][12] = 22,
+ [0][0][RTW89_CHILE][12] = 52,
+ [0][0][RTW89_QATAR][12] = 28,
[0][0][RTW89_FCC][14] = 52,
[0][0][RTW89_ETSI][14] = 28,
[0][0][RTW89_MKK][14] = 34,
@@ -34976,70 +47165,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][14] = 28,
[0][0][RTW89_CN][14] = 16,
[0][0][RTW89_UK][14] = 28,
+ [0][0][RTW89_MEXICO][14] = 52,
+ [0][0][RTW89_UKRAINE][14] = 22,
+ [0][0][RTW89_CHILE][14] = 52,
+ [0][0][RTW89_QATAR][14] = 28,
[0][0][RTW89_FCC][15] = 52,
[0][0][RTW89_ETSI][15] = 30,
[0][0][RTW89_MKK][15] = 56,
[0][0][RTW89_IC][15] = 52,
- [0][0][RTW89_KCC][15] = 42,
+ [0][0][RTW89_KCC][15] = 40,
[0][0][RTW89_ACMA][15] = 30,
[0][0][RTW89_CN][15] = 127,
[0][0][RTW89_UK][15] = 30,
+ [0][0][RTW89_MEXICO][15] = 52,
+ [0][0][RTW89_UKRAINE][15] = 22,
+ [0][0][RTW89_CHILE][15] = 52,
+ [0][0][RTW89_QATAR][15] = 30,
[0][0][RTW89_FCC][17] = 52,
[0][0][RTW89_ETSI][17] = 30,
[0][0][RTW89_MKK][17] = 58,
[0][0][RTW89_IC][17] = 52,
- [0][0][RTW89_KCC][17] = 42,
+ [0][0][RTW89_KCC][17] = 40,
[0][0][RTW89_ACMA][17] = 30,
[0][0][RTW89_CN][17] = 127,
[0][0][RTW89_UK][17] = 30,
+ [0][0][RTW89_MEXICO][17] = 52,
+ [0][0][RTW89_UKRAINE][17] = 22,
+ [0][0][RTW89_CHILE][17] = 52,
+ [0][0][RTW89_QATAR][17] = 30,
[0][0][RTW89_FCC][19] = 52,
[0][0][RTW89_ETSI][19] = 30,
[0][0][RTW89_MKK][19] = 58,
[0][0][RTW89_IC][19] = 52,
- [0][0][RTW89_KCC][19] = 42,
+ [0][0][RTW89_KCC][19] = 40,
[0][0][RTW89_ACMA][19] = 30,
[0][0][RTW89_CN][19] = 127,
[0][0][RTW89_UK][19] = 30,
+ [0][0][RTW89_MEXICO][19] = 52,
+ [0][0][RTW89_UKRAINE][19] = 22,
+ [0][0][RTW89_CHILE][19] = 52,
+ [0][0][RTW89_QATAR][19] = 30,
[0][0][RTW89_FCC][21] = 52,
[0][0][RTW89_ETSI][21] = 30,
[0][0][RTW89_MKK][21] = 58,
[0][0][RTW89_IC][21] = 52,
- [0][0][RTW89_KCC][21] = 42,
+ [0][0][RTW89_KCC][21] = 40,
[0][0][RTW89_ACMA][21] = 30,
[0][0][RTW89_CN][21] = 127,
[0][0][RTW89_UK][21] = 30,
+ [0][0][RTW89_MEXICO][21] = 52,
+ [0][0][RTW89_UKRAINE][21] = 22,
+ [0][0][RTW89_CHILE][21] = 52,
+ [0][0][RTW89_QATAR][21] = 30,
[0][0][RTW89_FCC][23] = 52,
[0][0][RTW89_ETSI][23] = 30,
[0][0][RTW89_MKK][23] = 58,
[0][0][RTW89_IC][23] = 52,
- [0][0][RTW89_KCC][23] = 42,
+ [0][0][RTW89_KCC][23] = 40,
[0][0][RTW89_ACMA][23] = 30,
[0][0][RTW89_CN][23] = 127,
[0][0][RTW89_UK][23] = 30,
+ [0][0][RTW89_MEXICO][23] = 52,
+ [0][0][RTW89_UKRAINE][23] = 22,
+ [0][0][RTW89_CHILE][23] = 52,
+ [0][0][RTW89_QATAR][23] = 30,
[0][0][RTW89_FCC][25] = 52,
[0][0][RTW89_ETSI][25] = 30,
[0][0][RTW89_MKK][25] = 58,
[0][0][RTW89_IC][25] = 127,
- [0][0][RTW89_KCC][25] = 42,
+ [0][0][RTW89_KCC][25] = 40,
[0][0][RTW89_ACMA][25] = 127,
[0][0][RTW89_CN][25] = 127,
[0][0][RTW89_UK][25] = 30,
+ [0][0][RTW89_MEXICO][25] = 52,
+ [0][0][RTW89_UKRAINE][25] = 22,
+ [0][0][RTW89_CHILE][25] = 52,
+ [0][0][RTW89_QATAR][25] = 30,
[0][0][RTW89_FCC][27] = 52,
[0][0][RTW89_ETSI][27] = 30,
[0][0][RTW89_MKK][27] = 58,
[0][0][RTW89_IC][27] = 127,
- [0][0][RTW89_KCC][27] = 42,
+ [0][0][RTW89_KCC][27] = 40,
[0][0][RTW89_ACMA][27] = 127,
[0][0][RTW89_CN][27] = 127,
[0][0][RTW89_UK][27] = 30,
+ [0][0][RTW89_MEXICO][27] = 52,
+ [0][0][RTW89_UKRAINE][27] = 22,
+ [0][0][RTW89_CHILE][27] = 52,
+ [0][0][RTW89_QATAR][27] = 30,
[0][0][RTW89_FCC][29] = 52,
[0][0][RTW89_ETSI][29] = 30,
[0][0][RTW89_MKK][29] = 58,
[0][0][RTW89_IC][29] = 127,
- [0][0][RTW89_KCC][29] = 42,
+ [0][0][RTW89_KCC][29] = 40,
[0][0][RTW89_ACMA][29] = 127,
[0][0][RTW89_CN][29] = 127,
[0][0][RTW89_UK][29] = 30,
+ [0][0][RTW89_MEXICO][29] = 52,
+ [0][0][RTW89_UKRAINE][29] = 22,
+ [0][0][RTW89_CHILE][29] = 52,
+ [0][0][RTW89_QATAR][29] = 30,
[0][0][RTW89_FCC][31] = 52,
[0][0][RTW89_ETSI][31] = 30,
[0][0][RTW89_MKK][31] = 58,
@@ -35048,6 +47273,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][31] = 30,
[0][0][RTW89_CN][31] = 127,
[0][0][RTW89_UK][31] = 30,
+ [0][0][RTW89_MEXICO][31] = 52,
+ [0][0][RTW89_UKRAINE][31] = 22,
+ [0][0][RTW89_CHILE][31] = 52,
+ [0][0][RTW89_QATAR][31] = 30,
[0][0][RTW89_FCC][33] = 44,
[0][0][RTW89_ETSI][33] = 30,
[0][0][RTW89_MKK][33] = 58,
@@ -35056,6 +47285,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][33] = 30,
[0][0][RTW89_CN][33] = 127,
[0][0][RTW89_UK][33] = 30,
+ [0][0][RTW89_MEXICO][33] = 44,
+ [0][0][RTW89_UKRAINE][33] = 22,
+ [0][0][RTW89_CHILE][33] = 44,
+ [0][0][RTW89_QATAR][33] = 30,
[0][0][RTW89_FCC][35] = 44,
[0][0][RTW89_ETSI][35] = 30,
[0][0][RTW89_MKK][35] = 58,
@@ -35064,6 +47297,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][35] = 30,
[0][0][RTW89_CN][35] = 127,
[0][0][RTW89_UK][35] = 30,
+ [0][0][RTW89_MEXICO][35] = 44,
+ [0][0][RTW89_UKRAINE][35] = 22,
+ [0][0][RTW89_CHILE][35] = 44,
+ [0][0][RTW89_QATAR][35] = 30,
[0][0][RTW89_FCC][37] = 52,
[0][0][RTW89_ETSI][37] = 127,
[0][0][RTW89_MKK][37] = 58,
@@ -35072,6 +47309,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][37] = 52,
[0][0][RTW89_CN][37] = 127,
[0][0][RTW89_UK][37] = 30,
+ [0][0][RTW89_MEXICO][37] = 52,
+ [0][0][RTW89_UKRAINE][37] = 127,
+ [0][0][RTW89_CHILE][37] = 52,
+ [0][0][RTW89_QATAR][37] = 127,
[0][0][RTW89_FCC][38] = 64,
[0][0][RTW89_ETSI][38] = 28,
[0][0][RTW89_MKK][38] = 127,
@@ -35080,6 +47321,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][38] = 64,
[0][0][RTW89_CN][38] = 54,
[0][0][RTW89_UK][38] = 30,
+ [0][0][RTW89_MEXICO][38] = 64,
+ [0][0][RTW89_UKRAINE][38] = 26,
+ [0][0][RTW89_CHILE][38] = 64,
+ [0][0][RTW89_QATAR][38] = 26,
[0][0][RTW89_FCC][40] = 64,
[0][0][RTW89_ETSI][40] = 28,
[0][0][RTW89_MKK][40] = 127,
@@ -35088,6 +47333,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][40] = 64,
[0][0][RTW89_CN][40] = 54,
[0][0][RTW89_UK][40] = 30,
+ [0][0][RTW89_MEXICO][40] = 64,
+ [0][0][RTW89_UKRAINE][40] = 26,
+ [0][0][RTW89_CHILE][40] = 64,
+ [0][0][RTW89_QATAR][40] = 26,
[0][0][RTW89_FCC][42] = 60,
[0][0][RTW89_ETSI][42] = 28,
[0][0][RTW89_MKK][42] = 127,
@@ -35096,6 +47345,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][42] = 60,
[0][0][RTW89_CN][42] = 54,
[0][0][RTW89_UK][42] = 30,
+ [0][0][RTW89_MEXICO][42] = 60,
+ [0][0][RTW89_UKRAINE][42] = 26,
+ [0][0][RTW89_CHILE][42] = 60,
+ [0][0][RTW89_QATAR][42] = 26,
[0][0][RTW89_FCC][44] = 60,
[0][0][RTW89_ETSI][44] = 28,
[0][0][RTW89_MKK][44] = 127,
@@ -35104,6 +47357,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][44] = 60,
[0][0][RTW89_CN][44] = 54,
[0][0][RTW89_UK][44] = 30,
+ [0][0][RTW89_MEXICO][44] = 60,
+ [0][0][RTW89_UKRAINE][44] = 26,
+ [0][0][RTW89_CHILE][44] = 60,
+ [0][0][RTW89_QATAR][44] = 26,
[0][0][RTW89_FCC][46] = 60,
[0][0][RTW89_ETSI][46] = 28,
[0][0][RTW89_MKK][46] = 127,
@@ -35112,6 +47369,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][46] = 60,
[0][0][RTW89_CN][46] = 54,
[0][0][RTW89_UK][46] = 30,
+ [0][0][RTW89_MEXICO][46] = 60,
+ [0][0][RTW89_UKRAINE][46] = 26,
+ [0][0][RTW89_CHILE][46] = 60,
+ [0][0][RTW89_QATAR][46] = 26,
[0][0][RTW89_FCC][48] = 46,
[0][0][RTW89_ETSI][48] = 127,
[0][0][RTW89_MKK][48] = 127,
@@ -35120,6 +47381,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][48] = 127,
[0][0][RTW89_CN][48] = 127,
[0][0][RTW89_UK][48] = 127,
+ [0][0][RTW89_MEXICO][48] = 127,
+ [0][0][RTW89_UKRAINE][48] = 127,
+ [0][0][RTW89_CHILE][48] = 127,
+ [0][0][RTW89_QATAR][48] = 127,
[0][0][RTW89_FCC][50] = 44,
[0][0][RTW89_ETSI][50] = 127,
[0][0][RTW89_MKK][50] = 127,
@@ -35128,6 +47393,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][50] = 127,
[0][0][RTW89_CN][50] = 127,
[0][0][RTW89_UK][50] = 127,
+ [0][0][RTW89_MEXICO][50] = 127,
+ [0][0][RTW89_UKRAINE][50] = 127,
+ [0][0][RTW89_CHILE][50] = 127,
+ [0][0][RTW89_QATAR][50] = 127,
[0][0][RTW89_FCC][52] = 34,
[0][0][RTW89_ETSI][52] = 127,
[0][0][RTW89_MKK][52] = 127,
@@ -35136,38 +47405,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][0][RTW89_ACMA][52] = 127,
[0][0][RTW89_CN][52] = 127,
[0][0][RTW89_UK][52] = 127,
+ [0][0][RTW89_MEXICO][52] = 127,
+ [0][0][RTW89_UKRAINE][52] = 127,
+ [0][0][RTW89_CHILE][52] = 127,
+ [0][0][RTW89_QATAR][52] = 127,
[0][1][RTW89_FCC][0] = 30,
[0][1][RTW89_ETSI][0] = 18,
[0][1][RTW89_MKK][0] = 20,
[0][1][RTW89_IC][0] = 8,
- [0][1][RTW89_KCC][0] = 26,
+ [0][1][RTW89_KCC][0] = 32,
[0][1][RTW89_ACMA][0] = 18,
[0][1][RTW89_CN][0] = 4,
[0][1][RTW89_UK][0] = 18,
+ [0][1][RTW89_MEXICO][0] = 30,
+ [0][1][RTW89_UKRAINE][0] = 10,
+ [0][1][RTW89_CHILE][0] = 30,
+ [0][1][RTW89_QATAR][0] = 18,
[0][1][RTW89_FCC][2] = 32,
[0][1][RTW89_ETSI][2] = 18,
[0][1][RTW89_MKK][2] = 20,
[0][1][RTW89_IC][2] = 8,
- [0][1][RTW89_KCC][2] = 26,
+ [0][1][RTW89_KCC][2] = 32,
[0][1][RTW89_ACMA][2] = 18,
[0][1][RTW89_CN][2] = 4,
[0][1][RTW89_UK][2] = 18,
+ [0][1][RTW89_MEXICO][2] = 32,
+ [0][1][RTW89_UKRAINE][2] = 10,
+ [0][1][RTW89_CHILE][2] = 32,
+ [0][1][RTW89_QATAR][2] = 18,
[0][1][RTW89_FCC][4] = 30,
[0][1][RTW89_ETSI][4] = 18,
[0][1][RTW89_MKK][4] = 8,
[0][1][RTW89_IC][4] = 8,
- [0][1][RTW89_KCC][4] = 26,
+ [0][1][RTW89_KCC][4] = 32,
[0][1][RTW89_ACMA][4] = 18,
[0][1][RTW89_CN][4] = 4,
[0][1][RTW89_UK][4] = 18,
+ [0][1][RTW89_MEXICO][4] = 30,
+ [0][1][RTW89_UKRAINE][4] = 10,
+ [0][1][RTW89_CHILE][4] = 30,
+ [0][1][RTW89_QATAR][4] = 18,
[0][1][RTW89_FCC][6] = 30,
[0][1][RTW89_ETSI][6] = 18,
[0][1][RTW89_MKK][6] = 8,
[0][1][RTW89_IC][6] = 8,
- [0][1][RTW89_KCC][6] = 0,
+ [0][1][RTW89_KCC][6] = 6,
[0][1][RTW89_ACMA][6] = 18,
[0][1][RTW89_CN][6] = 4,
[0][1][RTW89_UK][6] = 18,
+ [0][1][RTW89_MEXICO][6] = 30,
+ [0][1][RTW89_UKRAINE][6] = 10,
+ [0][1][RTW89_CHILE][6] = 30,
+ [0][1][RTW89_QATAR][6] = 18,
[0][1][RTW89_FCC][8] = 30,
[0][1][RTW89_ETSI][8] = 16,
[0][1][RTW89_MKK][8] = 20,
@@ -35176,6 +47465,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][8] = 16,
[0][1][RTW89_CN][8] = 4,
[0][1][RTW89_UK][8] = 16,
+ [0][1][RTW89_MEXICO][8] = 30,
+ [0][1][RTW89_UKRAINE][8] = 10,
+ [0][1][RTW89_CHILE][8] = 30,
+ [0][1][RTW89_QATAR][8] = 16,
[0][1][RTW89_FCC][10] = 30,
[0][1][RTW89_ETSI][10] = 16,
[0][1][RTW89_MKK][10] = 20,
@@ -35184,22 +47477,34 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][10] = 16,
[0][1][RTW89_CN][10] = 4,
[0][1][RTW89_UK][10] = 16,
+ [0][1][RTW89_MEXICO][10] = 30,
+ [0][1][RTW89_UKRAINE][10] = 10,
+ [0][1][RTW89_CHILE][10] = 30,
+ [0][1][RTW89_QATAR][10] = 16,
[0][1][RTW89_FCC][12] = 30,
[0][1][RTW89_ETSI][12] = 16,
[0][1][RTW89_MKK][12] = 34,
[0][1][RTW89_IC][12] = 30,
- [0][1][RTW89_KCC][12] = 28,
+ [0][1][RTW89_KCC][12] = 26,
[0][1][RTW89_ACMA][12] = 16,
[0][1][RTW89_CN][12] = 4,
[0][1][RTW89_UK][12] = 16,
+ [0][1][RTW89_MEXICO][12] = 30,
+ [0][1][RTW89_UKRAINE][12] = 10,
+ [0][1][RTW89_CHILE][12] = 30,
+ [0][1][RTW89_QATAR][12] = 16,
[0][1][RTW89_FCC][14] = 30,
[0][1][RTW89_ETSI][14] = 16,
[0][1][RTW89_MKK][14] = 34,
[0][1][RTW89_IC][14] = 30,
- [0][1][RTW89_KCC][14] = 28,
+ [0][1][RTW89_KCC][14] = 26,
[0][1][RTW89_ACMA][14] = 16,
[0][1][RTW89_CN][14] = 4,
[0][1][RTW89_UK][14] = 16,
+ [0][1][RTW89_MEXICO][14] = 30,
+ [0][1][RTW89_UKRAINE][14] = 10,
+ [0][1][RTW89_CHILE][14] = 30,
+ [0][1][RTW89_QATAR][14] = 16,
[0][1][RTW89_FCC][15] = 32,
[0][1][RTW89_ETSI][15] = 18,
[0][1][RTW89_MKK][15] = 44,
@@ -35208,6 +47513,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][15] = 18,
[0][1][RTW89_CN][15] = 127,
[0][1][RTW89_UK][15] = 18,
+ [0][1][RTW89_MEXICO][15] = 32,
+ [0][1][RTW89_UKRAINE][15] = 10,
+ [0][1][RTW89_CHILE][15] = 32,
+ [0][1][RTW89_QATAR][15] = 18,
[0][1][RTW89_FCC][17] = 32,
[0][1][RTW89_ETSI][17] = 18,
[0][1][RTW89_MKK][17] = 44,
@@ -35216,6 +47525,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][17] = 18,
[0][1][RTW89_CN][17] = 127,
[0][1][RTW89_UK][17] = 18,
+ [0][1][RTW89_MEXICO][17] = 32,
+ [0][1][RTW89_UKRAINE][17] = 10,
+ [0][1][RTW89_CHILE][17] = 32,
+ [0][1][RTW89_QATAR][17] = 18,
[0][1][RTW89_FCC][19] = 32,
[0][1][RTW89_ETSI][19] = 18,
[0][1][RTW89_MKK][19] = 44,
@@ -35224,6 +47537,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][19] = 18,
[0][1][RTW89_CN][19] = 127,
[0][1][RTW89_UK][19] = 18,
+ [0][1][RTW89_MEXICO][19] = 32,
+ [0][1][RTW89_UKRAINE][19] = 10,
+ [0][1][RTW89_CHILE][19] = 32,
+ [0][1][RTW89_QATAR][19] = 18,
[0][1][RTW89_FCC][21] = 32,
[0][1][RTW89_ETSI][21] = 18,
[0][1][RTW89_MKK][21] = 44,
@@ -35232,6 +47549,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][21] = 18,
[0][1][RTW89_CN][21] = 127,
[0][1][RTW89_UK][21] = 18,
+ [0][1][RTW89_MEXICO][21] = 32,
+ [0][1][RTW89_UKRAINE][21] = 10,
+ [0][1][RTW89_CHILE][21] = 32,
+ [0][1][RTW89_QATAR][21] = 18,
[0][1][RTW89_FCC][23] = 32,
[0][1][RTW89_ETSI][23] = 18,
[0][1][RTW89_MKK][23] = 44,
@@ -35240,6 +47561,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][23] = 18,
[0][1][RTW89_CN][23] = 127,
[0][1][RTW89_UK][23] = 18,
+ [0][1][RTW89_MEXICO][23] = 32,
+ [0][1][RTW89_UKRAINE][23] = 10,
+ [0][1][RTW89_CHILE][23] = 32,
+ [0][1][RTW89_QATAR][23] = 18,
[0][1][RTW89_FCC][25] = 32,
[0][1][RTW89_ETSI][25] = 18,
[0][1][RTW89_MKK][25] = 44,
@@ -35248,6 +47573,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][25] = 127,
[0][1][RTW89_CN][25] = 127,
[0][1][RTW89_UK][25] = 18,
+ [0][1][RTW89_MEXICO][25] = 32,
+ [0][1][RTW89_UKRAINE][25] = 10,
+ [0][1][RTW89_CHILE][25] = 32,
+ [0][1][RTW89_QATAR][25] = 18,
[0][1][RTW89_FCC][27] = 32,
[0][1][RTW89_ETSI][27] = 16,
[0][1][RTW89_MKK][27] = 44,
@@ -35256,6 +47585,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][27] = 127,
[0][1][RTW89_CN][27] = 127,
[0][1][RTW89_UK][27] = 16,
+ [0][1][RTW89_MEXICO][27] = 32,
+ [0][1][RTW89_UKRAINE][27] = 10,
+ [0][1][RTW89_CHILE][27] = 32,
+ [0][1][RTW89_QATAR][27] = 16,
[0][1][RTW89_FCC][29] = 32,
[0][1][RTW89_ETSI][29] = 16,
[0][1][RTW89_MKK][29] = 44,
@@ -35264,6 +47597,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][29] = 127,
[0][1][RTW89_CN][29] = 127,
[0][1][RTW89_UK][29] = 16,
+ [0][1][RTW89_MEXICO][29] = 32,
+ [0][1][RTW89_UKRAINE][29] = 10,
+ [0][1][RTW89_CHILE][29] = 32,
+ [0][1][RTW89_QATAR][29] = 16,
[0][1][RTW89_FCC][31] = 32,
[0][1][RTW89_ETSI][31] = 16,
[0][1][RTW89_MKK][31] = 44,
@@ -35272,6 +47609,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][31] = 16,
[0][1][RTW89_CN][31] = 127,
[0][1][RTW89_UK][31] = 16,
+ [0][1][RTW89_MEXICO][31] = 32,
+ [0][1][RTW89_UKRAINE][31] = 10,
+ [0][1][RTW89_CHILE][31] = 32,
+ [0][1][RTW89_QATAR][31] = 16,
[0][1][RTW89_FCC][33] = 30,
[0][1][RTW89_ETSI][33] = 16,
[0][1][RTW89_MKK][33] = 44,
@@ -35280,6 +47621,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][33] = 16,
[0][1][RTW89_CN][33] = 127,
[0][1][RTW89_UK][33] = 16,
+ [0][1][RTW89_MEXICO][33] = 30,
+ [0][1][RTW89_UKRAINE][33] = 10,
+ [0][1][RTW89_CHILE][33] = 30,
+ [0][1][RTW89_QATAR][33] = 16,
[0][1][RTW89_FCC][35] = 30,
[0][1][RTW89_ETSI][35] = 16,
[0][1][RTW89_MKK][35] = 44,
@@ -35288,6 +47633,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][35] = 16,
[0][1][RTW89_CN][35] = 127,
[0][1][RTW89_UK][35] = 16,
+ [0][1][RTW89_MEXICO][35] = 30,
+ [0][1][RTW89_UKRAINE][35] = 10,
+ [0][1][RTW89_CHILE][35] = 30,
+ [0][1][RTW89_QATAR][35] = 16,
[0][1][RTW89_FCC][37] = 34,
[0][1][RTW89_ETSI][37] = 127,
[0][1][RTW89_MKK][37] = 44,
@@ -35296,46 +47645,70 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][37] = 34,
[0][1][RTW89_CN][37] = 127,
[0][1][RTW89_UK][37] = 18,
+ [0][1][RTW89_MEXICO][37] = 34,
+ [0][1][RTW89_UKRAINE][37] = 127,
+ [0][1][RTW89_CHILE][37] = 34,
+ [0][1][RTW89_QATAR][37] = 127,
[0][1][RTW89_FCC][38] = 62,
[0][1][RTW89_ETSI][38] = 16,
[0][1][RTW89_MKK][38] = 127,
[0][1][RTW89_IC][38] = 62,
- [0][1][RTW89_KCC][38] = 28,
+ [0][1][RTW89_KCC][38] = 30,
[0][1][RTW89_ACMA][38] = 62,
[0][1][RTW89_CN][38] = 42,
[0][1][RTW89_UK][38] = 18,
+ [0][1][RTW89_MEXICO][38] = 62,
+ [0][1][RTW89_UKRAINE][38] = 14,
+ [0][1][RTW89_CHILE][38] = 62,
+ [0][1][RTW89_QATAR][38] = 14,
[0][1][RTW89_FCC][40] = 62,
[0][1][RTW89_ETSI][40] = 16,
[0][1][RTW89_MKK][40] = 127,
[0][1][RTW89_IC][40] = 62,
- [0][1][RTW89_KCC][40] = 28,
+ [0][1][RTW89_KCC][40] = 30,
[0][1][RTW89_ACMA][40] = 62,
[0][1][RTW89_CN][40] = 42,
[0][1][RTW89_UK][40] = 18,
+ [0][1][RTW89_MEXICO][40] = 62,
+ [0][1][RTW89_UKRAINE][40] = 14,
+ [0][1][RTW89_CHILE][40] = 62,
+ [0][1][RTW89_QATAR][40] = 14,
[0][1][RTW89_FCC][42] = 58,
[0][1][RTW89_ETSI][42] = 16,
[0][1][RTW89_MKK][42] = 127,
[0][1][RTW89_IC][42] = 58,
- [0][1][RTW89_KCC][42] = 28,
+ [0][1][RTW89_KCC][42] = 30,
[0][1][RTW89_ACMA][42] = 58,
[0][1][RTW89_CN][42] = 42,
[0][1][RTW89_UK][42] = 18,
+ [0][1][RTW89_MEXICO][42] = 58,
+ [0][1][RTW89_UKRAINE][42] = 14,
+ [0][1][RTW89_CHILE][42] = 58,
+ [0][1][RTW89_QATAR][42] = 14,
[0][1][RTW89_FCC][44] = 56,
[0][1][RTW89_ETSI][44] = 16,
[0][1][RTW89_MKK][44] = 127,
[0][1][RTW89_IC][44] = 56,
- [0][1][RTW89_KCC][44] = 28,
+ [0][1][RTW89_KCC][44] = 30,
[0][1][RTW89_ACMA][44] = 56,
[0][1][RTW89_CN][44] = 42,
[0][1][RTW89_UK][44] = 18,
+ [0][1][RTW89_MEXICO][44] = 56,
+ [0][1][RTW89_UKRAINE][44] = 14,
+ [0][1][RTW89_CHILE][44] = 56,
+ [0][1][RTW89_QATAR][44] = 14,
[0][1][RTW89_FCC][46] = 56,
[0][1][RTW89_ETSI][46] = 16,
[0][1][RTW89_MKK][46] = 127,
[0][1][RTW89_IC][46] = 56,
- [0][1][RTW89_KCC][46] = 28,
+ [0][1][RTW89_KCC][46] = 30,
[0][1][RTW89_ACMA][46] = 56,
[0][1][RTW89_CN][46] = 42,
[0][1][RTW89_UK][46] = 18,
+ [0][1][RTW89_MEXICO][46] = 56,
+ [0][1][RTW89_UKRAINE][46] = 14,
+ [0][1][RTW89_CHILE][46] = 56,
+ [0][1][RTW89_QATAR][46] = 14,
[0][1][RTW89_FCC][48] = 20,
[0][1][RTW89_ETSI][48] = 127,
[0][1][RTW89_MKK][48] = 127,
@@ -35344,6 +47717,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][48] = 127,
[0][1][RTW89_CN][48] = 127,
[0][1][RTW89_UK][48] = 127,
+ [0][1][RTW89_MEXICO][48] = 127,
+ [0][1][RTW89_UKRAINE][48] = 127,
+ [0][1][RTW89_CHILE][48] = 127,
+ [0][1][RTW89_QATAR][48] = 127,
[0][1][RTW89_FCC][50] = 20,
[0][1][RTW89_ETSI][50] = 127,
[0][1][RTW89_MKK][50] = 127,
@@ -35352,6 +47729,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][50] = 127,
[0][1][RTW89_CN][50] = 127,
[0][1][RTW89_UK][50] = 127,
+ [0][1][RTW89_MEXICO][50] = 127,
+ [0][1][RTW89_UKRAINE][50] = 127,
+ [0][1][RTW89_CHILE][50] = 127,
+ [0][1][RTW89_QATAR][50] = 127,
[0][1][RTW89_FCC][52] = 8,
[0][1][RTW89_ETSI][52] = 127,
[0][1][RTW89_MKK][52] = 127,
@@ -35360,70 +47741,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[0][1][RTW89_ACMA][52] = 127,
[0][1][RTW89_CN][52] = 127,
[0][1][RTW89_UK][52] = 127,
+ [0][1][RTW89_MEXICO][52] = 127,
+ [0][1][RTW89_UKRAINE][52] = 127,
+ [0][1][RTW89_CHILE][52] = 127,
+ [0][1][RTW89_QATAR][52] = 127,
[1][0][RTW89_FCC][0] = 62,
[1][0][RTW89_ETSI][0] = 40,
[1][0][RTW89_MKK][0] = 48,
[1][0][RTW89_IC][0] = 42,
- [1][0][RTW89_KCC][0] = 50,
+ [1][0][RTW89_KCC][0] = 54,
[1][0][RTW89_ACMA][0] = 40,
[1][0][RTW89_CN][0] = 26,
[1][0][RTW89_UK][0] = 40,
+ [1][0][RTW89_MEXICO][0] = 62,
+ [1][0][RTW89_UKRAINE][0] = 32,
+ [1][0][RTW89_CHILE][0] = 62,
+ [1][0][RTW89_QATAR][0] = 40,
[1][0][RTW89_FCC][2] = 62,
[1][0][RTW89_ETSI][2] = 40,
[1][0][RTW89_MKK][2] = 48,
[1][0][RTW89_IC][2] = 42,
- [1][0][RTW89_KCC][2] = 50,
+ [1][0][RTW89_KCC][2] = 54,
[1][0][RTW89_ACMA][2] = 40,
[1][0][RTW89_CN][2] = 26,
[1][0][RTW89_UK][2] = 40,
+ [1][0][RTW89_MEXICO][2] = 62,
+ [1][0][RTW89_UKRAINE][2] = 32,
+ [1][0][RTW89_CHILE][2] = 62,
+ [1][0][RTW89_QATAR][2] = 40,
[1][0][RTW89_FCC][4] = 64,
[1][0][RTW89_ETSI][4] = 40,
[1][0][RTW89_MKK][4] = 40,
[1][0][RTW89_IC][4] = 42,
- [1][0][RTW89_KCC][4] = 50,
+ [1][0][RTW89_KCC][4] = 54,
[1][0][RTW89_ACMA][4] = 40,
[1][0][RTW89_CN][4] = 26,
[1][0][RTW89_UK][4] = 40,
+ [1][0][RTW89_MEXICO][4] = 64,
+ [1][0][RTW89_UKRAINE][4] = 32,
+ [1][0][RTW89_CHILE][4] = 64,
+ [1][0][RTW89_QATAR][4] = 40,
[1][0][RTW89_FCC][6] = 64,
[1][0][RTW89_ETSI][6] = 40,
[1][0][RTW89_MKK][6] = 40,
[1][0][RTW89_IC][6] = 42,
- [1][0][RTW89_KCC][6] = 24,
+ [1][0][RTW89_KCC][6] = 32,
[1][0][RTW89_ACMA][6] = 40,
[1][0][RTW89_CN][6] = 26,
[1][0][RTW89_UK][6] = 40,
+ [1][0][RTW89_MEXICO][6] = 64,
+ [1][0][RTW89_UKRAINE][6] = 32,
+ [1][0][RTW89_CHILE][6] = 64,
+ [1][0][RTW89_QATAR][6] = 40,
[1][0][RTW89_FCC][8] = 62,
[1][0][RTW89_ETSI][8] = 40,
[1][0][RTW89_MKK][8] = 34,
[1][0][RTW89_IC][8] = 62,
- [1][0][RTW89_KCC][8] = 52,
+ [1][0][RTW89_KCC][8] = 50,
[1][0][RTW89_ACMA][8] = 40,
[1][0][RTW89_CN][8] = 26,
[1][0][RTW89_UK][8] = 40,
+ [1][0][RTW89_MEXICO][8] = 62,
+ [1][0][RTW89_UKRAINE][8] = 32,
+ [1][0][RTW89_CHILE][8] = 62,
+ [1][0][RTW89_QATAR][8] = 40,
[1][0][RTW89_FCC][10] = 62,
[1][0][RTW89_ETSI][10] = 40,
[1][0][RTW89_MKK][10] = 34,
[1][0][RTW89_IC][10] = 62,
- [1][0][RTW89_KCC][10] = 52,
+ [1][0][RTW89_KCC][10] = 50,
[1][0][RTW89_ACMA][10] = 40,
[1][0][RTW89_CN][10] = 26,
[1][0][RTW89_UK][10] = 40,
+ [1][0][RTW89_MEXICO][10] = 62,
+ [1][0][RTW89_UKRAINE][10] = 32,
+ [1][0][RTW89_CHILE][10] = 62,
+ [1][0][RTW89_QATAR][10] = 40,
[1][0][RTW89_FCC][12] = 62,
[1][0][RTW89_ETSI][12] = 40,
[1][0][RTW89_MKK][12] = 46,
[1][0][RTW89_IC][12] = 62,
- [1][0][RTW89_KCC][12] = 52,
+ [1][0][RTW89_KCC][12] = 50,
[1][0][RTW89_ACMA][12] = 40,
[1][0][RTW89_CN][12] = 26,
[1][0][RTW89_UK][12] = 40,
+ [1][0][RTW89_MEXICO][12] = 62,
+ [1][0][RTW89_UKRAINE][12] = 32,
+ [1][0][RTW89_CHILE][12] = 62,
+ [1][0][RTW89_QATAR][12] = 40,
[1][0][RTW89_FCC][14] = 62,
[1][0][RTW89_ETSI][14] = 40,
[1][0][RTW89_MKK][14] = 46,
[1][0][RTW89_IC][14] = 62,
- [1][0][RTW89_KCC][14] = 52,
+ [1][0][RTW89_KCC][14] = 50,
[1][0][RTW89_ACMA][14] = 40,
[1][0][RTW89_CN][14] = 26,
[1][0][RTW89_UK][14] = 40,
+ [1][0][RTW89_MEXICO][14] = 62,
+ [1][0][RTW89_UKRAINE][14] = 32,
+ [1][0][RTW89_CHILE][14] = 62,
+ [1][0][RTW89_QATAR][14] = 40,
[1][0][RTW89_FCC][15] = 62,
[1][0][RTW89_ETSI][15] = 40,
[1][0][RTW89_MKK][15] = 62,
@@ -35432,6 +47849,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][15] = 40,
[1][0][RTW89_CN][15] = 127,
[1][0][RTW89_UK][15] = 40,
+ [1][0][RTW89_MEXICO][15] = 62,
+ [1][0][RTW89_UKRAINE][15] = 32,
+ [1][0][RTW89_CHILE][15] = 62,
+ [1][0][RTW89_QATAR][15] = 40,
[1][0][RTW89_FCC][17] = 62,
[1][0][RTW89_ETSI][17] = 40,
[1][0][RTW89_MKK][17] = 68,
@@ -35440,6 +47861,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][17] = 40,
[1][0][RTW89_CN][17] = 127,
[1][0][RTW89_UK][17] = 40,
+ [1][0][RTW89_MEXICO][17] = 62,
+ [1][0][RTW89_UKRAINE][17] = 32,
+ [1][0][RTW89_CHILE][17] = 62,
+ [1][0][RTW89_QATAR][17] = 40,
[1][0][RTW89_FCC][19] = 64,
[1][0][RTW89_ETSI][19] = 40,
[1][0][RTW89_MKK][19] = 68,
@@ -35448,6 +47873,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][19] = 40,
[1][0][RTW89_CN][19] = 127,
[1][0][RTW89_UK][19] = 40,
+ [1][0][RTW89_MEXICO][19] = 64,
+ [1][0][RTW89_UKRAINE][19] = 32,
+ [1][0][RTW89_CHILE][19] = 64,
+ [1][0][RTW89_QATAR][19] = 40,
[1][0][RTW89_FCC][21] = 64,
[1][0][RTW89_ETSI][21] = 40,
[1][0][RTW89_MKK][21] = 68,
@@ -35456,6 +47885,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][21] = 40,
[1][0][RTW89_CN][21] = 127,
[1][0][RTW89_UK][21] = 40,
+ [1][0][RTW89_MEXICO][21] = 64,
+ [1][0][RTW89_UKRAINE][21] = 32,
+ [1][0][RTW89_CHILE][21] = 64,
+ [1][0][RTW89_QATAR][21] = 40,
[1][0][RTW89_FCC][23] = 64,
[1][0][RTW89_ETSI][23] = 40,
[1][0][RTW89_MKK][23] = 68,
@@ -35464,6 +47897,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][23] = 40,
[1][0][RTW89_CN][23] = 127,
[1][0][RTW89_UK][23] = 40,
+ [1][0][RTW89_MEXICO][23] = 64,
+ [1][0][RTW89_UKRAINE][23] = 32,
+ [1][0][RTW89_CHILE][23] = 64,
+ [1][0][RTW89_QATAR][23] = 40,
[1][0][RTW89_FCC][25] = 64,
[1][0][RTW89_ETSI][25] = 40,
[1][0][RTW89_MKK][25] = 68,
@@ -35472,6 +47909,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][25] = 127,
[1][0][RTW89_CN][25] = 127,
[1][0][RTW89_UK][25] = 40,
+ [1][0][RTW89_MEXICO][25] = 64,
+ [1][0][RTW89_UKRAINE][25] = 32,
+ [1][0][RTW89_CHILE][25] = 64,
+ [1][0][RTW89_QATAR][25] = 40,
[1][0][RTW89_FCC][27] = 64,
[1][0][RTW89_ETSI][27] = 42,
[1][0][RTW89_MKK][27] = 68,
@@ -35480,6 +47921,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][27] = 127,
[1][0][RTW89_CN][27] = 127,
[1][0][RTW89_UK][27] = 42,
+ [1][0][RTW89_MEXICO][27] = 64,
+ [1][0][RTW89_UKRAINE][27] = 32,
+ [1][0][RTW89_CHILE][27] = 64,
+ [1][0][RTW89_QATAR][27] = 42,
[1][0][RTW89_FCC][29] = 64,
[1][0][RTW89_ETSI][29] = 42,
[1][0][RTW89_MKK][29] = 68,
@@ -35488,38 +47933,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][29] = 127,
[1][0][RTW89_CN][29] = 127,
[1][0][RTW89_UK][29] = 42,
+ [1][0][RTW89_MEXICO][29] = 64,
+ [1][0][RTW89_UKRAINE][29] = 32,
+ [1][0][RTW89_CHILE][29] = 64,
+ [1][0][RTW89_QATAR][29] = 42,
[1][0][RTW89_FCC][31] = 64,
[1][0][RTW89_ETSI][31] = 42,
[1][0][RTW89_MKK][31] = 68,
[1][0][RTW89_IC][31] = 56,
- [1][0][RTW89_KCC][31] = 52,
+ [1][0][RTW89_KCC][31] = 50,
[1][0][RTW89_ACMA][31] = 42,
[1][0][RTW89_CN][31] = 127,
[1][0][RTW89_UK][31] = 42,
+ [1][0][RTW89_MEXICO][31] = 64,
+ [1][0][RTW89_UKRAINE][31] = 32,
+ [1][0][RTW89_CHILE][31] = 64,
+ [1][0][RTW89_QATAR][31] = 42,
[1][0][RTW89_FCC][33] = 56,
[1][0][RTW89_ETSI][33] = 42,
[1][0][RTW89_MKK][33] = 68,
[1][0][RTW89_IC][33] = 56,
- [1][0][RTW89_KCC][33] = 52,
+ [1][0][RTW89_KCC][33] = 50,
[1][0][RTW89_ACMA][33] = 42,
[1][0][RTW89_CN][33] = 127,
[1][0][RTW89_UK][33] = 42,
+ [1][0][RTW89_MEXICO][33] = 56,
+ [1][0][RTW89_UKRAINE][33] = 32,
+ [1][0][RTW89_CHILE][33] = 56,
+ [1][0][RTW89_QATAR][33] = 42,
[1][0][RTW89_FCC][35] = 56,
[1][0][RTW89_ETSI][35] = 42,
[1][0][RTW89_MKK][35] = 68,
[1][0][RTW89_IC][35] = 56,
- [1][0][RTW89_KCC][35] = 52,
+ [1][0][RTW89_KCC][35] = 50,
[1][0][RTW89_ACMA][35] = 42,
[1][0][RTW89_CN][35] = 127,
[1][0][RTW89_UK][35] = 42,
+ [1][0][RTW89_MEXICO][35] = 56,
+ [1][0][RTW89_UKRAINE][35] = 32,
+ [1][0][RTW89_CHILE][35] = 56,
+ [1][0][RTW89_QATAR][35] = 42,
[1][0][RTW89_FCC][37] = 66,
[1][0][RTW89_ETSI][37] = 127,
[1][0][RTW89_MKK][37] = 68,
[1][0][RTW89_IC][37] = 66,
- [1][0][RTW89_KCC][37] = 52,
+ [1][0][RTW89_KCC][37] = 50,
[1][0][RTW89_ACMA][37] = 66,
[1][0][RTW89_CN][37] = 127,
[1][0][RTW89_UK][37] = 42,
+ [1][0][RTW89_MEXICO][37] = 66,
+ [1][0][RTW89_UKRAINE][37] = 127,
+ [1][0][RTW89_CHILE][37] = 66,
+ [1][0][RTW89_QATAR][37] = 127,
[1][0][RTW89_FCC][38] = 76,
[1][0][RTW89_ETSI][38] = 28,
[1][0][RTW89_MKK][38] = 127,
@@ -35528,6 +47993,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][38] = 76,
[1][0][RTW89_CN][38] = 66,
[1][0][RTW89_UK][38] = 44,
+ [1][0][RTW89_MEXICO][38] = 76,
+ [1][0][RTW89_UKRAINE][38] = 26,
+ [1][0][RTW89_CHILE][38] = 76,
+ [1][0][RTW89_QATAR][38] = 26,
[1][0][RTW89_FCC][40] = 76,
[1][0][RTW89_ETSI][40] = 28,
[1][0][RTW89_MKK][40] = 127,
@@ -35536,6 +48005,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][40] = 76,
[1][0][RTW89_CN][40] = 66,
[1][0][RTW89_UK][40] = 44,
+ [1][0][RTW89_MEXICO][40] = 76,
+ [1][0][RTW89_UKRAINE][40] = 26,
+ [1][0][RTW89_CHILE][40] = 76,
+ [1][0][RTW89_QATAR][40] = 26,
[1][0][RTW89_FCC][42] = 68,
[1][0][RTW89_ETSI][42] = 28,
[1][0][RTW89_MKK][42] = 127,
@@ -35544,6 +48017,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][42] = 68,
[1][0][RTW89_CN][42] = 66,
[1][0][RTW89_UK][42] = 44,
+ [1][0][RTW89_MEXICO][42] = 68,
+ [1][0][RTW89_UKRAINE][42] = 26,
+ [1][0][RTW89_CHILE][42] = 68,
+ [1][0][RTW89_QATAR][42] = 26,
[1][0][RTW89_FCC][44] = 70,
[1][0][RTW89_ETSI][44] = 28,
[1][0][RTW89_MKK][44] = 127,
@@ -35552,6 +48029,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][44] = 70,
[1][0][RTW89_CN][44] = 66,
[1][0][RTW89_UK][44] = 42,
+ [1][0][RTW89_MEXICO][44] = 70,
+ [1][0][RTW89_UKRAINE][44] = 26,
+ [1][0][RTW89_CHILE][44] = 70,
+ [1][0][RTW89_QATAR][44] = 26,
[1][0][RTW89_FCC][46] = 70,
[1][0][RTW89_ETSI][46] = 28,
[1][0][RTW89_MKK][46] = 127,
@@ -35560,6 +48041,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][46] = 70,
[1][0][RTW89_CN][46] = 66,
[1][0][RTW89_UK][46] = 42,
+ [1][0][RTW89_MEXICO][46] = 70,
+ [1][0][RTW89_UKRAINE][46] = 26,
+ [1][0][RTW89_CHILE][46] = 70,
+ [1][0][RTW89_QATAR][46] = 26,
[1][0][RTW89_FCC][48] = 56,
[1][0][RTW89_ETSI][48] = 127,
[1][0][RTW89_MKK][48] = 127,
@@ -35568,6 +48053,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][48] = 127,
[1][0][RTW89_CN][48] = 127,
[1][0][RTW89_UK][48] = 127,
+ [1][0][RTW89_MEXICO][48] = 127,
+ [1][0][RTW89_UKRAINE][48] = 127,
+ [1][0][RTW89_CHILE][48] = 127,
+ [1][0][RTW89_QATAR][48] = 127,
[1][0][RTW89_FCC][50] = 58,
[1][0][RTW89_ETSI][50] = 127,
[1][0][RTW89_MKK][50] = 127,
@@ -35576,6 +48065,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][50] = 127,
[1][0][RTW89_CN][50] = 127,
[1][0][RTW89_UK][50] = 127,
+ [1][0][RTW89_MEXICO][50] = 127,
+ [1][0][RTW89_UKRAINE][50] = 127,
+ [1][0][RTW89_CHILE][50] = 127,
+ [1][0][RTW89_QATAR][50] = 127,
[1][0][RTW89_FCC][52] = 56,
[1][0][RTW89_ETSI][52] = 127,
[1][0][RTW89_MKK][52] = 127,
@@ -35584,54 +48077,82 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][0][RTW89_ACMA][52] = 127,
[1][0][RTW89_CN][52] = 127,
[1][0][RTW89_UK][52] = 127,
+ [1][0][RTW89_MEXICO][52] = 127,
+ [1][0][RTW89_UKRAINE][52] = 127,
+ [1][0][RTW89_CHILE][52] = 127,
+ [1][0][RTW89_QATAR][52] = 127,
[1][1][RTW89_FCC][0] = 44,
[1][1][RTW89_ETSI][0] = 30,
[1][1][RTW89_MKK][0] = 34,
[1][1][RTW89_IC][0] = 20,
- [1][1][RTW89_KCC][0] = 34,
+ [1][1][RTW89_KCC][0] = 40,
[1][1][RTW89_ACMA][0] = 30,
[1][1][RTW89_CN][0] = 14,
[1][1][RTW89_UK][0] = 30,
+ [1][1][RTW89_MEXICO][0] = 44,
+ [1][1][RTW89_UKRAINE][0] = 20,
+ [1][1][RTW89_CHILE][0] = 44,
+ [1][1][RTW89_QATAR][0] = 30,
[1][1][RTW89_FCC][2] = 44,
[1][1][RTW89_ETSI][2] = 30,
[1][1][RTW89_MKK][2] = 34,
[1][1][RTW89_IC][2] = 18,
- [1][1][RTW89_KCC][2] = 34,
+ [1][1][RTW89_KCC][2] = 40,
[1][1][RTW89_ACMA][2] = 30,
[1][1][RTW89_CN][2] = 14,
[1][1][RTW89_UK][2] = 30,
+ [1][1][RTW89_MEXICO][2] = 44,
+ [1][1][RTW89_UKRAINE][2] = 20,
+ [1][1][RTW89_CHILE][2] = 44,
+ [1][1][RTW89_QATAR][2] = 30,
[1][1][RTW89_FCC][4] = 46,
[1][1][RTW89_ETSI][4] = 30,
[1][1][RTW89_MKK][4] = 26,
[1][1][RTW89_IC][4] = 20,
- [1][1][RTW89_KCC][4] = 34,
+ [1][1][RTW89_KCC][4] = 40,
[1][1][RTW89_ACMA][4] = 30,
[1][1][RTW89_CN][4] = 14,
[1][1][RTW89_UK][4] = 30,
+ [1][1][RTW89_MEXICO][4] = 46,
+ [1][1][RTW89_UKRAINE][4] = 20,
+ [1][1][RTW89_CHILE][4] = 46,
+ [1][1][RTW89_QATAR][4] = 30,
[1][1][RTW89_FCC][6] = 46,
[1][1][RTW89_ETSI][6] = 30,
[1][1][RTW89_MKK][6] = 26,
[1][1][RTW89_IC][6] = 20,
- [1][1][RTW89_KCC][6] = 8,
+ [1][1][RTW89_KCC][6] = 18,
[1][1][RTW89_ACMA][6] = 30,
[1][1][RTW89_CN][6] = 14,
[1][1][RTW89_UK][6] = 30,
+ [1][1][RTW89_MEXICO][6] = 46,
+ [1][1][RTW89_UKRAINE][6] = 20,
+ [1][1][RTW89_CHILE][6] = 46,
+ [1][1][RTW89_QATAR][6] = 30,
[1][1][RTW89_FCC][8] = 44,
[1][1][RTW89_ETSI][8] = 30,
[1][1][RTW89_MKK][8] = 20,
[1][1][RTW89_IC][8] = 44,
- [1][1][RTW89_KCC][8] = 34,
+ [1][1][RTW89_KCC][8] = 38,
[1][1][RTW89_ACMA][8] = 30,
[1][1][RTW89_CN][8] = 14,
[1][1][RTW89_UK][8] = 30,
+ [1][1][RTW89_MEXICO][8] = 44,
+ [1][1][RTW89_UKRAINE][8] = 20,
+ [1][1][RTW89_CHILE][8] = 44,
+ [1][1][RTW89_QATAR][8] = 30,
[1][1][RTW89_FCC][10] = 44,
[1][1][RTW89_ETSI][10] = 30,
[1][1][RTW89_MKK][10] = 20,
[1][1][RTW89_IC][10] = 44,
- [1][1][RTW89_KCC][10] = 34,
+ [1][1][RTW89_KCC][10] = 38,
[1][1][RTW89_ACMA][10] = 30,
[1][1][RTW89_CN][10] = 14,
[1][1][RTW89_UK][10] = 30,
+ [1][1][RTW89_MEXICO][10] = 44,
+ [1][1][RTW89_UKRAINE][10] = 20,
+ [1][1][RTW89_CHILE][10] = 44,
+ [1][1][RTW89_QATAR][10] = 30,
[1][1][RTW89_FCC][12] = 44,
[1][1][RTW89_ETSI][12] = 30,
[1][1][RTW89_MKK][12] = 34,
@@ -35640,6 +48161,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][12] = 30,
[1][1][RTW89_CN][12] = 14,
[1][1][RTW89_UK][12] = 30,
+ [1][1][RTW89_MEXICO][12] = 44,
+ [1][1][RTW89_UKRAINE][12] = 20,
+ [1][1][RTW89_CHILE][12] = 44,
+ [1][1][RTW89_QATAR][12] = 30,
[1][1][RTW89_FCC][14] = 44,
[1][1][RTW89_ETSI][14] = 30,
[1][1][RTW89_MKK][14] = 34,
@@ -35648,142 +48173,214 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][14] = 30,
[1][1][RTW89_CN][14] = 14,
[1][1][RTW89_UK][14] = 30,
+ [1][1][RTW89_MEXICO][14] = 44,
+ [1][1][RTW89_UKRAINE][14] = 20,
+ [1][1][RTW89_CHILE][14] = 44,
+ [1][1][RTW89_QATAR][14] = 30,
[1][1][RTW89_FCC][15] = 44,
[1][1][RTW89_ETSI][15] = 28,
[1][1][RTW89_MKK][15] = 56,
[1][1][RTW89_IC][15] = 44,
- [1][1][RTW89_KCC][15] = 36,
+ [1][1][RTW89_KCC][15] = 38,
[1][1][RTW89_ACMA][15] = 28,
[1][1][RTW89_CN][15] = 127,
[1][1][RTW89_UK][15] = 28,
+ [1][1][RTW89_MEXICO][15] = 44,
+ [1][1][RTW89_UKRAINE][15] = 20,
+ [1][1][RTW89_CHILE][15] = 44,
+ [1][1][RTW89_QATAR][15] = 28,
[1][1][RTW89_FCC][17] = 44,
[1][1][RTW89_ETSI][17] = 28,
[1][1][RTW89_MKK][17] = 58,
[1][1][RTW89_IC][17] = 44,
- [1][1][RTW89_KCC][17] = 36,
+ [1][1][RTW89_KCC][17] = 38,
[1][1][RTW89_ACMA][17] = 28,
[1][1][RTW89_CN][17] = 127,
[1][1][RTW89_UK][17] = 28,
+ [1][1][RTW89_MEXICO][17] = 44,
+ [1][1][RTW89_UKRAINE][17] = 20,
+ [1][1][RTW89_CHILE][17] = 44,
+ [1][1][RTW89_QATAR][17] = 28,
[1][1][RTW89_FCC][19] = 44,
[1][1][RTW89_ETSI][19] = 28,
[1][1][RTW89_MKK][19] = 58,
[1][1][RTW89_IC][19] = 44,
- [1][1][RTW89_KCC][19] = 36,
+ [1][1][RTW89_KCC][19] = 38,
[1][1][RTW89_ACMA][19] = 28,
[1][1][RTW89_CN][19] = 127,
[1][1][RTW89_UK][19] = 28,
+ [1][1][RTW89_MEXICO][19] = 44,
+ [1][1][RTW89_UKRAINE][19] = 20,
+ [1][1][RTW89_CHILE][19] = 44,
+ [1][1][RTW89_QATAR][19] = 28,
[1][1][RTW89_FCC][21] = 44,
[1][1][RTW89_ETSI][21] = 28,
[1][1][RTW89_MKK][21] = 58,
[1][1][RTW89_IC][21] = 44,
- [1][1][RTW89_KCC][21] = 36,
+ [1][1][RTW89_KCC][21] = 38,
[1][1][RTW89_ACMA][21] = 28,
[1][1][RTW89_CN][21] = 127,
[1][1][RTW89_UK][21] = 28,
+ [1][1][RTW89_MEXICO][21] = 44,
+ [1][1][RTW89_UKRAINE][21] = 20,
+ [1][1][RTW89_CHILE][21] = 44,
+ [1][1][RTW89_QATAR][21] = 28,
[1][1][RTW89_FCC][23] = 44,
[1][1][RTW89_ETSI][23] = 28,
[1][1][RTW89_MKK][23] = 58,
[1][1][RTW89_IC][23] = 44,
- [1][1][RTW89_KCC][23] = 36,
+ [1][1][RTW89_KCC][23] = 38,
[1][1][RTW89_ACMA][23] = 28,
[1][1][RTW89_CN][23] = 127,
[1][1][RTW89_UK][23] = 28,
+ [1][1][RTW89_MEXICO][23] = 44,
+ [1][1][RTW89_UKRAINE][23] = 20,
+ [1][1][RTW89_CHILE][23] = 44,
+ [1][1][RTW89_QATAR][23] = 28,
[1][1][RTW89_FCC][25] = 44,
[1][1][RTW89_ETSI][25] = 28,
[1][1][RTW89_MKK][25] = 58,
[1][1][RTW89_IC][25] = 127,
- [1][1][RTW89_KCC][25] = 36,
+ [1][1][RTW89_KCC][25] = 38,
[1][1][RTW89_ACMA][25] = 127,
[1][1][RTW89_CN][25] = 127,
[1][1][RTW89_UK][25] = 28,
+ [1][1][RTW89_MEXICO][25] = 44,
+ [1][1][RTW89_UKRAINE][25] = 20,
+ [1][1][RTW89_CHILE][25] = 44,
+ [1][1][RTW89_QATAR][25] = 28,
[1][1][RTW89_FCC][27] = 44,
[1][1][RTW89_ETSI][27] = 30,
[1][1][RTW89_MKK][27] = 58,
[1][1][RTW89_IC][27] = 127,
- [1][1][RTW89_KCC][27] = 36,
+ [1][1][RTW89_KCC][27] = 38,
[1][1][RTW89_ACMA][27] = 127,
[1][1][RTW89_CN][27] = 127,
[1][1][RTW89_UK][27] = 30,
+ [1][1][RTW89_MEXICO][27] = 44,
+ [1][1][RTW89_UKRAINE][27] = 20,
+ [1][1][RTW89_CHILE][27] = 44,
+ [1][1][RTW89_QATAR][27] = 30,
[1][1][RTW89_FCC][29] = 44,
[1][1][RTW89_ETSI][29] = 30,
[1][1][RTW89_MKK][29] = 58,
[1][1][RTW89_IC][29] = 127,
- [1][1][RTW89_KCC][29] = 36,
+ [1][1][RTW89_KCC][29] = 38,
[1][1][RTW89_ACMA][29] = 127,
[1][1][RTW89_CN][29] = 127,
[1][1][RTW89_UK][29] = 30,
+ [1][1][RTW89_MEXICO][29] = 44,
+ [1][1][RTW89_UKRAINE][29] = 20,
+ [1][1][RTW89_CHILE][29] = 44,
+ [1][1][RTW89_QATAR][29] = 30,
[1][1][RTW89_FCC][31] = 44,
[1][1][RTW89_ETSI][31] = 30,
[1][1][RTW89_MKK][31] = 58,
[1][1][RTW89_IC][31] = 38,
- [1][1][RTW89_KCC][31] = 36,
+ [1][1][RTW89_KCC][31] = 40,
[1][1][RTW89_ACMA][31] = 30,
[1][1][RTW89_CN][31] = 127,
[1][1][RTW89_UK][31] = 30,
+ [1][1][RTW89_MEXICO][31] = 44,
+ [1][1][RTW89_UKRAINE][31] = 20,
+ [1][1][RTW89_CHILE][31] = 44,
+ [1][1][RTW89_QATAR][31] = 30,
[1][1][RTW89_FCC][33] = 38,
[1][1][RTW89_ETSI][33] = 30,
[1][1][RTW89_MKK][33] = 58,
[1][1][RTW89_IC][33] = 38,
- [1][1][RTW89_KCC][33] = 36,
+ [1][1][RTW89_KCC][33] = 40,
[1][1][RTW89_ACMA][33] = 30,
[1][1][RTW89_CN][33] = 127,
[1][1][RTW89_UK][33] = 30,
+ [1][1][RTW89_MEXICO][33] = 38,
+ [1][1][RTW89_UKRAINE][33] = 20,
+ [1][1][RTW89_CHILE][33] = 38,
+ [1][1][RTW89_QATAR][33] = 30,
[1][1][RTW89_FCC][35] = 38,
[1][1][RTW89_ETSI][35] = 30,
[1][1][RTW89_MKK][35] = 58,
[1][1][RTW89_IC][35] = 38,
- [1][1][RTW89_KCC][35] = 36,
+ [1][1][RTW89_KCC][35] = 40,
[1][1][RTW89_ACMA][35] = 30,
[1][1][RTW89_CN][35] = 127,
[1][1][RTW89_UK][35] = 30,
+ [1][1][RTW89_MEXICO][35] = 38,
+ [1][1][RTW89_UKRAINE][35] = 20,
+ [1][1][RTW89_CHILE][35] = 38,
+ [1][1][RTW89_QATAR][35] = 30,
[1][1][RTW89_FCC][37] = 46,
[1][1][RTW89_ETSI][37] = 127,
[1][1][RTW89_MKK][37] = 58,
[1][1][RTW89_IC][37] = 46,
- [1][1][RTW89_KCC][37] = 36,
+ [1][1][RTW89_KCC][37] = 40,
[1][1][RTW89_ACMA][37] = 46,
[1][1][RTW89_CN][37] = 127,
[1][1][RTW89_UK][37] = 32,
+ [1][1][RTW89_MEXICO][37] = 46,
+ [1][1][RTW89_UKRAINE][37] = 127,
+ [1][1][RTW89_CHILE][37] = 46,
+ [1][1][RTW89_QATAR][37] = 127,
[1][1][RTW89_FCC][38] = 74,
[1][1][RTW89_ETSI][38] = 16,
[1][1][RTW89_MKK][38] = 127,
[1][1][RTW89_IC][38] = 74,
- [1][1][RTW89_KCC][38] = 36,
+ [1][1][RTW89_KCC][38] = 38,
[1][1][RTW89_ACMA][38] = 74,
[1][1][RTW89_CN][38] = 54,
[1][1][RTW89_UK][38] = 30,
+ [1][1][RTW89_MEXICO][38] = 74,
+ [1][1][RTW89_UKRAINE][38] = 14,
+ [1][1][RTW89_CHILE][38] = 72,
+ [1][1][RTW89_QATAR][38] = 14,
[1][1][RTW89_FCC][40] = 74,
[1][1][RTW89_ETSI][40] = 16,
[1][1][RTW89_MKK][40] = 127,
[1][1][RTW89_IC][40] = 74,
- [1][1][RTW89_KCC][40] = 36,
+ [1][1][RTW89_KCC][40] = 38,
[1][1][RTW89_ACMA][40] = 74,
[1][1][RTW89_CN][40] = 54,
[1][1][RTW89_UK][40] = 30,
+ [1][1][RTW89_MEXICO][40] = 74,
+ [1][1][RTW89_UKRAINE][40] = 14,
+ [1][1][RTW89_CHILE][40] = 72,
+ [1][1][RTW89_QATAR][40] = 14,
[1][1][RTW89_FCC][42] = 74,
[1][1][RTW89_ETSI][42] = 16,
[1][1][RTW89_MKK][42] = 127,
[1][1][RTW89_IC][42] = 74,
- [1][1][RTW89_KCC][42] = 36,
+ [1][1][RTW89_KCC][42] = 38,
[1][1][RTW89_ACMA][42] = 74,
[1][1][RTW89_CN][42] = 54,
[1][1][RTW89_UK][42] = 30,
+ [1][1][RTW89_MEXICO][42] = 74,
+ [1][1][RTW89_UKRAINE][42] = 14,
+ [1][1][RTW89_CHILE][42] = 72,
+ [1][1][RTW89_QATAR][42] = 14,
[1][1][RTW89_FCC][44] = 74,
[1][1][RTW89_ETSI][44] = 16,
[1][1][RTW89_MKK][44] = 127,
[1][1][RTW89_IC][44] = 74,
- [1][1][RTW89_KCC][44] = 36,
+ [1][1][RTW89_KCC][44] = 38,
[1][1][RTW89_ACMA][44] = 74,
[1][1][RTW89_CN][44] = 54,
[1][1][RTW89_UK][44] = 30,
+ [1][1][RTW89_MEXICO][44] = 74,
+ [1][1][RTW89_UKRAINE][44] = 14,
+ [1][1][RTW89_CHILE][44] = 72,
+ [1][1][RTW89_QATAR][44] = 14,
[1][1][RTW89_FCC][46] = 74,
[1][1][RTW89_ETSI][46] = 16,
[1][1][RTW89_MKK][46] = 127,
[1][1][RTW89_IC][46] = 74,
- [1][1][RTW89_KCC][46] = 36,
+ [1][1][RTW89_KCC][46] = 38,
[1][1][RTW89_ACMA][46] = 74,
[1][1][RTW89_CN][46] = 54,
[1][1][RTW89_UK][46] = 30,
+ [1][1][RTW89_MEXICO][46] = 74,
+ [1][1][RTW89_UKRAINE][46] = 14,
+ [1][1][RTW89_CHILE][46] = 72,
+ [1][1][RTW89_QATAR][46] = 14,
[1][1][RTW89_FCC][48] = 34,
[1][1][RTW89_ETSI][48] = 127,
[1][1][RTW89_MKK][48] = 127,
@@ -35792,6 +48389,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][48] = 127,
[1][1][RTW89_CN][48] = 127,
[1][1][RTW89_UK][48] = 127,
+ [1][1][RTW89_MEXICO][48] = 127,
+ [1][1][RTW89_UKRAINE][48] = 127,
+ [1][1][RTW89_CHILE][48] = 127,
+ [1][1][RTW89_QATAR][48] = 127,
[1][1][RTW89_FCC][50] = 34,
[1][1][RTW89_ETSI][50] = 127,
[1][1][RTW89_MKK][50] = 127,
@@ -35800,6 +48401,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][50] = 127,
[1][1][RTW89_CN][50] = 127,
[1][1][RTW89_UK][50] = 127,
+ [1][1][RTW89_MEXICO][50] = 127,
+ [1][1][RTW89_UKRAINE][50] = 127,
+ [1][1][RTW89_CHILE][50] = 127,
+ [1][1][RTW89_QATAR][50] = 127,
[1][1][RTW89_FCC][52] = 30,
[1][1][RTW89_ETSI][52] = 127,
[1][1][RTW89_MKK][52] = 127,
@@ -35808,206 +48413,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[1][1][RTW89_ACMA][52] = 127,
[1][1][RTW89_CN][52] = 127,
[1][1][RTW89_UK][52] = 127,
+ [1][1][RTW89_MEXICO][52] = 127,
+ [1][1][RTW89_UKRAINE][52] = 127,
+ [1][1][RTW89_CHILE][52] = 127,
+ [1][1][RTW89_QATAR][52] = 127,
[2][0][RTW89_FCC][0] = 68,
[2][0][RTW89_ETSI][0] = 52,
[2][0][RTW89_MKK][0] = 60,
[2][0][RTW89_IC][0] = 52,
- [2][0][RTW89_KCC][0] = 64,
+ [2][0][RTW89_KCC][0] = 60,
[2][0][RTW89_ACMA][0] = 52,
[2][0][RTW89_CN][0] = 40,
[2][0][RTW89_UK][0] = 52,
+ [2][0][RTW89_MEXICO][0] = 62,
+ [2][0][RTW89_UKRAINE][0] = 46,
+ [2][0][RTW89_CHILE][0] = 68,
+ [2][0][RTW89_QATAR][0] = 52,
[2][0][RTW89_FCC][2] = 64,
[2][0][RTW89_ETSI][2] = 52,
[2][0][RTW89_MKK][2] = 60,
[2][0][RTW89_IC][2] = 50,
- [2][0][RTW89_KCC][2] = 64,
+ [2][0][RTW89_KCC][2] = 60,
[2][0][RTW89_ACMA][2] = 52,
[2][0][RTW89_CN][2] = 40,
[2][0][RTW89_UK][2] = 52,
+ [2][0][RTW89_MEXICO][2] = 62,
+ [2][0][RTW89_UKRAINE][2] = 46,
+ [2][0][RTW89_CHILE][2] = 64,
+ [2][0][RTW89_QATAR][2] = 52,
[2][0][RTW89_FCC][4] = 68,
[2][0][RTW89_ETSI][4] = 52,
[2][0][RTW89_MKK][4] = 50,
[2][0][RTW89_IC][4] = 50,
- [2][0][RTW89_KCC][4] = 64,
+ [2][0][RTW89_KCC][4] = 60,
[2][0][RTW89_ACMA][4] = 52,
[2][0][RTW89_CN][4] = 40,
[2][0][RTW89_UK][4] = 52,
+ [2][0][RTW89_MEXICO][4] = 62,
+ [2][0][RTW89_UKRAINE][4] = 46,
+ [2][0][RTW89_CHILE][4] = 68,
+ [2][0][RTW89_QATAR][4] = 52,
[2][0][RTW89_FCC][6] = 68,
[2][0][RTW89_ETSI][6] = 52,
[2][0][RTW89_MKK][6] = 50,
[2][0][RTW89_IC][6] = 50,
- [2][0][RTW89_KCC][6] = 36,
+ [2][0][RTW89_KCC][6] = 38,
[2][0][RTW89_ACMA][6] = 52,
[2][0][RTW89_CN][6] = 40,
[2][0][RTW89_UK][6] = 52,
+ [2][0][RTW89_MEXICO][6] = 62,
+ [2][0][RTW89_UKRAINE][6] = 46,
+ [2][0][RTW89_CHILE][6] = 68,
+ [2][0][RTW89_QATAR][6] = 52,
[2][0][RTW89_FCC][8] = 68,
[2][0][RTW89_ETSI][8] = 52,
[2][0][RTW89_MKK][8] = 44,
[2][0][RTW89_IC][8] = 64,
- [2][0][RTW89_KCC][8] = 62,
+ [2][0][RTW89_KCC][8] = 56,
[2][0][RTW89_ACMA][8] = 52,
[2][0][RTW89_CN][8] = 40,
[2][0][RTW89_UK][8] = 52,
+ [2][0][RTW89_MEXICO][8] = 68,
+ [2][0][RTW89_UKRAINE][8] = 46,
+ [2][0][RTW89_CHILE][8] = 68,
+ [2][0][RTW89_QATAR][8] = 52,
[2][0][RTW89_FCC][10] = 68,
[2][0][RTW89_ETSI][10] = 52,
[2][0][RTW89_MKK][10] = 44,
[2][0][RTW89_IC][10] = 64,
- [2][0][RTW89_KCC][10] = 62,
+ [2][0][RTW89_KCC][10] = 56,
[2][0][RTW89_ACMA][10] = 52,
[2][0][RTW89_CN][10] = 40,
[2][0][RTW89_UK][10] = 52,
+ [2][0][RTW89_MEXICO][10] = 68,
+ [2][0][RTW89_UKRAINE][10] = 46,
+ [2][0][RTW89_CHILE][10] = 68,
+ [2][0][RTW89_QATAR][10] = 52,
[2][0][RTW89_FCC][12] = 68,
[2][0][RTW89_ETSI][12] = 52,
[2][0][RTW89_MKK][12] = 58,
[2][0][RTW89_IC][12] = 64,
- [2][0][RTW89_KCC][12] = 62,
+ [2][0][RTW89_KCC][12] = 58,
[2][0][RTW89_ACMA][12] = 52,
[2][0][RTW89_CN][12] = 40,
[2][0][RTW89_UK][12] = 52,
+ [2][0][RTW89_MEXICO][12] = 68,
+ [2][0][RTW89_UKRAINE][12] = 46,
+ [2][0][RTW89_CHILE][12] = 68,
+ [2][0][RTW89_QATAR][12] = 52,
[2][0][RTW89_FCC][14] = 68,
[2][0][RTW89_ETSI][14] = 52,
[2][0][RTW89_MKK][14] = 58,
[2][0][RTW89_IC][14] = 64,
- [2][0][RTW89_KCC][14] = 62,
+ [2][0][RTW89_KCC][14] = 58,
[2][0][RTW89_ACMA][14] = 52,
[2][0][RTW89_CN][14] = 40,
[2][0][RTW89_UK][14] = 52,
+ [2][0][RTW89_MEXICO][14] = 68,
+ [2][0][RTW89_UKRAINE][14] = 46,
+ [2][0][RTW89_CHILE][14] = 68,
+ [2][0][RTW89_QATAR][14] = 52,
[2][0][RTW89_FCC][15] = 68,
[2][0][RTW89_ETSI][15] = 52,
[2][0][RTW89_MKK][15] = 68,
[2][0][RTW89_IC][15] = 68,
- [2][0][RTW89_KCC][15] = 62,
+ [2][0][RTW89_KCC][15] = 58,
[2][0][RTW89_ACMA][15] = 52,
[2][0][RTW89_CN][15] = 127,
[2][0][RTW89_UK][15] = 52,
+ [2][0][RTW89_MEXICO][15] = 68,
+ [2][0][RTW89_UKRAINE][15] = 46,
+ [2][0][RTW89_CHILE][15] = 68,
+ [2][0][RTW89_QATAR][15] = 52,
[2][0][RTW89_FCC][17] = 68,
[2][0][RTW89_ETSI][17] = 52,
[2][0][RTW89_MKK][17] = 74,
[2][0][RTW89_IC][17] = 68,
- [2][0][RTW89_KCC][17] = 62,
+ [2][0][RTW89_KCC][17] = 58,
[2][0][RTW89_ACMA][17] = 52,
[2][0][RTW89_CN][17] = 127,
[2][0][RTW89_UK][17] = 52,
+ [2][0][RTW89_MEXICO][17] = 68,
+ [2][0][RTW89_UKRAINE][17] = 46,
+ [2][0][RTW89_CHILE][17] = 68,
+ [2][0][RTW89_QATAR][17] = 52,
[2][0][RTW89_FCC][19] = 70,
[2][0][RTW89_ETSI][19] = 52,
[2][0][RTW89_MKK][19] = 74,
[2][0][RTW89_IC][19] = 70,
- [2][0][RTW89_KCC][19] = 62,
+ [2][0][RTW89_KCC][19] = 58,
[2][0][RTW89_ACMA][19] = 52,
[2][0][RTW89_CN][19] = 127,
[2][0][RTW89_UK][19] = 52,
+ [2][0][RTW89_MEXICO][19] = 70,
+ [2][0][RTW89_UKRAINE][19] = 46,
+ [2][0][RTW89_CHILE][19] = 70,
+ [2][0][RTW89_QATAR][19] = 52,
[2][0][RTW89_FCC][21] = 70,
[2][0][RTW89_ETSI][21] = 52,
[2][0][RTW89_MKK][21] = 74,
[2][0][RTW89_IC][21] = 70,
- [2][0][RTW89_KCC][21] = 62,
+ [2][0][RTW89_KCC][21] = 58,
[2][0][RTW89_ACMA][21] = 52,
[2][0][RTW89_CN][21] = 127,
[2][0][RTW89_UK][21] = 52,
+ [2][0][RTW89_MEXICO][21] = 70,
+ [2][0][RTW89_UKRAINE][21] = 46,
+ [2][0][RTW89_CHILE][21] = 70,
+ [2][0][RTW89_QATAR][21] = 52,
[2][0][RTW89_FCC][23] = 70,
[2][0][RTW89_ETSI][23] = 52,
[2][0][RTW89_MKK][23] = 74,
[2][0][RTW89_IC][23] = 70,
- [2][0][RTW89_KCC][23] = 62,
+ [2][0][RTW89_KCC][23] = 58,
[2][0][RTW89_ACMA][23] = 52,
[2][0][RTW89_CN][23] = 127,
[2][0][RTW89_UK][23] = 52,
+ [2][0][RTW89_MEXICO][23] = 70,
+ [2][0][RTW89_UKRAINE][23] = 46,
+ [2][0][RTW89_CHILE][23] = 70,
+ [2][0][RTW89_QATAR][23] = 52,
[2][0][RTW89_FCC][25] = 70,
[2][0][RTW89_ETSI][25] = 52,
[2][0][RTW89_MKK][25] = 74,
[2][0][RTW89_IC][25] = 127,
- [2][0][RTW89_KCC][25] = 62,
+ [2][0][RTW89_KCC][25] = 58,
[2][0][RTW89_ACMA][25] = 127,
[2][0][RTW89_CN][25] = 127,
[2][0][RTW89_UK][25] = 52,
+ [2][0][RTW89_MEXICO][25] = 70,
+ [2][0][RTW89_UKRAINE][25] = 46,
+ [2][0][RTW89_CHILE][25] = 70,
+ [2][0][RTW89_QATAR][25] = 52,
[2][0][RTW89_FCC][27] = 70,
[2][0][RTW89_ETSI][27] = 52,
[2][0][RTW89_MKK][27] = 74,
[2][0][RTW89_IC][27] = 127,
- [2][0][RTW89_KCC][27] = 62,
+ [2][0][RTW89_KCC][27] = 58,
[2][0][RTW89_ACMA][27] = 127,
[2][0][RTW89_CN][27] = 127,
[2][0][RTW89_UK][27] = 52,
+ [2][0][RTW89_MEXICO][27] = 70,
+ [2][0][RTW89_UKRAINE][27] = 46,
+ [2][0][RTW89_CHILE][27] = 70,
+ [2][0][RTW89_QATAR][27] = 52,
[2][0][RTW89_FCC][29] = 70,
[2][0][RTW89_ETSI][29] = 52,
[2][0][RTW89_MKK][29] = 74,
[2][0][RTW89_IC][29] = 127,
- [2][0][RTW89_KCC][29] = 62,
+ [2][0][RTW89_KCC][29] = 58,
[2][0][RTW89_ACMA][29] = 127,
[2][0][RTW89_CN][29] = 127,
[2][0][RTW89_UK][29] = 52,
+ [2][0][RTW89_MEXICO][29] = 70,
+ [2][0][RTW89_UKRAINE][29] = 46,
+ [2][0][RTW89_CHILE][29] = 70,
+ [2][0][RTW89_QATAR][29] = 52,
[2][0][RTW89_FCC][31] = 70,
[2][0][RTW89_ETSI][31] = 52,
[2][0][RTW89_MKK][31] = 74,
[2][0][RTW89_IC][31] = 62,
- [2][0][RTW89_KCC][31] = 62,
+ [2][0][RTW89_KCC][31] = 56,
[2][0][RTW89_ACMA][31] = 52,
[2][0][RTW89_CN][31] = 127,
[2][0][RTW89_UK][31] = 52,
+ [2][0][RTW89_MEXICO][31] = 70,
+ [2][0][RTW89_UKRAINE][31] = 46,
+ [2][0][RTW89_CHILE][31] = 70,
+ [2][0][RTW89_QATAR][31] = 52,
[2][0][RTW89_FCC][33] = 62,
[2][0][RTW89_ETSI][33] = 52,
[2][0][RTW89_MKK][33] = 74,
[2][0][RTW89_IC][33] = 62,
- [2][0][RTW89_KCC][33] = 62,
+ [2][0][RTW89_KCC][33] = 56,
[2][0][RTW89_ACMA][33] = 52,
[2][0][RTW89_CN][33] = 127,
[2][0][RTW89_UK][33] = 52,
+ [2][0][RTW89_MEXICO][33] = 62,
+ [2][0][RTW89_UKRAINE][33] = 46,
+ [2][0][RTW89_CHILE][33] = 62,
+ [2][0][RTW89_QATAR][33] = 52,
[2][0][RTW89_FCC][35] = 62,
[2][0][RTW89_ETSI][35] = 52,
[2][0][RTW89_MKK][35] = 74,
[2][0][RTW89_IC][35] = 62,
- [2][0][RTW89_KCC][35] = 62,
+ [2][0][RTW89_KCC][35] = 56,
[2][0][RTW89_ACMA][35] = 52,
[2][0][RTW89_CN][35] = 127,
[2][0][RTW89_UK][35] = 52,
+ [2][0][RTW89_MEXICO][35] = 62,
+ [2][0][RTW89_UKRAINE][35] = 46,
+ [2][0][RTW89_CHILE][35] = 62,
+ [2][0][RTW89_QATAR][35] = 52,
[2][0][RTW89_FCC][37] = 70,
[2][0][RTW89_ETSI][37] = 127,
[2][0][RTW89_MKK][37] = 74,
[2][0][RTW89_IC][37] = 70,
- [2][0][RTW89_KCC][37] = 62,
+ [2][0][RTW89_KCC][37] = 56,
[2][0][RTW89_ACMA][37] = 70,
[2][0][RTW89_CN][37] = 127,
[2][0][RTW89_UK][37] = 52,
+ [2][0][RTW89_MEXICO][37] = 70,
+ [2][0][RTW89_UKRAINE][37] = 127,
+ [2][0][RTW89_CHILE][37] = 70,
+ [2][0][RTW89_QATAR][37] = 127,
[2][0][RTW89_FCC][38] = 82,
[2][0][RTW89_ETSI][38] = 28,
[2][0][RTW89_MKK][38] = 127,
[2][0][RTW89_IC][38] = 82,
- [2][0][RTW89_KCC][38] = 64,
+ [2][0][RTW89_KCC][38] = 60,
[2][0][RTW89_ACMA][38] = 82,
[2][0][RTW89_CN][38] = 68,
[2][0][RTW89_UK][38] = 54,
+ [2][0][RTW89_MEXICO][38] = 82,
+ [2][0][RTW89_UKRAINE][38] = 26,
+ [2][0][RTW89_CHILE][38] = 82,
+ [2][0][RTW89_QATAR][38] = 26,
[2][0][RTW89_FCC][40] = 82,
[2][0][RTW89_ETSI][40] = 28,
[2][0][RTW89_MKK][40] = 127,
[2][0][RTW89_IC][40] = 82,
- [2][0][RTW89_KCC][40] = 64,
+ [2][0][RTW89_KCC][40] = 60,
[2][0][RTW89_ACMA][40] = 82,
[2][0][RTW89_CN][40] = 68,
[2][0][RTW89_UK][40] = 54,
+ [2][0][RTW89_MEXICO][40] = 82,
+ [2][0][RTW89_UKRAINE][40] = 26,
+ [2][0][RTW89_CHILE][40] = 82,
+ [2][0][RTW89_QATAR][40] = 26,
[2][0][RTW89_FCC][42] = 76,
[2][0][RTW89_ETSI][42] = 28,
[2][0][RTW89_MKK][42] = 127,
[2][0][RTW89_IC][42] = 76,
- [2][0][RTW89_KCC][42] = 64,
+ [2][0][RTW89_KCC][42] = 60,
[2][0][RTW89_ACMA][42] = 76,
[2][0][RTW89_CN][42] = 68,
[2][0][RTW89_UK][42] = 54,
+ [2][0][RTW89_MEXICO][42] = 76,
+ [2][0][RTW89_UKRAINE][42] = 26,
+ [2][0][RTW89_CHILE][42] = 76,
+ [2][0][RTW89_QATAR][42] = 26,
[2][0][RTW89_FCC][44] = 80,
[2][0][RTW89_ETSI][44] = 28,
[2][0][RTW89_MKK][44] = 127,
[2][0][RTW89_IC][44] = 80,
- [2][0][RTW89_KCC][44] = 64,
+ [2][0][RTW89_KCC][44] = 60,
[2][0][RTW89_ACMA][44] = 80,
[2][0][RTW89_CN][44] = 68,
[2][0][RTW89_UK][44] = 54,
+ [2][0][RTW89_MEXICO][44] = 80,
+ [2][0][RTW89_UKRAINE][44] = 26,
+ [2][0][RTW89_CHILE][44] = 80,
+ [2][0][RTW89_QATAR][44] = 26,
[2][0][RTW89_FCC][46] = 80,
[2][0][RTW89_ETSI][46] = 28,
[2][0][RTW89_MKK][46] = 127,
[2][0][RTW89_IC][46] = 80,
- [2][0][RTW89_KCC][46] = 64,
+ [2][0][RTW89_KCC][46] = 60,
[2][0][RTW89_ACMA][46] = 80,
[2][0][RTW89_CN][46] = 68,
[2][0][RTW89_UK][46] = 54,
+ [2][0][RTW89_MEXICO][46] = 80,
+ [2][0][RTW89_UKRAINE][46] = 26,
+ [2][0][RTW89_CHILE][46] = 80,
+ [2][0][RTW89_QATAR][46] = 26,
[2][0][RTW89_FCC][48] = 64,
[2][0][RTW89_ETSI][48] = 127,
[2][0][RTW89_MKK][48] = 127,
@@ -36016,6 +48725,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][48] = 127,
[2][0][RTW89_CN][48] = 127,
[2][0][RTW89_UK][48] = 127,
+ [2][0][RTW89_MEXICO][48] = 127,
+ [2][0][RTW89_UKRAINE][48] = 127,
+ [2][0][RTW89_CHILE][48] = 127,
+ [2][0][RTW89_QATAR][48] = 127,
[2][0][RTW89_FCC][50] = 64,
[2][0][RTW89_ETSI][50] = 127,
[2][0][RTW89_MKK][50] = 127,
@@ -36024,6 +48737,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][50] = 127,
[2][0][RTW89_CN][50] = 127,
[2][0][RTW89_UK][50] = 127,
+ [2][0][RTW89_MEXICO][50] = 127,
+ [2][0][RTW89_UKRAINE][50] = 127,
+ [2][0][RTW89_CHILE][50] = 127,
+ [2][0][RTW89_QATAR][50] = 127,
[2][0][RTW89_FCC][52] = 64,
[2][0][RTW89_ETSI][52] = 127,
[2][0][RTW89_MKK][52] = 127,
@@ -36032,206 +48749,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][0][RTW89_ACMA][52] = 127,
[2][0][RTW89_CN][52] = 127,
[2][0][RTW89_UK][52] = 127,
+ [2][0][RTW89_MEXICO][52] = 127,
+ [2][0][RTW89_UKRAINE][52] = 127,
+ [2][0][RTW89_CHILE][52] = 127,
+ [2][0][RTW89_QATAR][52] = 127,
[2][1][RTW89_FCC][0] = 50,
[2][1][RTW89_ETSI][0] = 40,
[2][1][RTW89_MKK][0] = 44,
[2][1][RTW89_IC][0] = 26,
- [2][1][RTW89_KCC][0] = 44,
+ [2][1][RTW89_KCC][0] = 52,
[2][1][RTW89_ACMA][0] = 40,
[2][1][RTW89_CN][0] = 28,
[2][1][RTW89_UK][0] = 40,
+ [2][1][RTW89_MEXICO][0] = 50,
+ [2][1][RTW89_UKRAINE][0] = 34,
+ [2][1][RTW89_CHILE][0] = 50,
+ [2][1][RTW89_QATAR][0] = 40,
[2][1][RTW89_FCC][2] = 50,
[2][1][RTW89_ETSI][2] = 40,
[2][1][RTW89_MKK][2] = 44,
[2][1][RTW89_IC][2] = 26,
- [2][1][RTW89_KCC][2] = 44,
+ [2][1][RTW89_KCC][2] = 52,
[2][1][RTW89_ACMA][2] = 40,
[2][1][RTW89_CN][2] = 28,
[2][1][RTW89_UK][2] = 40,
+ [2][1][RTW89_MEXICO][2] = 50,
+ [2][1][RTW89_UKRAINE][2] = 34,
+ [2][1][RTW89_CHILE][2] = 50,
+ [2][1][RTW89_QATAR][2] = 40,
[2][1][RTW89_FCC][4] = 50,
[2][1][RTW89_ETSI][4] = 40,
[2][1][RTW89_MKK][4] = 36,
[2][1][RTW89_IC][4] = 26,
- [2][1][RTW89_KCC][4] = 44,
+ [2][1][RTW89_KCC][4] = 52,
[2][1][RTW89_ACMA][4] = 40,
[2][1][RTW89_CN][4] = 28,
[2][1][RTW89_UK][4] = 40,
+ [2][1][RTW89_MEXICO][4] = 50,
+ [2][1][RTW89_UKRAINE][4] = 34,
+ [2][1][RTW89_CHILE][4] = 50,
+ [2][1][RTW89_QATAR][4] = 40,
[2][1][RTW89_FCC][6] = 50,
[2][1][RTW89_ETSI][6] = 40,
[2][1][RTW89_MKK][6] = 36,
[2][1][RTW89_IC][6] = 26,
- [2][1][RTW89_KCC][6] = 20,
+ [2][1][RTW89_KCC][6] = 30,
[2][1][RTW89_ACMA][6] = 40,
[2][1][RTW89_CN][6] = 28,
[2][1][RTW89_UK][6] = 40,
+ [2][1][RTW89_MEXICO][6] = 50,
+ [2][1][RTW89_UKRAINE][6] = 34,
+ [2][1][RTW89_CHILE][6] = 50,
+ [2][1][RTW89_QATAR][6] = 40,
[2][1][RTW89_FCC][8] = 50,
[2][1][RTW89_ETSI][8] = 40,
[2][1][RTW89_MKK][8] = 32,
[2][1][RTW89_IC][8] = 50,
- [2][1][RTW89_KCC][8] = 46,
+ [2][1][RTW89_KCC][8] = 50,
[2][1][RTW89_ACMA][8] = 40,
[2][1][RTW89_CN][8] = 28,
[2][1][RTW89_UK][8] = 40,
+ [2][1][RTW89_MEXICO][8] = 50,
+ [2][1][RTW89_UKRAINE][8] = 34,
+ [2][1][RTW89_CHILE][8] = 50,
+ [2][1][RTW89_QATAR][8] = 40,
[2][1][RTW89_FCC][10] = 50,
[2][1][RTW89_ETSI][10] = 40,
[2][1][RTW89_MKK][10] = 32,
[2][1][RTW89_IC][10] = 50,
- [2][1][RTW89_KCC][10] = 46,
+ [2][1][RTW89_KCC][10] = 50,
[2][1][RTW89_ACMA][10] = 40,
[2][1][RTW89_CN][10] = 28,
[2][1][RTW89_UK][10] = 40,
+ [2][1][RTW89_MEXICO][10] = 50,
+ [2][1][RTW89_UKRAINE][10] = 34,
+ [2][1][RTW89_CHILE][10] = 50,
+ [2][1][RTW89_QATAR][10] = 40,
[2][1][RTW89_FCC][12] = 48,
[2][1][RTW89_ETSI][12] = 40,
[2][1][RTW89_MKK][12] = 44,
[2][1][RTW89_IC][12] = 48,
- [2][1][RTW89_KCC][12] = 46,
+ [2][1][RTW89_KCC][12] = 48,
[2][1][RTW89_ACMA][12] = 40,
[2][1][RTW89_CN][12] = 28,
[2][1][RTW89_UK][12] = 40,
+ [2][1][RTW89_MEXICO][12] = 48,
+ [2][1][RTW89_UKRAINE][12] = 34,
+ [2][1][RTW89_CHILE][12] = 48,
+ [2][1][RTW89_QATAR][12] = 40,
[2][1][RTW89_FCC][14] = 48,
[2][1][RTW89_ETSI][14] = 40,
[2][1][RTW89_MKK][14] = 44,
[2][1][RTW89_IC][14] = 48,
- [2][1][RTW89_KCC][14] = 46,
+ [2][1][RTW89_KCC][14] = 48,
[2][1][RTW89_ACMA][14] = 40,
[2][1][RTW89_CN][14] = 28,
[2][1][RTW89_UK][14] = 40,
+ [2][1][RTW89_MEXICO][14] = 48,
+ [2][1][RTW89_UKRAINE][14] = 34,
+ [2][1][RTW89_CHILE][14] = 48,
+ [2][1][RTW89_QATAR][14] = 40,
[2][1][RTW89_FCC][15] = 50,
[2][1][RTW89_ETSI][15] = 40,
[2][1][RTW89_MKK][15] = 66,
[2][1][RTW89_IC][15] = 50,
- [2][1][RTW89_KCC][15] = 46,
+ [2][1][RTW89_KCC][15] = 48,
[2][1][RTW89_ACMA][15] = 40,
[2][1][RTW89_CN][15] = 127,
[2][1][RTW89_UK][15] = 40,
+ [2][1][RTW89_MEXICO][15] = 50,
+ [2][1][RTW89_UKRAINE][15] = 34,
+ [2][1][RTW89_CHILE][15] = 50,
+ [2][1][RTW89_QATAR][15] = 40,
[2][1][RTW89_FCC][17] = 50,
[2][1][RTW89_ETSI][17] = 40,
[2][1][RTW89_MKK][17] = 66,
[2][1][RTW89_IC][17] = 50,
- [2][1][RTW89_KCC][17] = 46,
+ [2][1][RTW89_KCC][17] = 48,
[2][1][RTW89_ACMA][17] = 40,
[2][1][RTW89_CN][17] = 127,
[2][1][RTW89_UK][17] = 40,
+ [2][1][RTW89_MEXICO][17] = 50,
+ [2][1][RTW89_UKRAINE][17] = 34,
+ [2][1][RTW89_CHILE][17] = 50,
+ [2][1][RTW89_QATAR][17] = 40,
[2][1][RTW89_FCC][19] = 50,
[2][1][RTW89_ETSI][19] = 40,
[2][1][RTW89_MKK][19] = 66,
[2][1][RTW89_IC][19] = 50,
- [2][1][RTW89_KCC][19] = 46,
+ [2][1][RTW89_KCC][19] = 48,
[2][1][RTW89_ACMA][19] = 40,
[2][1][RTW89_CN][19] = 127,
[2][1][RTW89_UK][19] = 40,
+ [2][1][RTW89_MEXICO][19] = 50,
+ [2][1][RTW89_UKRAINE][19] = 34,
+ [2][1][RTW89_CHILE][19] = 50,
+ [2][1][RTW89_QATAR][19] = 40,
[2][1][RTW89_FCC][21] = 50,
[2][1][RTW89_ETSI][21] = 40,
[2][1][RTW89_MKK][21] = 66,
[2][1][RTW89_IC][21] = 50,
- [2][1][RTW89_KCC][21] = 46,
+ [2][1][RTW89_KCC][21] = 48,
[2][1][RTW89_ACMA][21] = 40,
[2][1][RTW89_CN][21] = 127,
[2][1][RTW89_UK][21] = 40,
+ [2][1][RTW89_MEXICO][21] = 50,
+ [2][1][RTW89_UKRAINE][21] = 34,
+ [2][1][RTW89_CHILE][21] = 50,
+ [2][1][RTW89_QATAR][21] = 40,
[2][1][RTW89_FCC][23] = 50,
[2][1][RTW89_ETSI][23] = 40,
[2][1][RTW89_MKK][23] = 66,
[2][1][RTW89_IC][23] = 50,
- [2][1][RTW89_KCC][23] = 46,
+ [2][1][RTW89_KCC][23] = 48,
[2][1][RTW89_ACMA][23] = 40,
[2][1][RTW89_CN][23] = 127,
[2][1][RTW89_UK][23] = 40,
+ [2][1][RTW89_MEXICO][23] = 50,
+ [2][1][RTW89_UKRAINE][23] = 34,
+ [2][1][RTW89_CHILE][23] = 50,
+ [2][1][RTW89_QATAR][23] = 40,
[2][1][RTW89_FCC][25] = 50,
[2][1][RTW89_ETSI][25] = 40,
[2][1][RTW89_MKK][25] = 66,
[2][1][RTW89_IC][25] = 127,
- [2][1][RTW89_KCC][25] = 46,
+ [2][1][RTW89_KCC][25] = 48,
[2][1][RTW89_ACMA][25] = 127,
[2][1][RTW89_CN][25] = 127,
[2][1][RTW89_UK][25] = 40,
+ [2][1][RTW89_MEXICO][25] = 50,
+ [2][1][RTW89_UKRAINE][25] = 34,
+ [2][1][RTW89_CHILE][25] = 50,
+ [2][1][RTW89_QATAR][25] = 40,
[2][1][RTW89_FCC][27] = 50,
[2][1][RTW89_ETSI][27] = 40,
[2][1][RTW89_MKK][27] = 66,
[2][1][RTW89_IC][27] = 127,
- [2][1][RTW89_KCC][27] = 46,
+ [2][1][RTW89_KCC][27] = 48,
[2][1][RTW89_ACMA][27] = 127,
[2][1][RTW89_CN][27] = 127,
[2][1][RTW89_UK][27] = 40,
+ [2][1][RTW89_MEXICO][27] = 50,
+ [2][1][RTW89_UKRAINE][27] = 34,
+ [2][1][RTW89_CHILE][27] = 50,
+ [2][1][RTW89_QATAR][27] = 40,
[2][1][RTW89_FCC][29] = 50,
[2][1][RTW89_ETSI][29] = 40,
[2][1][RTW89_MKK][29] = 66,
[2][1][RTW89_IC][29] = 127,
- [2][1][RTW89_KCC][29] = 46,
+ [2][1][RTW89_KCC][29] = 48,
[2][1][RTW89_ACMA][29] = 127,
[2][1][RTW89_CN][29] = 127,
[2][1][RTW89_UK][29] = 40,
+ [2][1][RTW89_MEXICO][29] = 50,
+ [2][1][RTW89_UKRAINE][29] = 34,
+ [2][1][RTW89_CHILE][29] = 50,
+ [2][1][RTW89_QATAR][29] = 40,
[2][1][RTW89_FCC][31] = 50,
[2][1][RTW89_ETSI][31] = 40,
[2][1][RTW89_MKK][31] = 66,
[2][1][RTW89_IC][31] = 48,
- [2][1][RTW89_KCC][31] = 46,
+ [2][1][RTW89_KCC][31] = 48,
[2][1][RTW89_ACMA][31] = 40,
[2][1][RTW89_CN][31] = 127,
[2][1][RTW89_UK][31] = 40,
+ [2][1][RTW89_MEXICO][31] = 50,
+ [2][1][RTW89_UKRAINE][31] = 34,
+ [2][1][RTW89_CHILE][31] = 50,
+ [2][1][RTW89_QATAR][31] = 40,
[2][1][RTW89_FCC][33] = 48,
[2][1][RTW89_ETSI][33] = 40,
[2][1][RTW89_MKK][33] = 66,
[2][1][RTW89_IC][33] = 48,
- [2][1][RTW89_KCC][33] = 46,
+ [2][1][RTW89_KCC][33] = 48,
[2][1][RTW89_ACMA][33] = 40,
[2][1][RTW89_CN][33] = 127,
[2][1][RTW89_UK][33] = 40,
+ [2][1][RTW89_MEXICO][33] = 48,
+ [2][1][RTW89_UKRAINE][33] = 34,
+ [2][1][RTW89_CHILE][33] = 48,
+ [2][1][RTW89_QATAR][33] = 40,
[2][1][RTW89_FCC][35] = 48,
[2][1][RTW89_ETSI][35] = 40,
[2][1][RTW89_MKK][35] = 66,
[2][1][RTW89_IC][35] = 48,
- [2][1][RTW89_KCC][35] = 46,
+ [2][1][RTW89_KCC][35] = 48,
[2][1][RTW89_ACMA][35] = 40,
[2][1][RTW89_CN][35] = 127,
[2][1][RTW89_UK][35] = 40,
+ [2][1][RTW89_MEXICO][35] = 48,
+ [2][1][RTW89_UKRAINE][35] = 34,
+ [2][1][RTW89_CHILE][35] = 48,
+ [2][1][RTW89_QATAR][35] = 40,
[2][1][RTW89_FCC][37] = 52,
[2][1][RTW89_ETSI][37] = 127,
[2][1][RTW89_MKK][37] = 66,
[2][1][RTW89_IC][37] = 52,
- [2][1][RTW89_KCC][37] = 46,
+ [2][1][RTW89_KCC][37] = 48,
[2][1][RTW89_ACMA][37] = 52,
[2][1][RTW89_CN][37] = 127,
[2][1][RTW89_UK][37] = 42,
+ [2][1][RTW89_MEXICO][37] = 52,
+ [2][1][RTW89_UKRAINE][37] = 127,
+ [2][1][RTW89_CHILE][37] = 52,
+ [2][1][RTW89_QATAR][37] = 127,
[2][1][RTW89_FCC][38] = 78,
[2][1][RTW89_ETSI][38] = 16,
[2][1][RTW89_MKK][38] = 127,
[2][1][RTW89_IC][38] = 78,
- [2][1][RTW89_KCC][38] = 46,
+ [2][1][RTW89_KCC][38] = 50,
[2][1][RTW89_ACMA][38] = 78,
[2][1][RTW89_CN][38] = 56,
[2][1][RTW89_UK][38] = 42,
+ [2][1][RTW89_MEXICO][38] = 78,
+ [2][1][RTW89_UKRAINE][38] = 14,
+ [2][1][RTW89_CHILE][38] = 72,
+ [2][1][RTW89_QATAR][38] = 14,
[2][1][RTW89_FCC][40] = 78,
[2][1][RTW89_ETSI][40] = 16,
[2][1][RTW89_MKK][40] = 127,
[2][1][RTW89_IC][40] = 78,
- [2][1][RTW89_KCC][40] = 46,
+ [2][1][RTW89_KCC][40] = 50,
[2][1][RTW89_ACMA][40] = 78,
[2][1][RTW89_CN][40] = 56,
[2][1][RTW89_UK][40] = 42,
+ [2][1][RTW89_MEXICO][40] = 78,
+ [2][1][RTW89_UKRAINE][40] = 14,
+ [2][1][RTW89_CHILE][40] = 72,
+ [2][1][RTW89_QATAR][40] = 14,
[2][1][RTW89_FCC][42] = 78,
[2][1][RTW89_ETSI][42] = 16,
[2][1][RTW89_MKK][42] = 127,
[2][1][RTW89_IC][42] = 78,
- [2][1][RTW89_KCC][42] = 46,
+ [2][1][RTW89_KCC][42] = 50,
[2][1][RTW89_ACMA][42] = 78,
[2][1][RTW89_CN][42] = 56,
[2][1][RTW89_UK][42] = 42,
+ [2][1][RTW89_MEXICO][42] = 78,
+ [2][1][RTW89_UKRAINE][42] = 14,
+ [2][1][RTW89_CHILE][42] = 72,
+ [2][1][RTW89_QATAR][42] = 14,
[2][1][RTW89_FCC][44] = 74,
[2][1][RTW89_ETSI][44] = 16,
[2][1][RTW89_MKK][44] = 127,
[2][1][RTW89_IC][44] = 74,
- [2][1][RTW89_KCC][44] = 46,
+ [2][1][RTW89_KCC][44] = 50,
[2][1][RTW89_ACMA][44] = 74,
[2][1][RTW89_CN][44] = 56,
[2][1][RTW89_UK][44] = 42,
+ [2][1][RTW89_MEXICO][44] = 74,
+ [2][1][RTW89_UKRAINE][44] = 14,
+ [2][1][RTW89_CHILE][44] = 72,
+ [2][1][RTW89_QATAR][44] = 14,
[2][1][RTW89_FCC][46] = 74,
[2][1][RTW89_ETSI][46] = 16,
[2][1][RTW89_MKK][46] = 127,
[2][1][RTW89_IC][46] = 74,
- [2][1][RTW89_KCC][46] = 46,
+ [2][1][RTW89_KCC][46] = 50,
[2][1][RTW89_ACMA][46] = 74,
[2][1][RTW89_CN][46] = 56,
[2][1][RTW89_UK][46] = 42,
+ [2][1][RTW89_MEXICO][46] = 74,
+ [2][1][RTW89_UKRAINE][46] = 14,
+ [2][1][RTW89_CHILE][46] = 72,
+ [2][1][RTW89_QATAR][46] = 14,
[2][1][RTW89_FCC][48] = 40,
[2][1][RTW89_ETSI][48] = 127,
[2][1][RTW89_MKK][48] = 127,
@@ -36240,6 +49061,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][48] = 127,
[2][1][RTW89_CN][48] = 127,
[2][1][RTW89_UK][48] = 127,
+ [2][1][RTW89_MEXICO][48] = 127,
+ [2][1][RTW89_UKRAINE][48] = 127,
+ [2][1][RTW89_CHILE][48] = 127,
+ [2][1][RTW89_QATAR][48] = 127,
[2][1][RTW89_FCC][50] = 40,
[2][1][RTW89_ETSI][50] = 127,
[2][1][RTW89_MKK][50] = 127,
@@ -36248,6 +49073,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][50] = 127,
[2][1][RTW89_CN][50] = 127,
[2][1][RTW89_UK][50] = 127,
+ [2][1][RTW89_MEXICO][50] = 127,
+ [2][1][RTW89_UKRAINE][50] = 127,
+ [2][1][RTW89_CHILE][50] = 127,
+ [2][1][RTW89_QATAR][50] = 127,
[2][1][RTW89_FCC][52] = 40,
[2][1][RTW89_ETSI][52] = 127,
[2][1][RTW89_MKK][52] = 127,
@@ -36256,1163 +49085,7312 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
[2][1][RTW89_ACMA][52] = 127,
[2][1][RTW89_CN][52] = 127,
[2][1][RTW89_UK][52] = 127,
+ [2][1][RTW89_MEXICO][52] = 127,
+ [2][1][RTW89_UKRAINE][52] = 127,
+ [2][1][RTW89_CHILE][52] = 127,
+ [2][1][RTW89_QATAR][52] = 127,
};
static
const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM]
- [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = {
- [0][0][RTW89_WW][0] = -16,
- [0][0][RTW89_WW][2] = -18,
- [0][0][RTW89_WW][4] = -18,
- [0][0][RTW89_WW][6] = -18,
- [0][0][RTW89_WW][8] = -18,
- [0][0][RTW89_WW][10] = -18,
- [0][0][RTW89_WW][12] = -18,
- [0][0][RTW89_WW][14] = -18,
- [0][0][RTW89_WW][15] = -18,
- [0][0][RTW89_WW][17] = -18,
- [0][0][RTW89_WW][19] = -18,
- [0][0][RTW89_WW][21] = -18,
- [0][0][RTW89_WW][23] = -18,
- [0][0][RTW89_WW][25] = -18,
- [0][0][RTW89_WW][27] = -18,
- [0][0][RTW89_WW][29] = -18,
- [0][0][RTW89_WW][30] = -18,
- [0][0][RTW89_WW][32] = -18,
- [0][0][RTW89_WW][34] = -18,
- [0][0][RTW89_WW][36] = -18,
- [0][0][RTW89_WW][38] = -18,
- [0][0][RTW89_WW][40] = -18,
- [0][0][RTW89_WW][42] = -18,
- [0][0][RTW89_WW][44] = -16,
- [0][0][RTW89_WW][45] = -16,
- [0][0][RTW89_WW][47] = -18,
- [0][0][RTW89_WW][49] = -18,
- [0][0][RTW89_WW][51] = -18,
- [0][0][RTW89_WW][53] = -16,
- [0][0][RTW89_WW][55] = -18,
- [0][0][RTW89_WW][57] = -18,
- [0][0][RTW89_WW][59] = -18,
- [0][0][RTW89_WW][60] = -18,
- [0][0][RTW89_WW][62] = -18,
- [0][0][RTW89_WW][64] = -18,
- [0][0][RTW89_WW][66] = -18,
- [0][0][RTW89_WW][68] = -18,
- [0][0][RTW89_WW][70] = -16,
- [0][0][RTW89_WW][72] = -18,
- [0][0][RTW89_WW][74] = -18,
- [0][0][RTW89_WW][75] = -18,
- [0][0][RTW89_WW][77] = -18,
- [0][0][RTW89_WW][79] = -18,
- [0][0][RTW89_WW][81] = -18,
- [0][0][RTW89_WW][83] = -18,
- [0][0][RTW89_WW][85] = -18,
- [0][0][RTW89_WW][87] = -16,
- [0][0][RTW89_WW][89] = -16,
- [0][0][RTW89_WW][90] = -16,
- [0][0][RTW89_WW][92] = -16,
- [0][0][RTW89_WW][94] = -16,
- [0][0][RTW89_WW][96] = -16,
- [0][0][RTW89_WW][98] = -16,
- [0][0][RTW89_WW][100] = -16,
- [0][0][RTW89_WW][102] = -16,
- [0][0][RTW89_WW][104] = -16,
- [0][0][RTW89_WW][105] = -16,
- [0][0][RTW89_WW][107] = -12,
- [0][0][RTW89_WW][109] = -12,
- [0][0][RTW89_WW][111] = 0,
- [0][0][RTW89_WW][113] = 0,
- [0][0][RTW89_WW][115] = 0,
- [0][0][RTW89_WW][117] = 0,
- [0][0][RTW89_WW][119] = 0,
- [0][1][RTW89_WW][0] = -40,
- [0][1][RTW89_WW][2] = -40,
- [0][1][RTW89_WW][4] = -40,
- [0][1][RTW89_WW][6] = -40,
- [0][1][RTW89_WW][8] = -40,
- [0][1][RTW89_WW][10] = -40,
- [0][1][RTW89_WW][12] = -40,
- [0][1][RTW89_WW][14] = -40,
- [0][1][RTW89_WW][15] = -40,
- [0][1][RTW89_WW][17] = -40,
- [0][1][RTW89_WW][19] = -40,
- [0][1][RTW89_WW][21] = -40,
- [0][1][RTW89_WW][23] = -40,
- [0][1][RTW89_WW][25] = -40,
- [0][1][RTW89_WW][27] = -40,
- [0][1][RTW89_WW][29] = -40,
- [0][1][RTW89_WW][30] = -40,
- [0][1][RTW89_WW][32] = -40,
- [0][1][RTW89_WW][34] = -40,
- [0][1][RTW89_WW][36] = -40,
- [0][1][RTW89_WW][38] = -40,
- [0][1][RTW89_WW][40] = -40,
- [0][1][RTW89_WW][42] = -40,
- [0][1][RTW89_WW][44] = -40,
- [0][1][RTW89_WW][45] = -40,
- [0][1][RTW89_WW][47] = -40,
- [0][1][RTW89_WW][49] = -40,
- [0][1][RTW89_WW][51] = -40,
- [0][1][RTW89_WW][53] = -40,
- [0][1][RTW89_WW][55] = -40,
- [0][1][RTW89_WW][57] = -40,
- [0][1][RTW89_WW][59] = -40,
- [0][1][RTW89_WW][60] = -40,
- [0][1][RTW89_WW][62] = -40,
- [0][1][RTW89_WW][64] = -40,
- [0][1][RTW89_WW][66] = -40,
- [0][1][RTW89_WW][68] = -40,
- [0][1][RTW89_WW][70] = -38,
- [0][1][RTW89_WW][72] = -38,
- [0][1][RTW89_WW][74] = -38,
- [0][1][RTW89_WW][75] = -38,
- [0][1][RTW89_WW][77] = -38,
- [0][1][RTW89_WW][79] = -38,
- [0][1][RTW89_WW][81] = -38,
- [0][1][RTW89_WW][83] = -38,
- [0][1][RTW89_WW][85] = -38,
- [0][1][RTW89_WW][87] = -40,
- [0][1][RTW89_WW][89] = -38,
- [0][1][RTW89_WW][90] = -38,
- [0][1][RTW89_WW][92] = -38,
- [0][1][RTW89_WW][94] = -38,
- [0][1][RTW89_WW][96] = -38,
- [0][1][RTW89_WW][98] = -38,
- [0][1][RTW89_WW][100] = -38,
- [0][1][RTW89_WW][102] = -38,
- [0][1][RTW89_WW][104] = -38,
- [0][1][RTW89_WW][105] = -38,
- [0][1][RTW89_WW][107] = -34,
- [0][1][RTW89_WW][109] = -34,
- [0][1][RTW89_WW][111] = 0,
- [0][1][RTW89_WW][113] = 0,
- [0][1][RTW89_WW][115] = 0,
- [0][1][RTW89_WW][117] = 0,
- [0][1][RTW89_WW][119] = 0,
- [1][0][RTW89_WW][0] = -4,
- [1][0][RTW89_WW][2] = -4,
- [1][0][RTW89_WW][4] = -4,
- [1][0][RTW89_WW][6] = -4,
- [1][0][RTW89_WW][8] = -4,
- [1][0][RTW89_WW][10] = -4,
- [1][0][RTW89_WW][12] = -4,
- [1][0][RTW89_WW][14] = -4,
- [1][0][RTW89_WW][15] = -4,
- [1][0][RTW89_WW][17] = -4,
- [1][0][RTW89_WW][19] = -4,
- [1][0][RTW89_WW][21] = -4,
- [1][0][RTW89_WW][23] = -4,
- [1][0][RTW89_WW][25] = -4,
- [1][0][RTW89_WW][27] = -4,
- [1][0][RTW89_WW][29] = -4,
- [1][0][RTW89_WW][30] = -4,
- [1][0][RTW89_WW][32] = -4,
- [1][0][RTW89_WW][34] = -4,
- [1][0][RTW89_WW][36] = -4,
- [1][0][RTW89_WW][38] = -4,
- [1][0][RTW89_WW][40] = -4,
- [1][0][RTW89_WW][42] = -4,
- [1][0][RTW89_WW][44] = -4,
- [1][0][RTW89_WW][45] = -4,
- [1][0][RTW89_WW][47] = -4,
- [1][0][RTW89_WW][49] = -4,
- [1][0][RTW89_WW][51] = -4,
- [1][0][RTW89_WW][53] = -4,
- [1][0][RTW89_WW][55] = -4,
- [1][0][RTW89_WW][57] = -4,
- [1][0][RTW89_WW][59] = -4,
- [1][0][RTW89_WW][60] = -4,
- [1][0][RTW89_WW][62] = -4,
- [1][0][RTW89_WW][64] = -4,
- [1][0][RTW89_WW][66] = -4,
- [1][0][RTW89_WW][68] = -4,
- [1][0][RTW89_WW][70] = -4,
- [1][0][RTW89_WW][72] = -4,
- [1][0][RTW89_WW][74] = -4,
- [1][0][RTW89_WW][75] = -4,
- [1][0][RTW89_WW][77] = -4,
- [1][0][RTW89_WW][79] = -4,
- [1][0][RTW89_WW][81] = -4,
- [1][0][RTW89_WW][83] = -4,
- [1][0][RTW89_WW][85] = -4,
- [1][0][RTW89_WW][87] = -4,
- [1][0][RTW89_WW][89] = -4,
- [1][0][RTW89_WW][90] = -4,
- [1][0][RTW89_WW][92] = -4,
- [1][0][RTW89_WW][94] = -4,
- [1][0][RTW89_WW][96] = -4,
- [1][0][RTW89_WW][98] = -4,
- [1][0][RTW89_WW][100] = -4,
- [1][0][RTW89_WW][102] = -4,
- [1][0][RTW89_WW][104] = -4,
- [1][0][RTW89_WW][105] = -4,
- [1][0][RTW89_WW][107] = 1,
- [1][0][RTW89_WW][109] = 2,
- [1][0][RTW89_WW][111] = 0,
- [1][0][RTW89_WW][113] = 0,
- [1][0][RTW89_WW][115] = 0,
- [1][0][RTW89_WW][117] = 0,
- [1][0][RTW89_WW][119] = 0,
- [1][1][RTW89_WW][0] = -26,
- [1][1][RTW89_WW][2] = -28,
- [1][1][RTW89_WW][4] = -28,
- [1][1][RTW89_WW][6] = -28,
- [1][1][RTW89_WW][8] = -28,
- [1][1][RTW89_WW][10] = -28,
- [1][1][RTW89_WW][12] = -28,
- [1][1][RTW89_WW][14] = -28,
- [1][1][RTW89_WW][15] = -28,
- [1][1][RTW89_WW][17] = -28,
- [1][1][RTW89_WW][19] = -28,
- [1][1][RTW89_WW][21] = -28,
- [1][1][RTW89_WW][23] = -28,
- [1][1][RTW89_WW][25] = -28,
- [1][1][RTW89_WW][27] = -28,
- [1][1][RTW89_WW][29] = -28,
- [1][1][RTW89_WW][30] = -28,
- [1][1][RTW89_WW][32] = -28,
- [1][1][RTW89_WW][34] = -28,
- [1][1][RTW89_WW][36] = -28,
- [1][1][RTW89_WW][38] = -28,
- [1][1][RTW89_WW][40] = -28,
- [1][1][RTW89_WW][42] = -28,
- [1][1][RTW89_WW][44] = -28,
- [1][1][RTW89_WW][45] = -26,
- [1][1][RTW89_WW][47] = -28,
- [1][1][RTW89_WW][49] = -28,
- [1][1][RTW89_WW][51] = -28,
- [1][1][RTW89_WW][53] = -26,
- [1][1][RTW89_WW][55] = -28,
- [1][1][RTW89_WW][57] = -28,
- [1][1][RTW89_WW][59] = -28,
- [1][1][RTW89_WW][60] = -28,
- [1][1][RTW89_WW][62] = -28,
- [1][1][RTW89_WW][64] = -28,
- [1][1][RTW89_WW][66] = -28,
- [1][1][RTW89_WW][68] = -28,
- [1][1][RTW89_WW][70] = -26,
- [1][1][RTW89_WW][72] = -28,
- [1][1][RTW89_WW][74] = -28,
- [1][1][RTW89_WW][75] = -28,
- [1][1][RTW89_WW][77] = -28,
- [1][1][RTW89_WW][79] = -28,
- [1][1][RTW89_WW][81] = -28,
- [1][1][RTW89_WW][83] = -28,
- [1][1][RTW89_WW][85] = -28,
- [1][1][RTW89_WW][87] = -28,
- [1][1][RTW89_WW][89] = -26,
- [1][1][RTW89_WW][90] = -26,
- [1][1][RTW89_WW][92] = -26,
- [1][1][RTW89_WW][94] = -26,
- [1][1][RTW89_WW][96] = -26,
- [1][1][RTW89_WW][98] = -26,
- [1][1][RTW89_WW][100] = -26,
- [1][1][RTW89_WW][102] = -26,
- [1][1][RTW89_WW][104] = -26,
- [1][1][RTW89_WW][105] = -26,
- [1][1][RTW89_WW][107] = -22,
- [1][1][RTW89_WW][109] = -22,
- [1][1][RTW89_WW][111] = 0,
- [1][1][RTW89_WW][113] = 0,
- [1][1][RTW89_WW][115] = 0,
- [1][1][RTW89_WW][117] = 0,
- [1][1][RTW89_WW][119] = 0,
- [2][0][RTW89_WW][0] = 8,
- [2][0][RTW89_WW][2] = 8,
- [2][0][RTW89_WW][4] = 8,
- [2][0][RTW89_WW][6] = 8,
- [2][0][RTW89_WW][8] = 8,
- [2][0][RTW89_WW][10] = 8,
- [2][0][RTW89_WW][12] = 8,
- [2][0][RTW89_WW][14] = 8,
- [2][0][RTW89_WW][15] = 8,
- [2][0][RTW89_WW][17] = 8,
- [2][0][RTW89_WW][19] = 8,
- [2][0][RTW89_WW][21] = 8,
- [2][0][RTW89_WW][23] = 8,
- [2][0][RTW89_WW][25] = 8,
- [2][0][RTW89_WW][27] = 8,
- [2][0][RTW89_WW][29] = 8,
- [2][0][RTW89_WW][30] = 8,
- [2][0][RTW89_WW][32] = 8,
- [2][0][RTW89_WW][34] = 8,
- [2][0][RTW89_WW][36] = 8,
- [2][0][RTW89_WW][38] = 8,
- [2][0][RTW89_WW][40] = 8,
- [2][0][RTW89_WW][42] = 8,
- [2][0][RTW89_WW][44] = 8,
- [2][0][RTW89_WW][45] = 8,
- [2][0][RTW89_WW][47] = 8,
- [2][0][RTW89_WW][49] = 8,
- [2][0][RTW89_WW][51] = 8,
- [2][0][RTW89_WW][53] = 8,
- [2][0][RTW89_WW][55] = 8,
- [2][0][RTW89_WW][57] = 8,
- [2][0][RTW89_WW][59] = 8,
- [2][0][RTW89_WW][60] = 8,
- [2][0][RTW89_WW][62] = 8,
- [2][0][RTW89_WW][64] = 8,
- [2][0][RTW89_WW][66] = 8,
- [2][0][RTW89_WW][68] = 8,
- [2][0][RTW89_WW][70] = 8,
- [2][0][RTW89_WW][72] = 8,
- [2][0][RTW89_WW][74] = 8,
- [2][0][RTW89_WW][75] = 8,
- [2][0][RTW89_WW][77] = 8,
- [2][0][RTW89_WW][79] = 8,
- [2][0][RTW89_WW][81] = 8,
- [2][0][RTW89_WW][83] = 8,
- [2][0][RTW89_WW][85] = 8,
- [2][0][RTW89_WW][87] = 8,
- [2][0][RTW89_WW][89] = 8,
- [2][0][RTW89_WW][90] = 8,
- [2][0][RTW89_WW][92] = 8,
- [2][0][RTW89_WW][94] = 8,
- [2][0][RTW89_WW][96] = 8,
- [2][0][RTW89_WW][98] = 8,
- [2][0][RTW89_WW][100] = 8,
- [2][0][RTW89_WW][102] = 8,
- [2][0][RTW89_WW][104] = 8,
- [2][0][RTW89_WW][105] = 8,
- [2][0][RTW89_WW][107] = 10,
- [2][0][RTW89_WW][109] = 12,
- [2][0][RTW89_WW][111] = 0,
- [2][0][RTW89_WW][113] = 0,
- [2][0][RTW89_WW][115] = 0,
- [2][0][RTW89_WW][117] = 0,
- [2][0][RTW89_WW][119] = 0,
- [2][1][RTW89_WW][0] = -16,
- [2][1][RTW89_WW][2] = -16,
- [2][1][RTW89_WW][4] = -16,
- [2][1][RTW89_WW][6] = -16,
- [2][1][RTW89_WW][8] = -16,
- [2][1][RTW89_WW][10] = -16,
- [2][1][RTW89_WW][12] = -16,
- [2][1][RTW89_WW][14] = -16,
- [2][1][RTW89_WW][15] = -16,
- [2][1][RTW89_WW][17] = -16,
- [2][1][RTW89_WW][19] = -16,
- [2][1][RTW89_WW][21] = -16,
- [2][1][RTW89_WW][23] = -16,
- [2][1][RTW89_WW][25] = -16,
- [2][1][RTW89_WW][27] = -16,
- [2][1][RTW89_WW][29] = -16,
- [2][1][RTW89_WW][30] = -16,
- [2][1][RTW89_WW][32] = -16,
- [2][1][RTW89_WW][34] = -16,
- [2][1][RTW89_WW][36] = -16,
- [2][1][RTW89_WW][38] = -16,
- [2][1][RTW89_WW][40] = -16,
- [2][1][RTW89_WW][42] = -16,
- [2][1][RTW89_WW][44] = -16,
- [2][1][RTW89_WW][45] = -16,
- [2][1][RTW89_WW][47] = -16,
- [2][1][RTW89_WW][49] = -16,
- [2][1][RTW89_WW][51] = -16,
- [2][1][RTW89_WW][53] = -16,
- [2][1][RTW89_WW][55] = -16,
- [2][1][RTW89_WW][57] = -16,
- [2][1][RTW89_WW][59] = -16,
- [2][1][RTW89_WW][60] = -16,
- [2][1][RTW89_WW][62] = -16,
- [2][1][RTW89_WW][64] = -16,
- [2][1][RTW89_WW][66] = -16,
- [2][1][RTW89_WW][68] = -16,
- [2][1][RTW89_WW][70] = -16,
- [2][1][RTW89_WW][72] = -16,
- [2][1][RTW89_WW][74] = -16,
- [2][1][RTW89_WW][75] = -16,
- [2][1][RTW89_WW][77] = -16,
- [2][1][RTW89_WW][79] = -16,
- [2][1][RTW89_WW][81] = -16,
- [2][1][RTW89_WW][83] = -16,
- [2][1][RTW89_WW][85] = -18,
- [2][1][RTW89_WW][87] = -16,
- [2][1][RTW89_WW][89] = -16,
- [2][1][RTW89_WW][90] = -16,
- [2][1][RTW89_WW][92] = -16,
- [2][1][RTW89_WW][94] = -16,
- [2][1][RTW89_WW][96] = -16,
- [2][1][RTW89_WW][98] = -16,
- [2][1][RTW89_WW][100] = -16,
- [2][1][RTW89_WW][102] = -16,
- [2][1][RTW89_WW][104] = -16,
- [2][1][RTW89_WW][105] = -16,
- [2][1][RTW89_WW][107] = -12,
- [2][1][RTW89_WW][109] = -10,
- [2][1][RTW89_WW][111] = 0,
- [2][1][RTW89_WW][113] = 0,
- [2][1][RTW89_WW][115] = 0,
- [2][1][RTW89_WW][117] = 0,
- [2][1][RTW89_WW][119] = 0,
- [0][0][RTW89_FCC][0] = -16,
- [0][0][RTW89_ETSI][0] = 32,
- [0][0][RTW89_FCC][2] = -18,
- [0][0][RTW89_ETSI][2] = 32,
- [0][0][RTW89_FCC][4] = -18,
- [0][0][RTW89_ETSI][4] = 32,
- [0][0][RTW89_FCC][6] = -18,
- [0][0][RTW89_ETSI][6] = 32,
- [0][0][RTW89_FCC][8] = -18,
- [0][0][RTW89_ETSI][8] = 32,
- [0][0][RTW89_FCC][10] = -18,
- [0][0][RTW89_ETSI][10] = 32,
- [0][0][RTW89_FCC][12] = -18,
- [0][0][RTW89_ETSI][12] = 32,
- [0][0][RTW89_FCC][14] = -18,
- [0][0][RTW89_ETSI][14] = 32,
- [0][0][RTW89_FCC][15] = -18,
- [0][0][RTW89_ETSI][15] = 32,
- [0][0][RTW89_FCC][17] = -18,
- [0][0][RTW89_ETSI][17] = 32,
- [0][0][RTW89_FCC][19] = -18,
- [0][0][RTW89_ETSI][19] = 32,
- [0][0][RTW89_FCC][21] = -18,
- [0][0][RTW89_ETSI][21] = 32,
- [0][0][RTW89_FCC][23] = -18,
- [0][0][RTW89_ETSI][23] = 32,
- [0][0][RTW89_FCC][25] = -18,
- [0][0][RTW89_ETSI][25] = 32,
- [0][0][RTW89_FCC][27] = -18,
- [0][0][RTW89_ETSI][27] = 32,
- [0][0][RTW89_FCC][29] = -18,
- [0][0][RTW89_ETSI][29] = 32,
- [0][0][RTW89_FCC][30] = -18,
- [0][0][RTW89_ETSI][30] = 32,
- [0][0][RTW89_FCC][32] = -18,
- [0][0][RTW89_ETSI][32] = 32,
- [0][0][RTW89_FCC][34] = -18,
- [0][0][RTW89_ETSI][34] = 32,
- [0][0][RTW89_FCC][36] = -18,
- [0][0][RTW89_ETSI][36] = 32,
- [0][0][RTW89_FCC][38] = -18,
- [0][0][RTW89_ETSI][38] = 32,
- [0][0][RTW89_FCC][40] = -18,
- [0][0][RTW89_ETSI][40] = 32,
- [0][0][RTW89_FCC][42] = -18,
- [0][0][RTW89_ETSI][42] = 32,
- [0][0][RTW89_FCC][44] = -16,
- [0][0][RTW89_ETSI][44] = 32,
- [0][0][RTW89_FCC][45] = -16,
- [0][0][RTW89_ETSI][45] = 127,
- [0][0][RTW89_FCC][47] = -18,
- [0][0][RTW89_ETSI][47] = 127,
- [0][0][RTW89_FCC][49] = -18,
- [0][0][RTW89_ETSI][49] = 127,
- [0][0][RTW89_FCC][51] = -18,
- [0][0][RTW89_ETSI][51] = 127,
- [0][0][RTW89_FCC][53] = -16,
- [0][0][RTW89_ETSI][53] = 127,
- [0][0][RTW89_FCC][55] = -18,
- [0][0][RTW89_ETSI][55] = 127,
- [0][0][RTW89_FCC][57] = -18,
- [0][0][RTW89_ETSI][57] = 127,
- [0][0][RTW89_FCC][59] = -18,
- [0][0][RTW89_ETSI][59] = 127,
- [0][0][RTW89_FCC][60] = -18,
- [0][0][RTW89_ETSI][60] = 127,
- [0][0][RTW89_FCC][62] = -18,
- [0][0][RTW89_ETSI][62] = 127,
- [0][0][RTW89_FCC][64] = -18,
- [0][0][RTW89_ETSI][64] = 127,
- [0][0][RTW89_FCC][66] = -18,
- [0][0][RTW89_ETSI][66] = 127,
- [0][0][RTW89_FCC][68] = -18,
- [0][0][RTW89_ETSI][68] = 127,
- [0][0][RTW89_FCC][70] = -16,
- [0][0][RTW89_ETSI][70] = 127,
- [0][0][RTW89_FCC][72] = -18,
- [0][0][RTW89_ETSI][72] = 127,
- [0][0][RTW89_FCC][74] = -18,
- [0][0][RTW89_ETSI][74] = 127,
- [0][0][RTW89_FCC][75] = -18,
- [0][0][RTW89_ETSI][75] = 127,
- [0][0][RTW89_FCC][77] = -18,
- [0][0][RTW89_ETSI][77] = 127,
- [0][0][RTW89_FCC][79] = -18,
- [0][0][RTW89_ETSI][79] = 127,
- [0][0][RTW89_FCC][81] = -18,
- [0][0][RTW89_ETSI][81] = 127,
- [0][0][RTW89_FCC][83] = -18,
- [0][0][RTW89_ETSI][83] = 127,
- [0][0][RTW89_FCC][85] = -18,
- [0][0][RTW89_ETSI][85] = 127,
- [0][0][RTW89_FCC][87] = -16,
- [0][0][RTW89_ETSI][87] = 127,
- [0][0][RTW89_FCC][89] = -16,
- [0][0][RTW89_ETSI][89] = 127,
- [0][0][RTW89_FCC][90] = -16,
- [0][0][RTW89_ETSI][90] = 127,
- [0][0][RTW89_FCC][92] = -16,
- [0][0][RTW89_ETSI][92] = 127,
- [0][0][RTW89_FCC][94] = -16,
- [0][0][RTW89_ETSI][94] = 127,
- [0][0][RTW89_FCC][96] = -16,
- [0][0][RTW89_ETSI][96] = 127,
- [0][0][RTW89_FCC][98] = -16,
- [0][0][RTW89_ETSI][98] = 127,
- [0][0][RTW89_FCC][100] = -16,
- [0][0][RTW89_ETSI][100] = 127,
- [0][0][RTW89_FCC][102] = -16,
- [0][0][RTW89_ETSI][102] = 127,
- [0][0][RTW89_FCC][104] = -16,
- [0][0][RTW89_ETSI][104] = 127,
- [0][0][RTW89_FCC][105] = -16,
- [0][0][RTW89_ETSI][105] = 127,
- [0][0][RTW89_FCC][107] = -12,
- [0][0][RTW89_ETSI][107] = 127,
- [0][0][RTW89_FCC][109] = -12,
- [0][0][RTW89_ETSI][109] = 127,
- [0][0][RTW89_FCC][111] = 127,
- [0][0][RTW89_ETSI][111] = 127,
- [0][0][RTW89_FCC][113] = 127,
- [0][0][RTW89_ETSI][113] = 127,
- [0][0][RTW89_FCC][115] = 127,
- [0][0][RTW89_ETSI][115] = 127,
- [0][0][RTW89_FCC][117] = 127,
- [0][0][RTW89_ETSI][117] = 127,
- [0][0][RTW89_FCC][119] = 127,
- [0][0][RTW89_ETSI][119] = 127,
- [0][1][RTW89_FCC][0] = -40,
- [0][1][RTW89_ETSI][0] = 20,
- [0][1][RTW89_FCC][2] = -40,
- [0][1][RTW89_ETSI][2] = 20,
- [0][1][RTW89_FCC][4] = -40,
- [0][1][RTW89_ETSI][4] = 20,
- [0][1][RTW89_FCC][6] = -40,
- [0][1][RTW89_ETSI][6] = 20,
- [0][1][RTW89_FCC][8] = -40,
- [0][1][RTW89_ETSI][8] = 20,
- [0][1][RTW89_FCC][10] = -40,
- [0][1][RTW89_ETSI][10] = 20,
- [0][1][RTW89_FCC][12] = -40,
- [0][1][RTW89_ETSI][12] = 20,
- [0][1][RTW89_FCC][14] = -40,
- [0][1][RTW89_ETSI][14] = 20,
- [0][1][RTW89_FCC][15] = -40,
- [0][1][RTW89_ETSI][15] = 20,
- [0][1][RTW89_FCC][17] = -40,
- [0][1][RTW89_ETSI][17] = 20,
- [0][1][RTW89_FCC][19] = -40,
- [0][1][RTW89_ETSI][19] = 20,
- [0][1][RTW89_FCC][21] = -40,
- [0][1][RTW89_ETSI][21] = 20,
- [0][1][RTW89_FCC][23] = -40,
- [0][1][RTW89_ETSI][23] = 20,
- [0][1][RTW89_FCC][25] = -40,
- [0][1][RTW89_ETSI][25] = 20,
- [0][1][RTW89_FCC][27] = -40,
- [0][1][RTW89_ETSI][27] = 20,
- [0][1][RTW89_FCC][29] = -40,
- [0][1][RTW89_ETSI][29] = 20,
- [0][1][RTW89_FCC][30] = -40,
- [0][1][RTW89_ETSI][30] = 20,
- [0][1][RTW89_FCC][32] = -40,
- [0][1][RTW89_ETSI][32] = 20,
- [0][1][RTW89_FCC][34] = -40,
- [0][1][RTW89_ETSI][34] = 20,
- [0][1][RTW89_FCC][36] = -40,
- [0][1][RTW89_ETSI][36] = 20,
- [0][1][RTW89_FCC][38] = -40,
- [0][1][RTW89_ETSI][38] = 20,
- [0][1][RTW89_FCC][40] = -40,
- [0][1][RTW89_ETSI][40] = 20,
- [0][1][RTW89_FCC][42] = -40,
- [0][1][RTW89_ETSI][42] = 20,
- [0][1][RTW89_FCC][44] = -40,
- [0][1][RTW89_ETSI][44] = 20,
- [0][1][RTW89_FCC][45] = -40,
- [0][1][RTW89_ETSI][45] = 127,
- [0][1][RTW89_FCC][47] = -40,
- [0][1][RTW89_ETSI][47] = 127,
- [0][1][RTW89_FCC][49] = -40,
- [0][1][RTW89_ETSI][49] = 127,
- [0][1][RTW89_FCC][51] = -40,
- [0][1][RTW89_ETSI][51] = 127,
- [0][1][RTW89_FCC][53] = -40,
- [0][1][RTW89_ETSI][53] = 127,
- [0][1][RTW89_FCC][55] = -40,
- [0][1][RTW89_ETSI][55] = 127,
- [0][1][RTW89_FCC][57] = -40,
- [0][1][RTW89_ETSI][57] = 127,
- [0][1][RTW89_FCC][59] = -40,
- [0][1][RTW89_ETSI][59] = 127,
- [0][1][RTW89_FCC][60] = -40,
- [0][1][RTW89_ETSI][60] = 127,
- [0][1][RTW89_FCC][62] = -40,
- [0][1][RTW89_ETSI][62] = 127,
- [0][1][RTW89_FCC][64] = -40,
- [0][1][RTW89_ETSI][64] = 127,
- [0][1][RTW89_FCC][66] = -40,
- [0][1][RTW89_ETSI][66] = 127,
- [0][1][RTW89_FCC][68] = -40,
- [0][1][RTW89_ETSI][68] = 127,
- [0][1][RTW89_FCC][70] = -38,
- [0][1][RTW89_ETSI][70] = 127,
- [0][1][RTW89_FCC][72] = -38,
- [0][1][RTW89_ETSI][72] = 127,
- [0][1][RTW89_FCC][74] = -38,
- [0][1][RTW89_ETSI][74] = 127,
- [0][1][RTW89_FCC][75] = -38,
- [0][1][RTW89_ETSI][75] = 127,
- [0][1][RTW89_FCC][77] = -38,
- [0][1][RTW89_ETSI][77] = 127,
- [0][1][RTW89_FCC][79] = -38,
- [0][1][RTW89_ETSI][79] = 127,
- [0][1][RTW89_FCC][81] = -38,
- [0][1][RTW89_ETSI][81] = 127,
- [0][1][RTW89_FCC][83] = -38,
- [0][1][RTW89_ETSI][83] = 127,
- [0][1][RTW89_FCC][85] = -38,
- [0][1][RTW89_ETSI][85] = 127,
- [0][1][RTW89_FCC][87] = -40,
- [0][1][RTW89_ETSI][87] = 127,
- [0][1][RTW89_FCC][89] = -38,
- [0][1][RTW89_ETSI][89] = 127,
- [0][1][RTW89_FCC][90] = -38,
- [0][1][RTW89_ETSI][90] = 127,
- [0][1][RTW89_FCC][92] = -38,
- [0][1][RTW89_ETSI][92] = 127,
- [0][1][RTW89_FCC][94] = -38,
- [0][1][RTW89_ETSI][94] = 127,
- [0][1][RTW89_FCC][96] = -38,
- [0][1][RTW89_ETSI][96] = 127,
- [0][1][RTW89_FCC][98] = -38,
- [0][1][RTW89_ETSI][98] = 127,
- [0][1][RTW89_FCC][100] = -38,
- [0][1][RTW89_ETSI][100] = 127,
- [0][1][RTW89_FCC][102] = -38,
- [0][1][RTW89_ETSI][102] = 127,
- [0][1][RTW89_FCC][104] = -38,
- [0][1][RTW89_ETSI][104] = 127,
- [0][1][RTW89_FCC][105] = -38,
- [0][1][RTW89_ETSI][105] = 127,
- [0][1][RTW89_FCC][107] = -34,
- [0][1][RTW89_ETSI][107] = 127,
- [0][1][RTW89_FCC][109] = -34,
- [0][1][RTW89_ETSI][109] = 127,
- [0][1][RTW89_FCC][111] = 127,
- [0][1][RTW89_ETSI][111] = 127,
- [0][1][RTW89_FCC][113] = 127,
- [0][1][RTW89_ETSI][113] = 127,
- [0][1][RTW89_FCC][115] = 127,
- [0][1][RTW89_ETSI][115] = 127,
- [0][1][RTW89_FCC][117] = 127,
- [0][1][RTW89_ETSI][117] = 127,
- [0][1][RTW89_FCC][119] = 127,
- [0][1][RTW89_ETSI][119] = 127,
- [1][0][RTW89_FCC][0] = -4,
- [1][0][RTW89_ETSI][0] = 46,
- [1][0][RTW89_FCC][2] = -4,
- [1][0][RTW89_ETSI][2] = 46,
- [1][0][RTW89_FCC][4] = -4,
- [1][0][RTW89_ETSI][4] = 46,
- [1][0][RTW89_FCC][6] = -4,
- [1][0][RTW89_ETSI][6] = 46,
- [1][0][RTW89_FCC][8] = -4,
- [1][0][RTW89_ETSI][8] = 46,
- [1][0][RTW89_FCC][10] = -4,
- [1][0][RTW89_ETSI][10] = 46,
- [1][0][RTW89_FCC][12] = -4,
- [1][0][RTW89_ETSI][12] = 46,
- [1][0][RTW89_FCC][14] = -4,
- [1][0][RTW89_ETSI][14] = 46,
- [1][0][RTW89_FCC][15] = -4,
- [1][0][RTW89_ETSI][15] = 46,
- [1][0][RTW89_FCC][17] = -4,
- [1][0][RTW89_ETSI][17] = 46,
- [1][0][RTW89_FCC][19] = -4,
- [1][0][RTW89_ETSI][19] = 46,
- [1][0][RTW89_FCC][21] = -4,
- [1][0][RTW89_ETSI][21] = 46,
- [1][0][RTW89_FCC][23] = -4,
- [1][0][RTW89_ETSI][23] = 46,
- [1][0][RTW89_FCC][25] = -4,
- [1][0][RTW89_ETSI][25] = 46,
- [1][0][RTW89_FCC][27] = -4,
- [1][0][RTW89_ETSI][27] = 46,
- [1][0][RTW89_FCC][29] = -4,
- [1][0][RTW89_ETSI][29] = 46,
- [1][0][RTW89_FCC][30] = -4,
- [1][0][RTW89_ETSI][30] = 46,
- [1][0][RTW89_FCC][32] = -4,
- [1][0][RTW89_ETSI][32] = 46,
- [1][0][RTW89_FCC][34] = -4,
- [1][0][RTW89_ETSI][34] = 46,
- [1][0][RTW89_FCC][36] = -4,
- [1][0][RTW89_ETSI][36] = 46,
- [1][0][RTW89_FCC][38] = -4,
- [1][0][RTW89_ETSI][38] = 46,
- [1][0][RTW89_FCC][40] = -4,
- [1][0][RTW89_ETSI][40] = 46,
- [1][0][RTW89_FCC][42] = -4,
- [1][0][RTW89_ETSI][42] = 46,
- [1][0][RTW89_FCC][44] = -4,
- [1][0][RTW89_ETSI][44] = 46,
- [1][0][RTW89_FCC][45] = -4,
- [1][0][RTW89_ETSI][45] = 127,
- [1][0][RTW89_FCC][47] = -4,
- [1][0][RTW89_ETSI][47] = 127,
- [1][0][RTW89_FCC][49] = -4,
- [1][0][RTW89_ETSI][49] = 127,
- [1][0][RTW89_FCC][51] = -4,
- [1][0][RTW89_ETSI][51] = 127,
- [1][0][RTW89_FCC][53] = -4,
- [1][0][RTW89_ETSI][53] = 127,
- [1][0][RTW89_FCC][55] = -4,
- [1][0][RTW89_ETSI][55] = 127,
- [1][0][RTW89_FCC][57] = -4,
- [1][0][RTW89_ETSI][57] = 127,
- [1][0][RTW89_FCC][59] = -4,
- [1][0][RTW89_ETSI][59] = 127,
- [1][0][RTW89_FCC][60] = -4,
- [1][0][RTW89_ETSI][60] = 127,
- [1][0][RTW89_FCC][62] = -4,
- [1][0][RTW89_ETSI][62] = 127,
- [1][0][RTW89_FCC][64] = -4,
- [1][0][RTW89_ETSI][64] = 127,
- [1][0][RTW89_FCC][66] = -4,
- [1][0][RTW89_ETSI][66] = 127,
- [1][0][RTW89_FCC][68] = -4,
- [1][0][RTW89_ETSI][68] = 127,
- [1][0][RTW89_FCC][70] = -4,
- [1][0][RTW89_ETSI][70] = 127,
- [1][0][RTW89_FCC][72] = -4,
- [1][0][RTW89_ETSI][72] = 127,
- [1][0][RTW89_FCC][74] = -4,
- [1][0][RTW89_ETSI][74] = 127,
- [1][0][RTW89_FCC][75] = -4,
- [1][0][RTW89_ETSI][75] = 127,
- [1][0][RTW89_FCC][77] = -4,
- [1][0][RTW89_ETSI][77] = 127,
- [1][0][RTW89_FCC][79] = -4,
- [1][0][RTW89_ETSI][79] = 127,
- [1][0][RTW89_FCC][81] = -4,
- [1][0][RTW89_ETSI][81] = 127,
- [1][0][RTW89_FCC][83] = -4,
- [1][0][RTW89_ETSI][83] = 127,
- [1][0][RTW89_FCC][85] = -4,
- [1][0][RTW89_ETSI][85] = 127,
- [1][0][RTW89_FCC][87] = -4,
- [1][0][RTW89_ETSI][87] = 127,
- [1][0][RTW89_FCC][89] = -4,
- [1][0][RTW89_ETSI][89] = 127,
- [1][0][RTW89_FCC][90] = -4,
- [1][0][RTW89_ETSI][90] = 127,
- [1][0][RTW89_FCC][92] = -4,
- [1][0][RTW89_ETSI][92] = 127,
- [1][0][RTW89_FCC][94] = -4,
- [1][0][RTW89_ETSI][94] = 127,
- [1][0][RTW89_FCC][96] = -4,
- [1][0][RTW89_ETSI][96] = 127,
- [1][0][RTW89_FCC][98] = -4,
- [1][0][RTW89_ETSI][98] = 127,
- [1][0][RTW89_FCC][100] = -4,
- [1][0][RTW89_ETSI][100] = 127,
- [1][0][RTW89_FCC][102] = -4,
- [1][0][RTW89_ETSI][102] = 127,
- [1][0][RTW89_FCC][104] = -4,
- [1][0][RTW89_ETSI][104] = 127,
- [1][0][RTW89_FCC][105] = -4,
- [1][0][RTW89_ETSI][105] = 127,
- [1][0][RTW89_FCC][107] = 0,
- [1][0][RTW89_ETSI][107] = 127,
- [1][0][RTW89_FCC][109] = 2,
- [1][0][RTW89_ETSI][109] = 127,
- [1][0][RTW89_FCC][111] = 127,
- [1][0][RTW89_ETSI][111] = 127,
- [1][0][RTW89_FCC][113] = 127,
- [1][0][RTW89_ETSI][113] = 127,
- [1][0][RTW89_FCC][115] = 127,
- [1][0][RTW89_ETSI][115] = 127,
- [1][0][RTW89_FCC][117] = 127,
- [1][0][RTW89_ETSI][117] = 127,
- [1][0][RTW89_FCC][119] = 127,
- [1][0][RTW89_ETSI][119] = 127,
- [1][1][RTW89_FCC][0] = -26,
- [1][1][RTW89_ETSI][0] = 32,
- [1][1][RTW89_FCC][2] = -28,
- [1][1][RTW89_ETSI][2] = 32,
- [1][1][RTW89_FCC][4] = -28,
- [1][1][RTW89_ETSI][4] = 32,
- [1][1][RTW89_FCC][6] = -28,
- [1][1][RTW89_ETSI][6] = 32,
- [1][1][RTW89_FCC][8] = -28,
- [1][1][RTW89_ETSI][8] = 32,
- [1][1][RTW89_FCC][10] = -28,
- [1][1][RTW89_ETSI][10] = 32,
- [1][1][RTW89_FCC][12] = -28,
- [1][1][RTW89_ETSI][12] = 32,
- [1][1][RTW89_FCC][14] = -28,
- [1][1][RTW89_ETSI][14] = 32,
- [1][1][RTW89_FCC][15] = -28,
- [1][1][RTW89_ETSI][15] = 32,
- [1][1][RTW89_FCC][17] = -28,
- [1][1][RTW89_ETSI][17] = 32,
- [1][1][RTW89_FCC][19] = -28,
- [1][1][RTW89_ETSI][19] = 32,
- [1][1][RTW89_FCC][21] = -28,
- [1][1][RTW89_ETSI][21] = 32,
- [1][1][RTW89_FCC][23] = -28,
- [1][1][RTW89_ETSI][23] = 32,
- [1][1][RTW89_FCC][25] = -28,
- [1][1][RTW89_ETSI][25] = 32,
- [1][1][RTW89_FCC][27] = -28,
- [1][1][RTW89_ETSI][27] = 32,
- [1][1][RTW89_FCC][29] = -28,
- [1][1][RTW89_ETSI][29] = 32,
- [1][1][RTW89_FCC][30] = -28,
- [1][1][RTW89_ETSI][30] = 32,
- [1][1][RTW89_FCC][32] = -28,
- [1][1][RTW89_ETSI][32] = 32,
- [1][1][RTW89_FCC][34] = -28,
- [1][1][RTW89_ETSI][34] = 32,
- [1][1][RTW89_FCC][36] = -28,
- [1][1][RTW89_ETSI][36] = 32,
- [1][1][RTW89_FCC][38] = -28,
- [1][1][RTW89_ETSI][38] = 32,
- [1][1][RTW89_FCC][40] = -28,
- [1][1][RTW89_ETSI][40] = 32,
- [1][1][RTW89_FCC][42] = -28,
- [1][1][RTW89_ETSI][42] = 32,
- [1][1][RTW89_FCC][44] = -28,
- [1][1][RTW89_ETSI][44] = 34,
- [1][1][RTW89_FCC][45] = -26,
- [1][1][RTW89_ETSI][45] = 127,
- [1][1][RTW89_FCC][47] = -28,
- [1][1][RTW89_ETSI][47] = 127,
- [1][1][RTW89_FCC][49] = -28,
- [1][1][RTW89_ETSI][49] = 127,
- [1][1][RTW89_FCC][51] = -28,
- [1][1][RTW89_ETSI][51] = 127,
- [1][1][RTW89_FCC][53] = -26,
- [1][1][RTW89_ETSI][53] = 127,
- [1][1][RTW89_FCC][55] = -28,
- [1][1][RTW89_ETSI][55] = 127,
- [1][1][RTW89_FCC][57] = -28,
- [1][1][RTW89_ETSI][57] = 127,
- [1][1][RTW89_FCC][59] = -28,
- [1][1][RTW89_ETSI][59] = 127,
- [1][1][RTW89_FCC][60] = -28,
- [1][1][RTW89_ETSI][60] = 127,
- [1][1][RTW89_FCC][62] = -28,
- [1][1][RTW89_ETSI][62] = 127,
- [1][1][RTW89_FCC][64] = -28,
- [1][1][RTW89_ETSI][64] = 127,
- [1][1][RTW89_FCC][66] = -28,
- [1][1][RTW89_ETSI][66] = 127,
- [1][1][RTW89_FCC][68] = -28,
- [1][1][RTW89_ETSI][68] = 127,
- [1][1][RTW89_FCC][70] = -26,
- [1][1][RTW89_ETSI][70] = 127,
- [1][1][RTW89_FCC][72] = -28,
- [1][1][RTW89_ETSI][72] = 127,
- [1][1][RTW89_FCC][74] = -28,
- [1][1][RTW89_ETSI][74] = 127,
- [1][1][RTW89_FCC][75] = -28,
- [1][1][RTW89_ETSI][75] = 127,
- [1][1][RTW89_FCC][77] = -28,
- [1][1][RTW89_ETSI][77] = 127,
- [1][1][RTW89_FCC][79] = -28,
- [1][1][RTW89_ETSI][79] = 127,
- [1][1][RTW89_FCC][81] = -28,
- [1][1][RTW89_ETSI][81] = 127,
- [1][1][RTW89_FCC][83] = -28,
- [1][1][RTW89_ETSI][83] = 127,
- [1][1][RTW89_FCC][85] = -28,
- [1][1][RTW89_ETSI][85] = 127,
- [1][1][RTW89_FCC][87] = -28,
- [1][1][RTW89_ETSI][87] = 127,
- [1][1][RTW89_FCC][89] = -26,
- [1][1][RTW89_ETSI][89] = 127,
- [1][1][RTW89_FCC][90] = -26,
- [1][1][RTW89_ETSI][90] = 127,
- [1][1][RTW89_FCC][92] = -26,
- [1][1][RTW89_ETSI][92] = 127,
- [1][1][RTW89_FCC][94] = -26,
- [1][1][RTW89_ETSI][94] = 127,
- [1][1][RTW89_FCC][96] = -26,
- [1][1][RTW89_ETSI][96] = 127,
- [1][1][RTW89_FCC][98] = -26,
- [1][1][RTW89_ETSI][98] = 127,
- [1][1][RTW89_FCC][100] = -26,
- [1][1][RTW89_ETSI][100] = 127,
- [1][1][RTW89_FCC][102] = -26,
- [1][1][RTW89_ETSI][102] = 127,
- [1][1][RTW89_FCC][104] = -26,
- [1][1][RTW89_ETSI][104] = 127,
- [1][1][RTW89_FCC][105] = -26,
- [1][1][RTW89_ETSI][105] = 127,
- [1][1][RTW89_FCC][107] = -22,
- [1][1][RTW89_ETSI][107] = 127,
- [1][1][RTW89_FCC][109] = -22,
- [1][1][RTW89_ETSI][109] = 127,
- [1][1][RTW89_FCC][111] = 127,
- [1][1][RTW89_ETSI][111] = 127,
- [1][1][RTW89_FCC][113] = 127,
- [1][1][RTW89_ETSI][113] = 127,
- [1][1][RTW89_FCC][115] = 127,
- [1][1][RTW89_ETSI][115] = 127,
- [1][1][RTW89_FCC][117] = 127,
- [1][1][RTW89_ETSI][117] = 127,
- [1][1][RTW89_FCC][119] = 127,
- [1][1][RTW89_ETSI][119] = 127,
- [2][0][RTW89_FCC][0] = 8,
- [2][0][RTW89_ETSI][0] = 56,
- [2][0][RTW89_FCC][2] = 8,
- [2][0][RTW89_ETSI][2] = 56,
- [2][0][RTW89_FCC][4] = 8,
- [2][0][RTW89_ETSI][4] = 56,
- [2][0][RTW89_FCC][6] = 8,
- [2][0][RTW89_ETSI][6] = 56,
- [2][0][RTW89_FCC][8] = 8,
- [2][0][RTW89_ETSI][8] = 56,
- [2][0][RTW89_FCC][10] = 8,
- [2][0][RTW89_ETSI][10] = 56,
- [2][0][RTW89_FCC][12] = 8,
- [2][0][RTW89_ETSI][12] = 56,
- [2][0][RTW89_FCC][14] = 8,
- [2][0][RTW89_ETSI][14] = 56,
- [2][0][RTW89_FCC][15] = 8,
- [2][0][RTW89_ETSI][15] = 56,
- [2][0][RTW89_FCC][17] = 8,
- [2][0][RTW89_ETSI][17] = 56,
- [2][0][RTW89_FCC][19] = 8,
- [2][0][RTW89_ETSI][19] = 56,
- [2][0][RTW89_FCC][21] = 8,
- [2][0][RTW89_ETSI][21] = 56,
- [2][0][RTW89_FCC][23] = 8,
- [2][0][RTW89_ETSI][23] = 56,
- [2][0][RTW89_FCC][25] = 8,
- [2][0][RTW89_ETSI][25] = 56,
- [2][0][RTW89_FCC][27] = 8,
- [2][0][RTW89_ETSI][27] = 56,
- [2][0][RTW89_FCC][29] = 8,
- [2][0][RTW89_ETSI][29] = 56,
- [2][0][RTW89_FCC][30] = 8,
- [2][0][RTW89_ETSI][30] = 56,
- [2][0][RTW89_FCC][32] = 8,
- [2][0][RTW89_ETSI][32] = 56,
- [2][0][RTW89_FCC][34] = 8,
- [2][0][RTW89_ETSI][34] = 56,
- [2][0][RTW89_FCC][36] = 8,
- [2][0][RTW89_ETSI][36] = 56,
- [2][0][RTW89_FCC][38] = 8,
- [2][0][RTW89_ETSI][38] = 56,
- [2][0][RTW89_FCC][40] = 8,
- [2][0][RTW89_ETSI][40] = 56,
- [2][0][RTW89_FCC][42] = 8,
- [2][0][RTW89_ETSI][42] = 56,
- [2][0][RTW89_FCC][44] = 8,
- [2][0][RTW89_ETSI][44] = 56,
- [2][0][RTW89_FCC][45] = 8,
- [2][0][RTW89_ETSI][45] = 127,
- [2][0][RTW89_FCC][47] = 8,
- [2][0][RTW89_ETSI][47] = 127,
- [2][0][RTW89_FCC][49] = 8,
- [2][0][RTW89_ETSI][49] = 127,
- [2][0][RTW89_FCC][51] = 8,
- [2][0][RTW89_ETSI][51] = 127,
- [2][0][RTW89_FCC][53] = 8,
- [2][0][RTW89_ETSI][53] = 127,
- [2][0][RTW89_FCC][55] = 8,
- [2][0][RTW89_ETSI][55] = 127,
- [2][0][RTW89_FCC][57] = 8,
- [2][0][RTW89_ETSI][57] = 127,
- [2][0][RTW89_FCC][59] = 8,
- [2][0][RTW89_ETSI][59] = 127,
- [2][0][RTW89_FCC][60] = 8,
- [2][0][RTW89_ETSI][60] = 127,
- [2][0][RTW89_FCC][62] = 8,
- [2][0][RTW89_ETSI][62] = 127,
- [2][0][RTW89_FCC][64] = 8,
- [2][0][RTW89_ETSI][64] = 127,
- [2][0][RTW89_FCC][66] = 8,
- [2][0][RTW89_ETSI][66] = 127,
- [2][0][RTW89_FCC][68] = 8,
- [2][0][RTW89_ETSI][68] = 127,
- [2][0][RTW89_FCC][70] = 8,
- [2][0][RTW89_ETSI][70] = 127,
- [2][0][RTW89_FCC][72] = 8,
- [2][0][RTW89_ETSI][72] = 127,
- [2][0][RTW89_FCC][74] = 8,
- [2][0][RTW89_ETSI][74] = 127,
- [2][0][RTW89_FCC][75] = 8,
- [2][0][RTW89_ETSI][75] = 127,
- [2][0][RTW89_FCC][77] = 8,
- [2][0][RTW89_ETSI][77] = 127,
- [2][0][RTW89_FCC][79] = 8,
- [2][0][RTW89_ETSI][79] = 127,
- [2][0][RTW89_FCC][81] = 8,
- [2][0][RTW89_ETSI][81] = 127,
- [2][0][RTW89_FCC][83] = 8,
- [2][0][RTW89_ETSI][83] = 127,
- [2][0][RTW89_FCC][85] = 8,
- [2][0][RTW89_ETSI][85] = 127,
- [2][0][RTW89_FCC][87] = 8,
- [2][0][RTW89_ETSI][87] = 127,
- [2][0][RTW89_FCC][89] = 8,
- [2][0][RTW89_ETSI][89] = 127,
- [2][0][RTW89_FCC][90] = 8,
- [2][0][RTW89_ETSI][90] = 127,
- [2][0][RTW89_FCC][92] = 8,
- [2][0][RTW89_ETSI][92] = 127,
- [2][0][RTW89_FCC][94] = 8,
- [2][0][RTW89_ETSI][94] = 127,
- [2][0][RTW89_FCC][96] = 8,
- [2][0][RTW89_ETSI][96] = 127,
- [2][0][RTW89_FCC][98] = 8,
- [2][0][RTW89_ETSI][98] = 127,
- [2][0][RTW89_FCC][100] = 8,
- [2][0][RTW89_ETSI][100] = 127,
- [2][0][RTW89_FCC][102] = 8,
- [2][0][RTW89_ETSI][102] = 127,
- [2][0][RTW89_FCC][104] = 8,
- [2][0][RTW89_ETSI][104] = 127,
- [2][0][RTW89_FCC][105] = 8,
- [2][0][RTW89_ETSI][105] = 127,
- [2][0][RTW89_FCC][107] = 10,
- [2][0][RTW89_ETSI][107] = 127,
- [2][0][RTW89_FCC][109] = 12,
- [2][0][RTW89_ETSI][109] = 127,
- [2][0][RTW89_FCC][111] = 127,
- [2][0][RTW89_ETSI][111] = 127,
- [2][0][RTW89_FCC][113] = 127,
- [2][0][RTW89_ETSI][113] = 127,
- [2][0][RTW89_FCC][115] = 127,
- [2][0][RTW89_ETSI][115] = 127,
- [2][0][RTW89_FCC][117] = 127,
- [2][0][RTW89_ETSI][117] = 127,
- [2][0][RTW89_FCC][119] = 127,
- [2][0][RTW89_ETSI][119] = 127,
- [2][1][RTW89_FCC][0] = -16,
- [2][1][RTW89_ETSI][0] = 44,
- [2][1][RTW89_FCC][2] = -16,
- [2][1][RTW89_ETSI][2] = 44,
- [2][1][RTW89_FCC][4] = -16,
- [2][1][RTW89_ETSI][4] = 44,
- [2][1][RTW89_FCC][6] = -16,
- [2][1][RTW89_ETSI][6] = 44,
- [2][1][RTW89_FCC][8] = -16,
- [2][1][RTW89_ETSI][8] = 44,
- [2][1][RTW89_FCC][10] = -16,
- [2][1][RTW89_ETSI][10] = 44,
- [2][1][RTW89_FCC][12] = -16,
- [2][1][RTW89_ETSI][12] = 44,
- [2][1][RTW89_FCC][14] = -16,
- [2][1][RTW89_ETSI][14] = 44,
- [2][1][RTW89_FCC][15] = -16,
- [2][1][RTW89_ETSI][15] = 44,
- [2][1][RTW89_FCC][17] = -16,
- [2][1][RTW89_ETSI][17] = 44,
- [2][1][RTW89_FCC][19] = -16,
- [2][1][RTW89_ETSI][19] = 44,
- [2][1][RTW89_FCC][21] = -16,
- [2][1][RTW89_ETSI][21] = 44,
- [2][1][RTW89_FCC][23] = -16,
- [2][1][RTW89_ETSI][23] = 44,
- [2][1][RTW89_FCC][25] = -16,
- [2][1][RTW89_ETSI][25] = 44,
- [2][1][RTW89_FCC][27] = -16,
- [2][1][RTW89_ETSI][27] = 44,
- [2][1][RTW89_FCC][29] = -16,
- [2][1][RTW89_ETSI][29] = 44,
- [2][1][RTW89_FCC][30] = -16,
- [2][1][RTW89_ETSI][30] = 44,
- [2][1][RTW89_FCC][32] = -16,
- [2][1][RTW89_ETSI][32] = 44,
- [2][1][RTW89_FCC][34] = -16,
- [2][1][RTW89_ETSI][34] = 44,
- [2][1][RTW89_FCC][36] = -16,
- [2][1][RTW89_ETSI][36] = 44,
- [2][1][RTW89_FCC][38] = -16,
- [2][1][RTW89_ETSI][38] = 44,
- [2][1][RTW89_FCC][40] = -16,
- [2][1][RTW89_ETSI][40] = 44,
- [2][1][RTW89_FCC][42] = -16,
- [2][1][RTW89_ETSI][42] = 44,
- [2][1][RTW89_FCC][44] = -16,
- [2][1][RTW89_ETSI][44] = 44,
- [2][1][RTW89_FCC][45] = -16,
- [2][1][RTW89_ETSI][45] = 127,
- [2][1][RTW89_FCC][47] = -16,
- [2][1][RTW89_ETSI][47] = 127,
- [2][1][RTW89_FCC][49] = -16,
- [2][1][RTW89_ETSI][49] = 127,
- [2][1][RTW89_FCC][51] = -16,
- [2][1][RTW89_ETSI][51] = 127,
- [2][1][RTW89_FCC][53] = -16,
- [2][1][RTW89_ETSI][53] = 127,
- [2][1][RTW89_FCC][55] = -16,
- [2][1][RTW89_ETSI][55] = 127,
- [2][1][RTW89_FCC][57] = -16,
- [2][1][RTW89_ETSI][57] = 127,
- [2][1][RTW89_FCC][59] = -16,
- [2][1][RTW89_ETSI][59] = 127,
- [2][1][RTW89_FCC][60] = -16,
- [2][1][RTW89_ETSI][60] = 127,
- [2][1][RTW89_FCC][62] = -16,
- [2][1][RTW89_ETSI][62] = 127,
- [2][1][RTW89_FCC][64] = -16,
- [2][1][RTW89_ETSI][64] = 127,
- [2][1][RTW89_FCC][66] = -16,
- [2][1][RTW89_ETSI][66] = 127,
- [2][1][RTW89_FCC][68] = -16,
- [2][1][RTW89_ETSI][68] = 127,
- [2][1][RTW89_FCC][70] = -16,
- [2][1][RTW89_ETSI][70] = 127,
- [2][1][RTW89_FCC][72] = -16,
- [2][1][RTW89_ETSI][72] = 127,
- [2][1][RTW89_FCC][74] = -16,
- [2][1][RTW89_ETSI][74] = 127,
- [2][1][RTW89_FCC][75] = -16,
- [2][1][RTW89_ETSI][75] = 127,
- [2][1][RTW89_FCC][77] = -16,
- [2][1][RTW89_ETSI][77] = 127,
- [2][1][RTW89_FCC][79] = -16,
- [2][1][RTW89_ETSI][79] = 127,
- [2][1][RTW89_FCC][81] = -16,
- [2][1][RTW89_ETSI][81] = 127,
- [2][1][RTW89_FCC][83] = -16,
- [2][1][RTW89_ETSI][83] = 127,
- [2][1][RTW89_FCC][85] = -18,
- [2][1][RTW89_ETSI][85] = 127,
- [2][1][RTW89_FCC][87] = -16,
- [2][1][RTW89_ETSI][87] = 127,
- [2][1][RTW89_FCC][89] = -16,
- [2][1][RTW89_ETSI][89] = 127,
- [2][1][RTW89_FCC][90] = -16,
- [2][1][RTW89_ETSI][90] = 127,
- [2][1][RTW89_FCC][92] = -16,
- [2][1][RTW89_ETSI][92] = 127,
- [2][1][RTW89_FCC][94] = -16,
- [2][1][RTW89_ETSI][94] = 127,
- [2][1][RTW89_FCC][96] = -16,
- [2][1][RTW89_ETSI][96] = 127,
- [2][1][RTW89_FCC][98] = -16,
- [2][1][RTW89_ETSI][98] = 127,
- [2][1][RTW89_FCC][100] = -16,
- [2][1][RTW89_ETSI][100] = 127,
- [2][1][RTW89_FCC][102] = -16,
- [2][1][RTW89_ETSI][102] = 127,
- [2][1][RTW89_FCC][104] = -16,
- [2][1][RTW89_ETSI][104] = 127,
- [2][1][RTW89_FCC][105] = -16,
- [2][1][RTW89_ETSI][105] = 127,
- [2][1][RTW89_FCC][107] = -12,
- [2][1][RTW89_ETSI][107] = 127,
- [2][1][RTW89_FCC][109] = -10,
- [2][1][RTW89_ETSI][109] = 127,
- [2][1][RTW89_FCC][111] = 127,
- [2][1][RTW89_ETSI][111] = 127,
- [2][1][RTW89_FCC][113] = 127,
- [2][1][RTW89_ETSI][113] = 127,
- [2][1][RTW89_FCC][115] = 127,
- [2][1][RTW89_ETSI][115] = 127,
- [2][1][RTW89_FCC][117] = 127,
- [2][1][RTW89_ETSI][117] = 127,
- [2][1][RTW89_FCC][119] = 127,
- [2][1][RTW89_ETSI][119] = 127,
+ [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
+ [RTW89_6G_CH_NUM] = {
+ [0][0][RTW89_WW][0][0] = -16,
+ [0][0][RTW89_WW][1][0] = -16,
+ [0][0][RTW89_WW][2][0] = 44,
+ [0][0][RTW89_WW][0][2] = -18,
+ [0][0][RTW89_WW][1][2] = -18,
+ [0][0][RTW89_WW][2][2] = 44,
+ [0][0][RTW89_WW][0][4] = -18,
+ [0][0][RTW89_WW][1][4] = -18,
+ [0][0][RTW89_WW][2][4] = 44,
+ [0][0][RTW89_WW][0][6] = -18,
+ [0][0][RTW89_WW][1][6] = -18,
+ [0][0][RTW89_WW][2][6] = 44,
+ [0][0][RTW89_WW][0][8] = -18,
+ [0][0][RTW89_WW][1][8] = -18,
+ [0][0][RTW89_WW][2][8] = 44,
+ [0][0][RTW89_WW][0][10] = -18,
+ [0][0][RTW89_WW][1][10] = -18,
+ [0][0][RTW89_WW][2][10] = 44,
+ [0][0][RTW89_WW][0][12] = -18,
+ [0][0][RTW89_WW][1][12] = -18,
+ [0][0][RTW89_WW][2][12] = 44,
+ [0][0][RTW89_WW][0][14] = -18,
+ [0][0][RTW89_WW][1][14] = -18,
+ [0][0][RTW89_WW][2][14] = 44,
+ [0][0][RTW89_WW][0][15] = -18,
+ [0][0][RTW89_WW][1][15] = -18,
+ [0][0][RTW89_WW][2][15] = 44,
+ [0][0][RTW89_WW][0][17] = -18,
+ [0][0][RTW89_WW][1][17] = -18,
+ [0][0][RTW89_WW][2][17] = 44,
+ [0][0][RTW89_WW][0][19] = -18,
+ [0][0][RTW89_WW][1][19] = -18,
+ [0][0][RTW89_WW][2][19] = 44,
+ [0][0][RTW89_WW][0][21] = -18,
+ [0][0][RTW89_WW][1][21] = -18,
+ [0][0][RTW89_WW][2][21] = 44,
+ [0][0][RTW89_WW][0][23] = -18,
+ [0][0][RTW89_WW][1][23] = -18,
+ [0][0][RTW89_WW][2][23] = 54,
+ [0][0][RTW89_WW][0][25] = -18,
+ [0][0][RTW89_WW][1][25] = -18,
+ [0][0][RTW89_WW][2][25] = 54,
+ [0][0][RTW89_WW][0][27] = -18,
+ [0][0][RTW89_WW][1][27] = -18,
+ [0][0][RTW89_WW][2][27] = 54,
+ [0][0][RTW89_WW][0][29] = -18,
+ [0][0][RTW89_WW][1][29] = -18,
+ [0][0][RTW89_WW][2][29] = 54,
+ [0][0][RTW89_WW][0][30] = -18,
+ [0][0][RTW89_WW][1][30] = -18,
+ [0][0][RTW89_WW][2][30] = 54,
+ [0][0][RTW89_WW][0][32] = -18,
+ [0][0][RTW89_WW][1][32] = -18,
+ [0][0][RTW89_WW][2][32] = 54,
+ [0][0][RTW89_WW][0][34] = -18,
+ [0][0][RTW89_WW][1][34] = -18,
+ [0][0][RTW89_WW][2][34] = 54,
+ [0][0][RTW89_WW][0][36] = -18,
+ [0][0][RTW89_WW][1][36] = -18,
+ [0][0][RTW89_WW][2][36] = 54,
+ [0][0][RTW89_WW][0][38] = -18,
+ [0][0][RTW89_WW][1][38] = -18,
+ [0][0][RTW89_WW][2][38] = 54,
+ [0][0][RTW89_WW][0][40] = -18,
+ [0][0][RTW89_WW][1][40] = -18,
+ [0][0][RTW89_WW][2][40] = 54,
+ [0][0][RTW89_WW][0][42] = -18,
+ [0][0][RTW89_WW][1][42] = -18,
+ [0][0][RTW89_WW][2][42] = 54,
+ [0][0][RTW89_WW][0][44] = -16,
+ [0][0][RTW89_WW][1][44] = -16,
+ [0][0][RTW89_WW][2][44] = 56,
+ [0][0][RTW89_WW][0][45] = -16,
+ [0][0][RTW89_WW][1][45] = -16,
+ [0][0][RTW89_WW][2][45] = 0,
+ [0][0][RTW89_WW][0][47] = -18,
+ [0][0][RTW89_WW][1][47] = -18,
+ [0][0][RTW89_WW][2][47] = 0,
+ [0][0][RTW89_WW][0][49] = -18,
+ [0][0][RTW89_WW][1][49] = -18,
+ [0][0][RTW89_WW][2][49] = 0,
+ [0][0][RTW89_WW][0][51] = -18,
+ [0][0][RTW89_WW][1][51] = -18,
+ [0][0][RTW89_WW][2][51] = 0,
+ [0][0][RTW89_WW][0][53] = -16,
+ [0][0][RTW89_WW][1][53] = -16,
+ [0][0][RTW89_WW][2][53] = 0,
+ [0][0][RTW89_WW][0][55] = -18,
+ [0][0][RTW89_WW][1][55] = -18,
+ [0][0][RTW89_WW][2][55] = 56,
+ [0][0][RTW89_WW][0][57] = -18,
+ [0][0][RTW89_WW][1][57] = -18,
+ [0][0][RTW89_WW][2][57] = 56,
+ [0][0][RTW89_WW][0][59] = -18,
+ [0][0][RTW89_WW][1][59] = -18,
+ [0][0][RTW89_WW][2][59] = 56,
+ [0][0][RTW89_WW][0][60] = -18,
+ [0][0][RTW89_WW][1][60] = -18,
+ [0][0][RTW89_WW][2][60] = 56,
+ [0][0][RTW89_WW][0][62] = -18,
+ [0][0][RTW89_WW][1][62] = -18,
+ [0][0][RTW89_WW][2][62] = 56,
+ [0][0][RTW89_WW][0][64] = -18,
+ [0][0][RTW89_WW][1][64] = -18,
+ [0][0][RTW89_WW][2][64] = 56,
+ [0][0][RTW89_WW][0][66] = -18,
+ [0][0][RTW89_WW][1][66] = -18,
+ [0][0][RTW89_WW][2][66] = 56,
+ [0][0][RTW89_WW][0][68] = -18,
+ [0][0][RTW89_WW][1][68] = -18,
+ [0][0][RTW89_WW][2][68] = 56,
+ [0][0][RTW89_WW][0][70] = -16,
+ [0][0][RTW89_WW][1][70] = -16,
+ [0][0][RTW89_WW][2][70] = 56,
+ [0][0][RTW89_WW][0][72] = -18,
+ [0][0][RTW89_WW][1][72] = -18,
+ [0][0][RTW89_WW][2][72] = 56,
+ [0][0][RTW89_WW][0][74] = -18,
+ [0][0][RTW89_WW][1][74] = -18,
+ [0][0][RTW89_WW][2][74] = 56,
+ [0][0][RTW89_WW][0][75] = -18,
+ [0][0][RTW89_WW][1][75] = -18,
+ [0][0][RTW89_WW][2][75] = 56,
+ [0][0][RTW89_WW][0][77] = -18,
+ [0][0][RTW89_WW][1][77] = -18,
+ [0][0][RTW89_WW][2][77] = 56,
+ [0][0][RTW89_WW][0][79] = -18,
+ [0][0][RTW89_WW][1][79] = -18,
+ [0][0][RTW89_WW][2][79] = 56,
+ [0][0][RTW89_WW][0][81] = -18,
+ [0][0][RTW89_WW][1][81] = -18,
+ [0][0][RTW89_WW][2][81] = 56,
+ [0][0][RTW89_WW][0][83] = -18,
+ [0][0][RTW89_WW][1][83] = -18,
+ [0][0][RTW89_WW][2][83] = 56,
+ [0][0][RTW89_WW][0][85] = -18,
+ [0][0][RTW89_WW][1][85] = -18,
+ [0][0][RTW89_WW][2][85] = 56,
+ [0][0][RTW89_WW][0][87] = -16,
+ [0][0][RTW89_WW][1][87] = -16,
+ [0][0][RTW89_WW][2][87] = 0,
+ [0][0][RTW89_WW][0][89] = -16,
+ [0][0][RTW89_WW][1][89] = -16,
+ [0][0][RTW89_WW][2][89] = 0,
+ [0][0][RTW89_WW][0][90] = -16,
+ [0][0][RTW89_WW][1][90] = -16,
+ [0][0][RTW89_WW][2][90] = 0,
+ [0][0][RTW89_WW][0][92] = -16,
+ [0][0][RTW89_WW][1][92] = -16,
+ [0][0][RTW89_WW][2][92] = 0,
+ [0][0][RTW89_WW][0][94] = -16,
+ [0][0][RTW89_WW][1][94] = -16,
+ [0][0][RTW89_WW][2][94] = 0,
+ [0][0][RTW89_WW][0][96] = -16,
+ [0][0][RTW89_WW][1][96] = -16,
+ [0][0][RTW89_WW][2][96] = 0,
+ [0][0][RTW89_WW][0][98] = -16,
+ [0][0][RTW89_WW][1][98] = -16,
+ [0][0][RTW89_WW][2][98] = 0,
+ [0][0][RTW89_WW][0][100] = -16,
+ [0][0][RTW89_WW][1][100] = -16,
+ [0][0][RTW89_WW][2][100] = 0,
+ [0][0][RTW89_WW][0][102] = -16,
+ [0][0][RTW89_WW][1][102] = -16,
+ [0][0][RTW89_WW][2][102] = 0,
+ [0][0][RTW89_WW][0][104] = -16,
+ [0][0][RTW89_WW][1][104] = -16,
+ [0][0][RTW89_WW][2][104] = 0,
+ [0][0][RTW89_WW][0][105] = -16,
+ [0][0][RTW89_WW][1][105] = -16,
+ [0][0][RTW89_WW][2][105] = 0,
+ [0][0][RTW89_WW][0][107] = -12,
+ [0][0][RTW89_WW][1][107] = -12,
+ [0][0][RTW89_WW][2][107] = 0,
+ [0][0][RTW89_WW][0][109] = -12,
+ [0][0][RTW89_WW][1][109] = -12,
+ [0][0][RTW89_WW][2][109] = 0,
+ [0][0][RTW89_WW][0][111] = 0,
+ [0][0][RTW89_WW][1][111] = 0,
+ [0][0][RTW89_WW][2][111] = 0,
+ [0][0][RTW89_WW][0][113] = 0,
+ [0][0][RTW89_WW][1][113] = 0,
+ [0][0][RTW89_WW][2][113] = 0,
+ [0][0][RTW89_WW][0][115] = 0,
+ [0][0][RTW89_WW][1][115] = 0,
+ [0][0][RTW89_WW][2][115] = 0,
+ [0][0][RTW89_WW][0][117] = 0,
+ [0][0][RTW89_WW][1][117] = 0,
+ [0][0][RTW89_WW][2][117] = 0,
+ [0][0][RTW89_WW][0][119] = 0,
+ [0][0][RTW89_WW][1][119] = 0,
+ [0][0][RTW89_WW][2][119] = 0,
+ [0][1][RTW89_WW][0][0] = -40,
+ [0][1][RTW89_WW][1][0] = -40,
+ [0][1][RTW89_WW][2][0] = 32,
+ [0][1][RTW89_WW][0][2] = -40,
+ [0][1][RTW89_WW][1][2] = -40,
+ [0][1][RTW89_WW][2][2] = 32,
+ [0][1][RTW89_WW][0][4] = -40,
+ [0][1][RTW89_WW][1][4] = -40,
+ [0][1][RTW89_WW][2][4] = 32,
+ [0][1][RTW89_WW][0][6] = -40,
+ [0][1][RTW89_WW][1][6] = -40,
+ [0][1][RTW89_WW][2][6] = 32,
+ [0][1][RTW89_WW][0][8] = -40,
+ [0][1][RTW89_WW][1][8] = -40,
+ [0][1][RTW89_WW][2][8] = 32,
+ [0][1][RTW89_WW][0][10] = -40,
+ [0][1][RTW89_WW][1][10] = -40,
+ [0][1][RTW89_WW][2][10] = 32,
+ [0][1][RTW89_WW][0][12] = -40,
+ [0][1][RTW89_WW][1][12] = -40,
+ [0][1][RTW89_WW][2][12] = 32,
+ [0][1][RTW89_WW][0][14] = -40,
+ [0][1][RTW89_WW][1][14] = -40,
+ [0][1][RTW89_WW][2][14] = 32,
+ [0][1][RTW89_WW][0][15] = -40,
+ [0][1][RTW89_WW][1][15] = -40,
+ [0][1][RTW89_WW][2][15] = 32,
+ [0][1][RTW89_WW][0][17] = -40,
+ [0][1][RTW89_WW][1][17] = -40,
+ [0][1][RTW89_WW][2][17] = 32,
+ [0][1][RTW89_WW][0][19] = -40,
+ [0][1][RTW89_WW][1][19] = -40,
+ [0][1][RTW89_WW][2][19] = 32,
+ [0][1][RTW89_WW][0][21] = -40,
+ [0][1][RTW89_WW][1][21] = -40,
+ [0][1][RTW89_WW][2][21] = 32,
+ [0][1][RTW89_WW][0][23] = -40,
+ [0][1][RTW89_WW][1][23] = -40,
+ [0][1][RTW89_WW][2][23] = 32,
+ [0][1][RTW89_WW][0][25] = -40,
+ [0][1][RTW89_WW][1][25] = -40,
+ [0][1][RTW89_WW][2][25] = 32,
+ [0][1][RTW89_WW][0][27] = -40,
+ [0][1][RTW89_WW][1][27] = -40,
+ [0][1][RTW89_WW][2][27] = 32,
+ [0][1][RTW89_WW][0][29] = -40,
+ [0][1][RTW89_WW][1][29] = -40,
+ [0][1][RTW89_WW][2][29] = 32,
+ [0][1][RTW89_WW][0][30] = -40,
+ [0][1][RTW89_WW][1][30] = -40,
+ [0][1][RTW89_WW][2][30] = 32,
+ [0][1][RTW89_WW][0][32] = -40,
+ [0][1][RTW89_WW][1][32] = -40,
+ [0][1][RTW89_WW][2][32] = 32,
+ [0][1][RTW89_WW][0][34] = -40,
+ [0][1][RTW89_WW][1][34] = -40,
+ [0][1][RTW89_WW][2][34] = 32,
+ [0][1][RTW89_WW][0][36] = -40,
+ [0][1][RTW89_WW][1][36] = -40,
+ [0][1][RTW89_WW][2][36] = 32,
+ [0][1][RTW89_WW][0][38] = -40,
+ [0][1][RTW89_WW][1][38] = -40,
+ [0][1][RTW89_WW][2][38] = 32,
+ [0][1][RTW89_WW][0][40] = -40,
+ [0][1][RTW89_WW][1][40] = -40,
+ [0][1][RTW89_WW][2][40] = 32,
+ [0][1][RTW89_WW][0][42] = -40,
+ [0][1][RTW89_WW][1][42] = -40,
+ [0][1][RTW89_WW][2][42] = 32,
+ [0][1][RTW89_WW][0][44] = -40,
+ [0][1][RTW89_WW][1][44] = -40,
+ [0][1][RTW89_WW][2][44] = 32,
+ [0][1][RTW89_WW][0][45] = -40,
+ [0][1][RTW89_WW][1][45] = -40,
+ [0][1][RTW89_WW][2][45] = 0,
+ [0][1][RTW89_WW][0][47] = -40,
+ [0][1][RTW89_WW][1][47] = -40,
+ [0][1][RTW89_WW][2][47] = 0,
+ [0][1][RTW89_WW][0][49] = -40,
+ [0][1][RTW89_WW][1][49] = -40,
+ [0][1][RTW89_WW][2][49] = 0,
+ [0][1][RTW89_WW][0][51] = -40,
+ [0][1][RTW89_WW][1][51] = -40,
+ [0][1][RTW89_WW][2][51] = 0,
+ [0][1][RTW89_WW][0][53] = -40,
+ [0][1][RTW89_WW][1][53] = -40,
+ [0][1][RTW89_WW][2][53] = 0,
+ [0][1][RTW89_WW][0][55] = -40,
+ [0][1][RTW89_WW][1][55] = -40,
+ [0][1][RTW89_WW][2][55] = 30,
+ [0][1][RTW89_WW][0][57] = -40,
+ [0][1][RTW89_WW][1][57] = -40,
+ [0][1][RTW89_WW][2][57] = 30,
+ [0][1][RTW89_WW][0][59] = -40,
+ [0][1][RTW89_WW][1][59] = -40,
+ [0][1][RTW89_WW][2][59] = 30,
+ [0][1][RTW89_WW][0][60] = -40,
+ [0][1][RTW89_WW][1][60] = -40,
+ [0][1][RTW89_WW][2][60] = 30,
+ [0][1][RTW89_WW][0][62] = -40,
+ [0][1][RTW89_WW][1][62] = -40,
+ [0][1][RTW89_WW][2][62] = 30,
+ [0][1][RTW89_WW][0][64] = -40,
+ [0][1][RTW89_WW][1][64] = -40,
+ [0][1][RTW89_WW][2][64] = 30,
+ [0][1][RTW89_WW][0][66] = -40,
+ [0][1][RTW89_WW][1][66] = -40,
+ [0][1][RTW89_WW][2][66] = 30,
+ [0][1][RTW89_WW][0][68] = -40,
+ [0][1][RTW89_WW][1][68] = -40,
+ [0][1][RTW89_WW][2][68] = 30,
+ [0][1][RTW89_WW][0][70] = -38,
+ [0][1][RTW89_WW][1][70] = -38,
+ [0][1][RTW89_WW][2][70] = 30,
+ [0][1][RTW89_WW][0][72] = -38,
+ [0][1][RTW89_WW][1][72] = -38,
+ [0][1][RTW89_WW][2][72] = 30,
+ [0][1][RTW89_WW][0][74] = -38,
+ [0][1][RTW89_WW][1][74] = -38,
+ [0][1][RTW89_WW][2][74] = 30,
+ [0][1][RTW89_WW][0][75] = -38,
+ [0][1][RTW89_WW][1][75] = -38,
+ [0][1][RTW89_WW][2][75] = 30,
+ [0][1][RTW89_WW][0][77] = -38,
+ [0][1][RTW89_WW][1][77] = -38,
+ [0][1][RTW89_WW][2][77] = 30,
+ [0][1][RTW89_WW][0][79] = -38,
+ [0][1][RTW89_WW][1][79] = -38,
+ [0][1][RTW89_WW][2][79] = 30,
+ [0][1][RTW89_WW][0][81] = -38,
+ [0][1][RTW89_WW][1][81] = -38,
+ [0][1][RTW89_WW][2][81] = 30,
+ [0][1][RTW89_WW][0][83] = -38,
+ [0][1][RTW89_WW][1][83] = -38,
+ [0][1][RTW89_WW][2][83] = 30,
+ [0][1][RTW89_WW][0][85] = -38,
+ [0][1][RTW89_WW][1][85] = -38,
+ [0][1][RTW89_WW][2][85] = 30,
+ [0][1][RTW89_WW][0][87] = -40,
+ [0][1][RTW89_WW][1][87] = -40,
+ [0][1][RTW89_WW][2][87] = 0,
+ [0][1][RTW89_WW][0][89] = -38,
+ [0][1][RTW89_WW][1][89] = -38,
+ [0][1][RTW89_WW][2][89] = 0,
+ [0][1][RTW89_WW][0][90] = -38,
+ [0][1][RTW89_WW][1][90] = -38,
+ [0][1][RTW89_WW][2][90] = 0,
+ [0][1][RTW89_WW][0][92] = -38,
+ [0][1][RTW89_WW][1][92] = -38,
+ [0][1][RTW89_WW][2][92] = 0,
+ [0][1][RTW89_WW][0][94] = -38,
+ [0][1][RTW89_WW][1][94] = -38,
+ [0][1][RTW89_WW][2][94] = 0,
+ [0][1][RTW89_WW][0][96] = -38,
+ [0][1][RTW89_WW][1][96] = -38,
+ [0][1][RTW89_WW][2][96] = 0,
+ [0][1][RTW89_WW][0][98] = -38,
+ [0][1][RTW89_WW][1][98] = -38,
+ [0][1][RTW89_WW][2][98] = 0,
+ [0][1][RTW89_WW][0][100] = -38,
+ [0][1][RTW89_WW][1][100] = -38,
+ [0][1][RTW89_WW][2][100] = 0,
+ [0][1][RTW89_WW][0][102] = -38,
+ [0][1][RTW89_WW][1][102] = -38,
+ [0][1][RTW89_WW][2][102] = 0,
+ [0][1][RTW89_WW][0][104] = -38,
+ [0][1][RTW89_WW][1][104] = -38,
+ [0][1][RTW89_WW][2][104] = 0,
+ [0][1][RTW89_WW][0][105] = -38,
+ [0][1][RTW89_WW][1][105] = -38,
+ [0][1][RTW89_WW][2][105] = 0,
+ [0][1][RTW89_WW][0][107] = -34,
+ [0][1][RTW89_WW][1][107] = -34,
+ [0][1][RTW89_WW][2][107] = 0,
+ [0][1][RTW89_WW][0][109] = -34,
+ [0][1][RTW89_WW][1][109] = -34,
+ [0][1][RTW89_WW][2][109] = 0,
+ [0][1][RTW89_WW][0][111] = 0,
+ [0][1][RTW89_WW][1][111] = 0,
+ [0][1][RTW89_WW][2][111] = 0,
+ [0][1][RTW89_WW][0][113] = 0,
+ [0][1][RTW89_WW][1][113] = 0,
+ [0][1][RTW89_WW][2][113] = 0,
+ [0][1][RTW89_WW][0][115] = 0,
+ [0][1][RTW89_WW][1][115] = 0,
+ [0][1][RTW89_WW][2][115] = 0,
+ [0][1][RTW89_WW][0][117] = 0,
+ [0][1][RTW89_WW][1][117] = 0,
+ [0][1][RTW89_WW][2][117] = 0,
+ [0][1][RTW89_WW][0][119] = 0,
+ [0][1][RTW89_WW][1][119] = 0,
+ [0][1][RTW89_WW][2][119] = 0,
+ [1][0][RTW89_WW][0][0] = -4,
+ [1][0][RTW89_WW][1][0] = -4,
+ [1][0][RTW89_WW][2][0] = 52,
+ [1][0][RTW89_WW][0][2] = -4,
+ [1][0][RTW89_WW][1][2] = -4,
+ [1][0][RTW89_WW][2][2] = 52,
+ [1][0][RTW89_WW][0][4] = -4,
+ [1][0][RTW89_WW][1][4] = -4,
+ [1][0][RTW89_WW][2][4] = 52,
+ [1][0][RTW89_WW][0][6] = -4,
+ [1][0][RTW89_WW][1][6] = -4,
+ [1][0][RTW89_WW][2][6] = 52,
+ [1][0][RTW89_WW][0][8] = -4,
+ [1][0][RTW89_WW][1][8] = -4,
+ [1][0][RTW89_WW][2][8] = 52,
+ [1][0][RTW89_WW][0][10] = -4,
+ [1][0][RTW89_WW][1][10] = -4,
+ [1][0][RTW89_WW][2][10] = 52,
+ [1][0][RTW89_WW][0][12] = -4,
+ [1][0][RTW89_WW][1][12] = -4,
+ [1][0][RTW89_WW][2][12] = 52,
+ [1][0][RTW89_WW][0][14] = -4,
+ [1][0][RTW89_WW][1][14] = -4,
+ [1][0][RTW89_WW][2][14] = 52,
+ [1][0][RTW89_WW][0][15] = -4,
+ [1][0][RTW89_WW][1][15] = -4,
+ [1][0][RTW89_WW][2][15] = 52,
+ [1][0][RTW89_WW][0][17] = -4,
+ [1][0][RTW89_WW][1][17] = -4,
+ [1][0][RTW89_WW][2][17] = 52,
+ [1][0][RTW89_WW][0][19] = -4,
+ [1][0][RTW89_WW][1][19] = -4,
+ [1][0][RTW89_WW][2][19] = 52,
+ [1][0][RTW89_WW][0][21] = -4,
+ [1][0][RTW89_WW][1][21] = -4,
+ [1][0][RTW89_WW][2][21] = 52,
+ [1][0][RTW89_WW][0][23] = -4,
+ [1][0][RTW89_WW][1][23] = -4,
+ [1][0][RTW89_WW][2][23] = 66,
+ [1][0][RTW89_WW][0][25] = -4,
+ [1][0][RTW89_WW][1][25] = -4,
+ [1][0][RTW89_WW][2][25] = 66,
+ [1][0][RTW89_WW][0][27] = -4,
+ [1][0][RTW89_WW][1][27] = -4,
+ [1][0][RTW89_WW][2][27] = 66,
+ [1][0][RTW89_WW][0][29] = -4,
+ [1][0][RTW89_WW][1][29] = -4,
+ [1][0][RTW89_WW][2][29] = 66,
+ [1][0][RTW89_WW][0][30] = -4,
+ [1][0][RTW89_WW][1][30] = -4,
+ [1][0][RTW89_WW][2][30] = 66,
+ [1][0][RTW89_WW][0][32] = -4,
+ [1][0][RTW89_WW][1][32] = -4,
+ [1][0][RTW89_WW][2][32] = 66,
+ [1][0][RTW89_WW][0][34] = -4,
+ [1][0][RTW89_WW][1][34] = -4,
+ [1][0][RTW89_WW][2][34] = 66,
+ [1][0][RTW89_WW][0][36] = -4,
+ [1][0][RTW89_WW][1][36] = -4,
+ [1][0][RTW89_WW][2][36] = 66,
+ [1][0][RTW89_WW][0][38] = -4,
+ [1][0][RTW89_WW][1][38] = -4,
+ [1][0][RTW89_WW][2][38] = 66,
+ [1][0][RTW89_WW][0][40] = -4,
+ [1][0][RTW89_WW][1][40] = -4,
+ [1][0][RTW89_WW][2][40] = 66,
+ [1][0][RTW89_WW][0][42] = -4,
+ [1][0][RTW89_WW][1][42] = -4,
+ [1][0][RTW89_WW][2][42] = 66,
+ [1][0][RTW89_WW][0][44] = -4,
+ [1][0][RTW89_WW][1][44] = -4,
+ [1][0][RTW89_WW][2][44] = 66,
+ [1][0][RTW89_WW][0][45] = -4,
+ [1][0][RTW89_WW][1][45] = -4,
+ [1][0][RTW89_WW][2][45] = 0,
+ [1][0][RTW89_WW][0][47] = -4,
+ [1][0][RTW89_WW][1][47] = -4,
+ [1][0][RTW89_WW][2][47] = 0,
+ [1][0][RTW89_WW][0][49] = -4,
+ [1][0][RTW89_WW][1][49] = -4,
+ [1][0][RTW89_WW][2][49] = 0,
+ [1][0][RTW89_WW][0][51] = -4,
+ [1][0][RTW89_WW][1][51] = -4,
+ [1][0][RTW89_WW][2][51] = 0,
+ [1][0][RTW89_WW][0][53] = -4,
+ [1][0][RTW89_WW][1][53] = -4,
+ [1][0][RTW89_WW][2][53] = 0,
+ [1][0][RTW89_WW][0][55] = -4,
+ [1][0][RTW89_WW][1][55] = -4,
+ [1][0][RTW89_WW][2][55] = 68,
+ [1][0][RTW89_WW][0][57] = -4,
+ [1][0][RTW89_WW][1][57] = -4,
+ [1][0][RTW89_WW][2][57] = 68,
+ [1][0][RTW89_WW][0][59] = -4,
+ [1][0][RTW89_WW][1][59] = -4,
+ [1][0][RTW89_WW][2][59] = 68,
+ [1][0][RTW89_WW][0][60] = -4,
+ [1][0][RTW89_WW][1][60] = -4,
+ [1][0][RTW89_WW][2][60] = 68,
+ [1][0][RTW89_WW][0][62] = -4,
+ [1][0][RTW89_WW][1][62] = -4,
+ [1][0][RTW89_WW][2][62] = 68,
+ [1][0][RTW89_WW][0][64] = -4,
+ [1][0][RTW89_WW][1][64] = -4,
+ [1][0][RTW89_WW][2][64] = 68,
+ [1][0][RTW89_WW][0][66] = -4,
+ [1][0][RTW89_WW][1][66] = -4,
+ [1][0][RTW89_WW][2][66] = 68,
+ [1][0][RTW89_WW][0][68] = -4,
+ [1][0][RTW89_WW][1][68] = -4,
+ [1][0][RTW89_WW][2][68] = 68,
+ [1][0][RTW89_WW][0][70] = -4,
+ [1][0][RTW89_WW][1][70] = -4,
+ [1][0][RTW89_WW][2][70] = 68,
+ [1][0][RTW89_WW][0][72] = -4,
+ [1][0][RTW89_WW][1][72] = -4,
+ [1][0][RTW89_WW][2][72] = 68,
+ [1][0][RTW89_WW][0][74] = -4,
+ [1][0][RTW89_WW][1][74] = -4,
+ [1][0][RTW89_WW][2][74] = 68,
+ [1][0][RTW89_WW][0][75] = -4,
+ [1][0][RTW89_WW][1][75] = -4,
+ [1][0][RTW89_WW][2][75] = 68,
+ [1][0][RTW89_WW][0][77] = -4,
+ [1][0][RTW89_WW][1][77] = -4,
+ [1][0][RTW89_WW][2][77] = 68,
+ [1][0][RTW89_WW][0][79] = -4,
+ [1][0][RTW89_WW][1][79] = -4,
+ [1][0][RTW89_WW][2][79] = 68,
+ [1][0][RTW89_WW][0][81] = -4,
+ [1][0][RTW89_WW][1][81] = -4,
+ [1][0][RTW89_WW][2][81] = 68,
+ [1][0][RTW89_WW][0][83] = -4,
+ [1][0][RTW89_WW][1][83] = -4,
+ [1][0][RTW89_WW][2][83] = 68,
+ [1][0][RTW89_WW][0][85] = -4,
+ [1][0][RTW89_WW][1][85] = -4,
+ [1][0][RTW89_WW][2][85] = 68,
+ [1][0][RTW89_WW][0][87] = -4,
+ [1][0][RTW89_WW][1][87] = -4,
+ [1][0][RTW89_WW][2][87] = 0,
+ [1][0][RTW89_WW][0][89] = -4,
+ [1][0][RTW89_WW][1][89] = -4,
+ [1][0][RTW89_WW][2][89] = 0,
+ [1][0][RTW89_WW][0][90] = -4,
+ [1][0][RTW89_WW][1][90] = -4,
+ [1][0][RTW89_WW][2][90] = 0,
+ [1][0][RTW89_WW][0][92] = -4,
+ [1][0][RTW89_WW][1][92] = -4,
+ [1][0][RTW89_WW][2][92] = 0,
+ [1][0][RTW89_WW][0][94] = -4,
+ [1][0][RTW89_WW][1][94] = -4,
+ [1][0][RTW89_WW][2][94] = 0,
+ [1][0][RTW89_WW][0][96] = -4,
+ [1][0][RTW89_WW][1][96] = -4,
+ [1][0][RTW89_WW][2][96] = 0,
+ [1][0][RTW89_WW][0][98] = -4,
+ [1][0][RTW89_WW][1][98] = -4,
+ [1][0][RTW89_WW][2][98] = 0,
+ [1][0][RTW89_WW][0][100] = -4,
+ [1][0][RTW89_WW][1][100] = -4,
+ [1][0][RTW89_WW][2][100] = 0,
+ [1][0][RTW89_WW][0][102] = -4,
+ [1][0][RTW89_WW][1][102] = -4,
+ [1][0][RTW89_WW][2][102] = 0,
+ [1][0][RTW89_WW][0][104] = -4,
+ [1][0][RTW89_WW][1][104] = -4,
+ [1][0][RTW89_WW][2][104] = 0,
+ [1][0][RTW89_WW][0][105] = -4,
+ [1][0][RTW89_WW][1][105] = -4,
+ [1][0][RTW89_WW][2][105] = 0,
+ [1][0][RTW89_WW][0][107] = -2,
+ [1][0][RTW89_WW][1][107] = -2,
+ [1][0][RTW89_WW][2][107] = 0,
+ [1][0][RTW89_WW][0][109] = 2,
+ [1][0][RTW89_WW][1][109] = 2,
+ [1][0][RTW89_WW][2][109] = 0,
+ [1][0][RTW89_WW][0][111] = 0,
+ [1][0][RTW89_WW][1][111] = 0,
+ [1][0][RTW89_WW][2][111] = 0,
+ [1][0][RTW89_WW][0][113] = 0,
+ [1][0][RTW89_WW][1][113] = 0,
+ [1][0][RTW89_WW][2][113] = 0,
+ [1][0][RTW89_WW][0][115] = 0,
+ [1][0][RTW89_WW][1][115] = 0,
+ [1][0][RTW89_WW][2][115] = 0,
+ [1][0][RTW89_WW][0][117] = 0,
+ [1][0][RTW89_WW][1][117] = 0,
+ [1][0][RTW89_WW][2][117] = 0,
+ [1][0][RTW89_WW][0][119] = 0,
+ [1][0][RTW89_WW][1][119] = 0,
+ [1][0][RTW89_WW][2][119] = 0,
+ [1][1][RTW89_WW][0][0] = -26,
+ [1][1][RTW89_WW][1][0] = -26,
+ [1][1][RTW89_WW][2][0] = 44,
+ [1][1][RTW89_WW][0][2] = -28,
+ [1][1][RTW89_WW][1][2] = -28,
+ [1][1][RTW89_WW][2][2] = 44,
+ [1][1][RTW89_WW][0][4] = -28,
+ [1][1][RTW89_WW][1][4] = -28,
+ [1][1][RTW89_WW][2][4] = 44,
+ [1][1][RTW89_WW][0][6] = -28,
+ [1][1][RTW89_WW][1][6] = -28,
+ [1][1][RTW89_WW][2][6] = 44,
+ [1][1][RTW89_WW][0][8] = -28,
+ [1][1][RTW89_WW][1][8] = -28,
+ [1][1][RTW89_WW][2][8] = 44,
+ [1][1][RTW89_WW][0][10] = -28,
+ [1][1][RTW89_WW][1][10] = -28,
+ [1][1][RTW89_WW][2][10] = 44,
+ [1][1][RTW89_WW][0][12] = -28,
+ [1][1][RTW89_WW][1][12] = -28,
+ [1][1][RTW89_WW][2][12] = 44,
+ [1][1][RTW89_WW][0][14] = -28,
+ [1][1][RTW89_WW][1][14] = -28,
+ [1][1][RTW89_WW][2][14] = 44,
+ [1][1][RTW89_WW][0][15] = -28,
+ [1][1][RTW89_WW][1][15] = -28,
+ [1][1][RTW89_WW][2][15] = 44,
+ [1][1][RTW89_WW][0][17] = -28,
+ [1][1][RTW89_WW][1][17] = -28,
+ [1][1][RTW89_WW][2][17] = 44,
+ [1][1][RTW89_WW][0][19] = -28,
+ [1][1][RTW89_WW][1][19] = -28,
+ [1][1][RTW89_WW][2][19] = 44,
+ [1][1][RTW89_WW][0][21] = -28,
+ [1][1][RTW89_WW][1][21] = -28,
+ [1][1][RTW89_WW][2][21] = 44,
+ [1][1][RTW89_WW][0][23] = -28,
+ [1][1][RTW89_WW][1][23] = -28,
+ [1][1][RTW89_WW][2][23] = 44,
+ [1][1][RTW89_WW][0][25] = -28,
+ [1][1][RTW89_WW][1][25] = -28,
+ [1][1][RTW89_WW][2][25] = 44,
+ [1][1][RTW89_WW][0][27] = -28,
+ [1][1][RTW89_WW][1][27] = -28,
+ [1][1][RTW89_WW][2][27] = 44,
+ [1][1][RTW89_WW][0][29] = -28,
+ [1][1][RTW89_WW][1][29] = -28,
+ [1][1][RTW89_WW][2][29] = 44,
+ [1][1][RTW89_WW][0][30] = -28,
+ [1][1][RTW89_WW][1][30] = -28,
+ [1][1][RTW89_WW][2][30] = 44,
+ [1][1][RTW89_WW][0][32] = -28,
+ [1][1][RTW89_WW][1][32] = -28,
+ [1][1][RTW89_WW][2][32] = 44,
+ [1][1][RTW89_WW][0][34] = -28,
+ [1][1][RTW89_WW][1][34] = -28,
+ [1][1][RTW89_WW][2][34] = 44,
+ [1][1][RTW89_WW][0][36] = -28,
+ [1][1][RTW89_WW][1][36] = -28,
+ [1][1][RTW89_WW][2][36] = 44,
+ [1][1][RTW89_WW][0][38] = -28,
+ [1][1][RTW89_WW][1][38] = -28,
+ [1][1][RTW89_WW][2][38] = 44,
+ [1][1][RTW89_WW][0][40] = -28,
+ [1][1][RTW89_WW][1][40] = -28,
+ [1][1][RTW89_WW][2][40] = 44,
+ [1][1][RTW89_WW][0][42] = -28,
+ [1][1][RTW89_WW][1][42] = -28,
+ [1][1][RTW89_WW][2][42] = 44,
+ [1][1][RTW89_WW][0][44] = -28,
+ [1][1][RTW89_WW][1][44] = -28,
+ [1][1][RTW89_WW][2][44] = 44,
+ [1][1][RTW89_WW][0][45] = -26,
+ [1][1][RTW89_WW][1][45] = -26,
+ [1][1][RTW89_WW][2][45] = 0,
+ [1][1][RTW89_WW][0][47] = -28,
+ [1][1][RTW89_WW][1][47] = -28,
+ [1][1][RTW89_WW][2][47] = 0,
+ [1][1][RTW89_WW][0][49] = -28,
+ [1][1][RTW89_WW][1][49] = -28,
+ [1][1][RTW89_WW][2][49] = 0,
+ [1][1][RTW89_WW][0][51] = -28,
+ [1][1][RTW89_WW][1][51] = -28,
+ [1][1][RTW89_WW][2][51] = 0,
+ [1][1][RTW89_WW][0][53] = -26,
+ [1][1][RTW89_WW][1][53] = -26,
+ [1][1][RTW89_WW][2][53] = 0,
+ [1][1][RTW89_WW][0][55] = -28,
+ [1][1][RTW89_WW][1][55] = -28,
+ [1][1][RTW89_WW][2][55] = 44,
+ [1][1][RTW89_WW][0][57] = -28,
+ [1][1][RTW89_WW][1][57] = -28,
+ [1][1][RTW89_WW][2][57] = 44,
+ [1][1][RTW89_WW][0][59] = -28,
+ [1][1][RTW89_WW][1][59] = -28,
+ [1][1][RTW89_WW][2][59] = 44,
+ [1][1][RTW89_WW][0][60] = -28,
+ [1][1][RTW89_WW][1][60] = -28,
+ [1][1][RTW89_WW][2][60] = 44,
+ [1][1][RTW89_WW][0][62] = -28,
+ [1][1][RTW89_WW][1][62] = -28,
+ [1][1][RTW89_WW][2][62] = 44,
+ [1][1][RTW89_WW][0][64] = -28,
+ [1][1][RTW89_WW][1][64] = -28,
+ [1][1][RTW89_WW][2][64] = 44,
+ [1][1][RTW89_WW][0][66] = -28,
+ [1][1][RTW89_WW][1][66] = -28,
+ [1][1][RTW89_WW][2][66] = 44,
+ [1][1][RTW89_WW][0][68] = -28,
+ [1][1][RTW89_WW][1][68] = -28,
+ [1][1][RTW89_WW][2][68] = 44,
+ [1][1][RTW89_WW][0][70] = -26,
+ [1][1][RTW89_WW][1][70] = -26,
+ [1][1][RTW89_WW][2][70] = 44,
+ [1][1][RTW89_WW][0][72] = -28,
+ [1][1][RTW89_WW][1][72] = -28,
+ [1][1][RTW89_WW][2][72] = 44,
+ [1][1][RTW89_WW][0][74] = -28,
+ [1][1][RTW89_WW][1][74] = -28,
+ [1][1][RTW89_WW][2][74] = 44,
+ [1][1][RTW89_WW][0][75] = -28,
+ [1][1][RTW89_WW][1][75] = -28,
+ [1][1][RTW89_WW][2][75] = 44,
+ [1][1][RTW89_WW][0][77] = -28,
+ [1][1][RTW89_WW][1][77] = -28,
+ [1][1][RTW89_WW][2][77] = 44,
+ [1][1][RTW89_WW][0][79] = -28,
+ [1][1][RTW89_WW][1][79] = -28,
+ [1][1][RTW89_WW][2][79] = 44,
+ [1][1][RTW89_WW][0][81] = -28,
+ [1][1][RTW89_WW][1][81] = -28,
+ [1][1][RTW89_WW][2][81] = 44,
+ [1][1][RTW89_WW][0][83] = -28,
+ [1][1][RTW89_WW][1][83] = -28,
+ [1][1][RTW89_WW][2][83] = 44,
+ [1][1][RTW89_WW][0][85] = -28,
+ [1][1][RTW89_WW][1][85] = -28,
+ [1][1][RTW89_WW][2][85] = 44,
+ [1][1][RTW89_WW][0][87] = -28,
+ [1][1][RTW89_WW][1][87] = -28,
+ [1][1][RTW89_WW][2][87] = 0,
+ [1][1][RTW89_WW][0][89] = -26,
+ [1][1][RTW89_WW][1][89] = -26,
+ [1][1][RTW89_WW][2][89] = 0,
+ [1][1][RTW89_WW][0][90] = -26,
+ [1][1][RTW89_WW][1][90] = -26,
+ [1][1][RTW89_WW][2][90] = 0,
+ [1][1][RTW89_WW][0][92] = -26,
+ [1][1][RTW89_WW][1][92] = -26,
+ [1][1][RTW89_WW][2][92] = 0,
+ [1][1][RTW89_WW][0][94] = -26,
+ [1][1][RTW89_WW][1][94] = -26,
+ [1][1][RTW89_WW][2][94] = 0,
+ [1][1][RTW89_WW][0][96] = -26,
+ [1][1][RTW89_WW][1][96] = -26,
+ [1][1][RTW89_WW][2][96] = 0,
+ [1][1][RTW89_WW][0][98] = -26,
+ [1][1][RTW89_WW][1][98] = -26,
+ [1][1][RTW89_WW][2][98] = 0,
+ [1][1][RTW89_WW][0][100] = -26,
+ [1][1][RTW89_WW][1][100] = -26,
+ [1][1][RTW89_WW][2][100] = 0,
+ [1][1][RTW89_WW][0][102] = -26,
+ [1][1][RTW89_WW][1][102] = -26,
+ [1][1][RTW89_WW][2][102] = 0,
+ [1][1][RTW89_WW][0][104] = -26,
+ [1][1][RTW89_WW][1][104] = -26,
+ [1][1][RTW89_WW][2][104] = 0,
+ [1][1][RTW89_WW][0][105] = -26,
+ [1][1][RTW89_WW][1][105] = -26,
+ [1][1][RTW89_WW][2][105] = 0,
+ [1][1][RTW89_WW][0][107] = -22,
+ [1][1][RTW89_WW][1][107] = -22,
+ [1][1][RTW89_WW][2][107] = 0,
+ [1][1][RTW89_WW][0][109] = -22,
+ [1][1][RTW89_WW][1][109] = -22,
+ [1][1][RTW89_WW][2][109] = 0,
+ [1][1][RTW89_WW][0][111] = 0,
+ [1][1][RTW89_WW][1][111] = 0,
+ [1][1][RTW89_WW][2][111] = 0,
+ [1][1][RTW89_WW][0][113] = 0,
+ [1][1][RTW89_WW][1][113] = 0,
+ [1][1][RTW89_WW][2][113] = 0,
+ [1][1][RTW89_WW][0][115] = 0,
+ [1][1][RTW89_WW][1][115] = 0,
+ [1][1][RTW89_WW][2][115] = 0,
+ [1][1][RTW89_WW][0][117] = 0,
+ [1][1][RTW89_WW][1][117] = 0,
+ [1][1][RTW89_WW][2][117] = 0,
+ [1][1][RTW89_WW][0][119] = 0,
+ [1][1][RTW89_WW][1][119] = 0,
+ [1][1][RTW89_WW][2][119] = 0,
+ [2][0][RTW89_WW][0][0] = -2,
+ [2][0][RTW89_WW][1][0] = -2,
+ [2][0][RTW89_WW][2][0] = 60,
+ [2][0][RTW89_WW][0][2] = -2,
+ [2][0][RTW89_WW][1][2] = -2,
+ [2][0][RTW89_WW][2][2] = 60,
+ [2][0][RTW89_WW][0][4] = -2,
+ [2][0][RTW89_WW][1][4] = -2,
+ [2][0][RTW89_WW][2][4] = 60,
+ [2][0][RTW89_WW][0][6] = -2,
+ [2][0][RTW89_WW][1][6] = -2,
+ [2][0][RTW89_WW][2][6] = 60,
+ [2][0][RTW89_WW][0][8] = -2,
+ [2][0][RTW89_WW][1][8] = -2,
+ [2][0][RTW89_WW][2][8] = 60,
+ [2][0][RTW89_WW][0][10] = -2,
+ [2][0][RTW89_WW][1][10] = -2,
+ [2][0][RTW89_WW][2][10] = 60,
+ [2][0][RTW89_WW][0][12] = -2,
+ [2][0][RTW89_WW][1][12] = -2,
+ [2][0][RTW89_WW][2][12] = 60,
+ [2][0][RTW89_WW][0][14] = -2,
+ [2][0][RTW89_WW][1][14] = -2,
+ [2][0][RTW89_WW][2][14] = 60,
+ [2][0][RTW89_WW][0][15] = -2,
+ [2][0][RTW89_WW][1][15] = -2,
+ [2][0][RTW89_WW][2][15] = 60,
+ [2][0][RTW89_WW][0][17] = -2,
+ [2][0][RTW89_WW][1][17] = -2,
+ [2][0][RTW89_WW][2][17] = 60,
+ [2][0][RTW89_WW][0][19] = -2,
+ [2][0][RTW89_WW][1][19] = -2,
+ [2][0][RTW89_WW][2][19] = 60,
+ [2][0][RTW89_WW][0][21] = -2,
+ [2][0][RTW89_WW][1][21] = -2,
+ [2][0][RTW89_WW][2][21] = 60,
+ [2][0][RTW89_WW][0][23] = -2,
+ [2][0][RTW89_WW][1][23] = -2,
+ [2][0][RTW89_WW][2][23] = 78,
+ [2][0][RTW89_WW][0][25] = -2,
+ [2][0][RTW89_WW][1][25] = -2,
+ [2][0][RTW89_WW][2][25] = 78,
+ [2][0][RTW89_WW][0][27] = -2,
+ [2][0][RTW89_WW][1][27] = -2,
+ [2][0][RTW89_WW][2][27] = 78,
+ [2][0][RTW89_WW][0][29] = -2,
+ [2][0][RTW89_WW][1][29] = -2,
+ [2][0][RTW89_WW][2][29] = 78,
+ [2][0][RTW89_WW][0][30] = -2,
+ [2][0][RTW89_WW][1][30] = -2,
+ [2][0][RTW89_WW][2][30] = 78,
+ [2][0][RTW89_WW][0][32] = -2,
+ [2][0][RTW89_WW][1][32] = -2,
+ [2][0][RTW89_WW][2][32] = 78,
+ [2][0][RTW89_WW][0][34] = -2,
+ [2][0][RTW89_WW][1][34] = -2,
+ [2][0][RTW89_WW][2][34] = 78,
+ [2][0][RTW89_WW][0][36] = -2,
+ [2][0][RTW89_WW][1][36] = -2,
+ [2][0][RTW89_WW][2][36] = 78,
+ [2][0][RTW89_WW][0][38] = -2,
+ [2][0][RTW89_WW][1][38] = -2,
+ [2][0][RTW89_WW][2][38] = 78,
+ [2][0][RTW89_WW][0][40] = -2,
+ [2][0][RTW89_WW][1][40] = -2,
+ [2][0][RTW89_WW][2][40] = 78,
+ [2][0][RTW89_WW][0][42] = -2,
+ [2][0][RTW89_WW][1][42] = -2,
+ [2][0][RTW89_WW][2][42] = 78,
+ [2][0][RTW89_WW][0][44] = -2,
+ [2][0][RTW89_WW][1][44] = -2,
+ [2][0][RTW89_WW][2][44] = 78,
+ [2][0][RTW89_WW][0][45] = -2,
+ [2][0][RTW89_WW][1][45] = -2,
+ [2][0][RTW89_WW][2][45] = 0,
+ [2][0][RTW89_WW][0][47] = -2,
+ [2][0][RTW89_WW][1][47] = -2,
+ [2][0][RTW89_WW][2][47] = 0,
+ [2][0][RTW89_WW][0][49] = -2,
+ [2][0][RTW89_WW][1][49] = -2,
+ [2][0][RTW89_WW][2][49] = 0,
+ [2][0][RTW89_WW][0][51] = -2,
+ [2][0][RTW89_WW][1][51] = -2,
+ [2][0][RTW89_WW][2][51] = 0,
+ [2][0][RTW89_WW][0][53] = -2,
+ [2][0][RTW89_WW][1][53] = -2,
+ [2][0][RTW89_WW][2][53] = 0,
+ [2][0][RTW89_WW][0][55] = -2,
+ [2][0][RTW89_WW][1][55] = -2,
+ [2][0][RTW89_WW][2][55] = 78,
+ [2][0][RTW89_WW][0][57] = -2,
+ [2][0][RTW89_WW][1][57] = -2,
+ [2][0][RTW89_WW][2][57] = 78,
+ [2][0][RTW89_WW][0][59] = -2,
+ [2][0][RTW89_WW][1][59] = -2,
+ [2][0][RTW89_WW][2][59] = 78,
+ [2][0][RTW89_WW][0][60] = -2,
+ [2][0][RTW89_WW][1][60] = -2,
+ [2][0][RTW89_WW][2][60] = 78,
+ [2][0][RTW89_WW][0][62] = -2,
+ [2][0][RTW89_WW][1][62] = -2,
+ [2][0][RTW89_WW][2][62] = 78,
+ [2][0][RTW89_WW][0][64] = -2,
+ [2][0][RTW89_WW][1][64] = -2,
+ [2][0][RTW89_WW][2][64] = 78,
+ [2][0][RTW89_WW][0][66] = -2,
+ [2][0][RTW89_WW][1][66] = -2,
+ [2][0][RTW89_WW][2][66] = 78,
+ [2][0][RTW89_WW][0][68] = -2,
+ [2][0][RTW89_WW][1][68] = -2,
+ [2][0][RTW89_WW][2][68] = 78,
+ [2][0][RTW89_WW][0][70] = -2,
+ [2][0][RTW89_WW][1][70] = -2,
+ [2][0][RTW89_WW][2][70] = 78,
+ [2][0][RTW89_WW][0][72] = -2,
+ [2][0][RTW89_WW][1][72] = -2,
+ [2][0][RTW89_WW][2][72] = 78,
+ [2][0][RTW89_WW][0][74] = -2,
+ [2][0][RTW89_WW][1][74] = -2,
+ [2][0][RTW89_WW][2][74] = 78,
+ [2][0][RTW89_WW][0][75] = -2,
+ [2][0][RTW89_WW][1][75] = -2,
+ [2][0][RTW89_WW][2][75] = 78,
+ [2][0][RTW89_WW][0][77] = -2,
+ [2][0][RTW89_WW][1][77] = -2,
+ [2][0][RTW89_WW][2][77] = 78,
+ [2][0][RTW89_WW][0][79] = -2,
+ [2][0][RTW89_WW][1][79] = -2,
+ [2][0][RTW89_WW][2][79] = 78,
+ [2][0][RTW89_WW][0][81] = -2,
+ [2][0][RTW89_WW][1][81] = -2,
+ [2][0][RTW89_WW][2][81] = 78,
+ [2][0][RTW89_WW][0][83] = -2,
+ [2][0][RTW89_WW][1][83] = -2,
+ [2][0][RTW89_WW][2][83] = 78,
+ [2][0][RTW89_WW][0][85] = -2,
+ [2][0][RTW89_WW][1][85] = -2,
+ [2][0][RTW89_WW][2][85] = 78,
+ [2][0][RTW89_WW][0][87] = -2,
+ [2][0][RTW89_WW][1][87] = -2,
+ [2][0][RTW89_WW][2][87] = 0,
+ [2][0][RTW89_WW][0][89] = -2,
+ [2][0][RTW89_WW][1][89] = -2,
+ [2][0][RTW89_WW][2][89] = 0,
+ [2][0][RTW89_WW][0][90] = -2,
+ [2][0][RTW89_WW][1][90] = -2,
+ [2][0][RTW89_WW][2][90] = 0,
+ [2][0][RTW89_WW][0][92] = -2,
+ [2][0][RTW89_WW][1][92] = -2,
+ [2][0][RTW89_WW][2][92] = 0,
+ [2][0][RTW89_WW][0][94] = -2,
+ [2][0][RTW89_WW][1][94] = -2,
+ [2][0][RTW89_WW][2][94] = 0,
+ [2][0][RTW89_WW][0][96] = -2,
+ [2][0][RTW89_WW][1][96] = -2,
+ [2][0][RTW89_WW][2][96] = 0,
+ [2][0][RTW89_WW][0][98] = -2,
+ [2][0][RTW89_WW][1][98] = -2,
+ [2][0][RTW89_WW][2][98] = 0,
+ [2][0][RTW89_WW][0][100] = -2,
+ [2][0][RTW89_WW][1][100] = -2,
+ [2][0][RTW89_WW][2][100] = 0,
+ [2][0][RTW89_WW][0][102] = -2,
+ [2][0][RTW89_WW][1][102] = -2,
+ [2][0][RTW89_WW][2][102] = 0,
+ [2][0][RTW89_WW][0][104] = -2,
+ [2][0][RTW89_WW][1][104] = -2,
+ [2][0][RTW89_WW][2][104] = 0,
+ [2][0][RTW89_WW][0][105] = -2,
+ [2][0][RTW89_WW][1][105] = -2,
+ [2][0][RTW89_WW][2][105] = 0,
+ [2][0][RTW89_WW][0][107] = -2,
+ [2][0][RTW89_WW][1][107] = -2,
+ [2][0][RTW89_WW][2][107] = 0,
+ [2][0][RTW89_WW][0][109] = 12,
+ [2][0][RTW89_WW][1][109] = 12,
+ [2][0][RTW89_WW][2][109] = 0,
+ [2][0][RTW89_WW][0][111] = 0,
+ [2][0][RTW89_WW][1][111] = 0,
+ [2][0][RTW89_WW][2][111] = 0,
+ [2][0][RTW89_WW][0][113] = 0,
+ [2][0][RTW89_WW][1][113] = 0,
+ [2][0][RTW89_WW][2][113] = 0,
+ [2][0][RTW89_WW][0][115] = 0,
+ [2][0][RTW89_WW][1][115] = 0,
+ [2][0][RTW89_WW][2][115] = 0,
+ [2][0][RTW89_WW][0][117] = 0,
+ [2][0][RTW89_WW][1][117] = 0,
+ [2][0][RTW89_WW][2][117] = 0,
+ [2][0][RTW89_WW][0][119] = 0,
+ [2][0][RTW89_WW][1][119] = 0,
+ [2][0][RTW89_WW][2][119] = 0,
+ [2][1][RTW89_WW][0][0] = -16,
+ [2][1][RTW89_WW][1][0] = -16,
+ [2][1][RTW89_WW][2][0] = 54,
+ [2][1][RTW89_WW][0][2] = -16,
+ [2][1][RTW89_WW][1][2] = -16,
+ [2][1][RTW89_WW][2][2] = 54,
+ [2][1][RTW89_WW][0][4] = -16,
+ [2][1][RTW89_WW][1][4] = -16,
+ [2][1][RTW89_WW][2][4] = 54,
+ [2][1][RTW89_WW][0][6] = -16,
+ [2][1][RTW89_WW][1][6] = -16,
+ [2][1][RTW89_WW][2][6] = 54,
+ [2][1][RTW89_WW][0][8] = -16,
+ [2][1][RTW89_WW][1][8] = -16,
+ [2][1][RTW89_WW][2][8] = 54,
+ [2][1][RTW89_WW][0][10] = -16,
+ [2][1][RTW89_WW][1][10] = -16,
+ [2][1][RTW89_WW][2][10] = 54,
+ [2][1][RTW89_WW][0][12] = -16,
+ [2][1][RTW89_WW][1][12] = -16,
+ [2][1][RTW89_WW][2][12] = 54,
+ [2][1][RTW89_WW][0][14] = -16,
+ [2][1][RTW89_WW][1][14] = -16,
+ [2][1][RTW89_WW][2][14] = 54,
+ [2][1][RTW89_WW][0][15] = -16,
+ [2][1][RTW89_WW][1][15] = -16,
+ [2][1][RTW89_WW][2][15] = 54,
+ [2][1][RTW89_WW][0][17] = -16,
+ [2][1][RTW89_WW][1][17] = -16,
+ [2][1][RTW89_WW][2][17] = 54,
+ [2][1][RTW89_WW][0][19] = -16,
+ [2][1][RTW89_WW][1][19] = -16,
+ [2][1][RTW89_WW][2][19] = 54,
+ [2][1][RTW89_WW][0][21] = -16,
+ [2][1][RTW89_WW][1][21] = -16,
+ [2][1][RTW89_WW][2][21] = 54,
+ [2][1][RTW89_WW][0][23] = -16,
+ [2][1][RTW89_WW][1][23] = -16,
+ [2][1][RTW89_WW][2][23] = 54,
+ [2][1][RTW89_WW][0][25] = -16,
+ [2][1][RTW89_WW][1][25] = -16,
+ [2][1][RTW89_WW][2][25] = 54,
+ [2][1][RTW89_WW][0][27] = -16,
+ [2][1][RTW89_WW][1][27] = -16,
+ [2][1][RTW89_WW][2][27] = 54,
+ [2][1][RTW89_WW][0][29] = -16,
+ [2][1][RTW89_WW][1][29] = -16,
+ [2][1][RTW89_WW][2][29] = 54,
+ [2][1][RTW89_WW][0][30] = -16,
+ [2][1][RTW89_WW][1][30] = -16,
+ [2][1][RTW89_WW][2][30] = 54,
+ [2][1][RTW89_WW][0][32] = -16,
+ [2][1][RTW89_WW][1][32] = -16,
+ [2][1][RTW89_WW][2][32] = 54,
+ [2][1][RTW89_WW][0][34] = -16,
+ [2][1][RTW89_WW][1][34] = -16,
+ [2][1][RTW89_WW][2][34] = 54,
+ [2][1][RTW89_WW][0][36] = -16,
+ [2][1][RTW89_WW][1][36] = -16,
+ [2][1][RTW89_WW][2][36] = 54,
+ [2][1][RTW89_WW][0][38] = -16,
+ [2][1][RTW89_WW][1][38] = -16,
+ [2][1][RTW89_WW][2][38] = 54,
+ [2][1][RTW89_WW][0][40] = -16,
+ [2][1][RTW89_WW][1][40] = -16,
+ [2][1][RTW89_WW][2][40] = 54,
+ [2][1][RTW89_WW][0][42] = -16,
+ [2][1][RTW89_WW][1][42] = -16,
+ [2][1][RTW89_WW][2][42] = 54,
+ [2][1][RTW89_WW][0][44] = -16,
+ [2][1][RTW89_WW][1][44] = -16,
+ [2][1][RTW89_WW][2][44] = 54,
+ [2][1][RTW89_WW][0][45] = -16,
+ [2][1][RTW89_WW][1][45] = -16,
+ [2][1][RTW89_WW][2][45] = 0,
+ [2][1][RTW89_WW][0][47] = -16,
+ [2][1][RTW89_WW][1][47] = -16,
+ [2][1][RTW89_WW][2][47] = 0,
+ [2][1][RTW89_WW][0][49] = -16,
+ [2][1][RTW89_WW][1][49] = -16,
+ [2][1][RTW89_WW][2][49] = 0,
+ [2][1][RTW89_WW][0][51] = -16,
+ [2][1][RTW89_WW][1][51] = -16,
+ [2][1][RTW89_WW][2][51] = 0,
+ [2][1][RTW89_WW][0][53] = -16,
+ [2][1][RTW89_WW][1][53] = -16,
+ [2][1][RTW89_WW][2][53] = 0,
+ [2][1][RTW89_WW][0][55] = -16,
+ [2][1][RTW89_WW][1][55] = -16,
+ [2][1][RTW89_WW][2][55] = 54,
+ [2][1][RTW89_WW][0][57] = -16,
+ [2][1][RTW89_WW][1][57] = -16,
+ [2][1][RTW89_WW][2][57] = 54,
+ [2][1][RTW89_WW][0][59] = -16,
+ [2][1][RTW89_WW][1][59] = -16,
+ [2][1][RTW89_WW][2][59] = 54,
+ [2][1][RTW89_WW][0][60] = -16,
+ [2][1][RTW89_WW][1][60] = -16,
+ [2][1][RTW89_WW][2][60] = 54,
+ [2][1][RTW89_WW][0][62] = -16,
+ [2][1][RTW89_WW][1][62] = -16,
+ [2][1][RTW89_WW][2][62] = 54,
+ [2][1][RTW89_WW][0][64] = -16,
+ [2][1][RTW89_WW][1][64] = -16,
+ [2][1][RTW89_WW][2][64] = 54,
+ [2][1][RTW89_WW][0][66] = -16,
+ [2][1][RTW89_WW][1][66] = -16,
+ [2][1][RTW89_WW][2][66] = 54,
+ [2][1][RTW89_WW][0][68] = -16,
+ [2][1][RTW89_WW][1][68] = -16,
+ [2][1][RTW89_WW][2][68] = 54,
+ [2][1][RTW89_WW][0][70] = -16,
+ [2][1][RTW89_WW][1][70] = -16,
+ [2][1][RTW89_WW][2][70] = 56,
+ [2][1][RTW89_WW][0][72] = -16,
+ [2][1][RTW89_WW][1][72] = -16,
+ [2][1][RTW89_WW][2][72] = 56,
+ [2][1][RTW89_WW][0][74] = -16,
+ [2][1][RTW89_WW][1][74] = -16,
+ [2][1][RTW89_WW][2][74] = 56,
+ [2][1][RTW89_WW][0][75] = -16,
+ [2][1][RTW89_WW][1][75] = -16,
+ [2][1][RTW89_WW][2][75] = 56,
+ [2][1][RTW89_WW][0][77] = -16,
+ [2][1][RTW89_WW][1][77] = -16,
+ [2][1][RTW89_WW][2][77] = 56,
+ [2][1][RTW89_WW][0][79] = -16,
+ [2][1][RTW89_WW][1][79] = -16,
+ [2][1][RTW89_WW][2][79] = 56,
+ [2][1][RTW89_WW][0][81] = -16,
+ [2][1][RTW89_WW][1][81] = -16,
+ [2][1][RTW89_WW][2][81] = 56,
+ [2][1][RTW89_WW][0][83] = -16,
+ [2][1][RTW89_WW][1][83] = -16,
+ [2][1][RTW89_WW][2][83] = 56,
+ [2][1][RTW89_WW][0][85] = -18,
+ [2][1][RTW89_WW][1][85] = -18,
+ [2][1][RTW89_WW][2][85] = 56,
+ [2][1][RTW89_WW][0][87] = -16,
+ [2][1][RTW89_WW][1][87] = -16,
+ [2][1][RTW89_WW][2][87] = 0,
+ [2][1][RTW89_WW][0][89] = -16,
+ [2][1][RTW89_WW][1][89] = -16,
+ [2][1][RTW89_WW][2][89] = 0,
+ [2][1][RTW89_WW][0][90] = -16,
+ [2][1][RTW89_WW][1][90] = -16,
+ [2][1][RTW89_WW][2][90] = 0,
+ [2][1][RTW89_WW][0][92] = -16,
+ [2][1][RTW89_WW][1][92] = -16,
+ [2][1][RTW89_WW][2][92] = 0,
+ [2][1][RTW89_WW][0][94] = -16,
+ [2][1][RTW89_WW][1][94] = -16,
+ [2][1][RTW89_WW][2][94] = 0,
+ [2][1][RTW89_WW][0][96] = -16,
+ [2][1][RTW89_WW][1][96] = -16,
+ [2][1][RTW89_WW][2][96] = 0,
+ [2][1][RTW89_WW][0][98] = -16,
+ [2][1][RTW89_WW][1][98] = -16,
+ [2][1][RTW89_WW][2][98] = 0,
+ [2][1][RTW89_WW][0][100] = -16,
+ [2][1][RTW89_WW][1][100] = -16,
+ [2][1][RTW89_WW][2][100] = 0,
+ [2][1][RTW89_WW][0][102] = -16,
+ [2][1][RTW89_WW][1][102] = -16,
+ [2][1][RTW89_WW][2][102] = 0,
+ [2][1][RTW89_WW][0][104] = -16,
+ [2][1][RTW89_WW][1][104] = -16,
+ [2][1][RTW89_WW][2][104] = 0,
+ [2][1][RTW89_WW][0][105] = -16,
+ [2][1][RTW89_WW][1][105] = -16,
+ [2][1][RTW89_WW][2][105] = 0,
+ [2][1][RTW89_WW][0][107] = -14,
+ [2][1][RTW89_WW][1][107] = -14,
+ [2][1][RTW89_WW][2][107] = 0,
+ [2][1][RTW89_WW][0][109] = -10,
+ [2][1][RTW89_WW][1][109] = -10,
+ [2][1][RTW89_WW][2][109] = 0,
+ [2][1][RTW89_WW][0][111] = 0,
+ [2][1][RTW89_WW][1][111] = 0,
+ [2][1][RTW89_WW][2][111] = 0,
+ [2][1][RTW89_WW][0][113] = 0,
+ [2][1][RTW89_WW][1][113] = 0,
+ [2][1][RTW89_WW][2][113] = 0,
+ [2][1][RTW89_WW][0][115] = 0,
+ [2][1][RTW89_WW][1][115] = 0,
+ [2][1][RTW89_WW][2][115] = 0,
+ [2][1][RTW89_WW][0][117] = 0,
+ [2][1][RTW89_WW][1][117] = 0,
+ [2][1][RTW89_WW][2][117] = 0,
+ [2][1][RTW89_WW][0][119] = 0,
+ [2][1][RTW89_WW][1][119] = 0,
+ [2][1][RTW89_WW][2][119] = 0,
+ [0][0][RTW89_FCC][1][0] = -16,
+ [0][0][RTW89_FCC][2][0] = 44,
+ [0][0][RTW89_ETSI][1][0] = 32,
+ [0][0][RTW89_ETSI][0][0] = -8,
+ [0][0][RTW89_MKK][1][0] = 30,
+ [0][0][RTW89_MKK][0][0] = -8,
+ [0][0][RTW89_IC][1][0] = -16,
+ [0][0][RTW89_KCC][1][0] = -2,
+ [0][0][RTW89_KCC][0][0] = -2,
+ [0][0][RTW89_ACMA][1][0] = 32,
+ [0][0][RTW89_ACMA][0][0] = -8,
+ [0][0][RTW89_CHILE][1][0] = -16,
+ [0][0][RTW89_QATAR][1][0] = 32,
+ [0][0][RTW89_QATAR][0][0] = -8,
+ [0][0][RTW89_UK][1][0] = 32,
+ [0][0][RTW89_UK][0][0] = -8,
+ [0][0][RTW89_FCC][1][2] = -18,
+ [0][0][RTW89_FCC][2][2] = 44,
+ [0][0][RTW89_ETSI][1][2] = 32,
+ [0][0][RTW89_ETSI][0][2] = -8,
+ [0][0][RTW89_MKK][1][2] = 30,
+ [0][0][RTW89_MKK][0][2] = -8,
+ [0][0][RTW89_IC][1][2] = -18,
+ [0][0][RTW89_KCC][1][2] = -2,
+ [0][0][RTW89_KCC][0][2] = -2,
+ [0][0][RTW89_ACMA][1][2] = 32,
+ [0][0][RTW89_ACMA][0][2] = -8,
+ [0][0][RTW89_CHILE][1][2] = -18,
+ [0][0][RTW89_QATAR][1][2] = 32,
+ [0][0][RTW89_QATAR][0][2] = -8,
+ [0][0][RTW89_UK][1][2] = 32,
+ [0][0][RTW89_UK][0][2] = -8,
+ [0][0][RTW89_FCC][1][4] = -18,
+ [0][0][RTW89_FCC][2][4] = 44,
+ [0][0][RTW89_ETSI][1][4] = 32,
+ [0][0][RTW89_ETSI][0][4] = -8,
+ [0][0][RTW89_MKK][1][4] = 30,
+ [0][0][RTW89_MKK][0][4] = -8,
+ [0][0][RTW89_IC][1][4] = -18,
+ [0][0][RTW89_KCC][1][4] = -2,
+ [0][0][RTW89_KCC][0][4] = -2,
+ [0][0][RTW89_ACMA][1][4] = 32,
+ [0][0][RTW89_ACMA][0][4] = -8,
+ [0][0][RTW89_CHILE][1][4] = -18,
+ [0][0][RTW89_QATAR][1][4] = 32,
+ [0][0][RTW89_QATAR][0][4] = -8,
+ [0][0][RTW89_UK][1][4] = 32,
+ [0][0][RTW89_UK][0][4] = -8,
+ [0][0][RTW89_FCC][1][6] = -18,
+ [0][0][RTW89_FCC][2][6] = 44,
+ [0][0][RTW89_ETSI][1][6] = 32,
+ [0][0][RTW89_ETSI][0][6] = -8,
+ [0][0][RTW89_MKK][1][6] = 30,
+ [0][0][RTW89_MKK][0][6] = -8,
+ [0][0][RTW89_IC][1][6] = -18,
+ [0][0][RTW89_KCC][1][6] = -2,
+ [0][0][RTW89_KCC][0][6] = -2,
+ [0][0][RTW89_ACMA][1][6] = 32,
+ [0][0][RTW89_ACMA][0][6] = -8,
+ [0][0][RTW89_CHILE][1][6] = -18,
+ [0][0][RTW89_QATAR][1][6] = 32,
+ [0][0][RTW89_QATAR][0][6] = -8,
+ [0][0][RTW89_UK][1][6] = 32,
+ [0][0][RTW89_UK][0][6] = -8,
+ [0][0][RTW89_FCC][1][8] = -18,
+ [0][0][RTW89_FCC][2][8] = 44,
+ [0][0][RTW89_ETSI][1][8] = 32,
+ [0][0][RTW89_ETSI][0][8] = -8,
+ [0][0][RTW89_MKK][1][8] = 30,
+ [0][0][RTW89_MKK][0][8] = -8,
+ [0][0][RTW89_IC][1][8] = -18,
+ [0][0][RTW89_KCC][1][8] = -2,
+ [0][0][RTW89_KCC][0][8] = -2,
+ [0][0][RTW89_ACMA][1][8] = 32,
+ [0][0][RTW89_ACMA][0][8] = -8,
+ [0][0][RTW89_CHILE][1][8] = -18,
+ [0][0][RTW89_QATAR][1][8] = 32,
+ [0][0][RTW89_QATAR][0][8] = -8,
+ [0][0][RTW89_UK][1][8] = 32,
+ [0][0][RTW89_UK][0][8] = -8,
+ [0][0][RTW89_FCC][1][10] = -18,
+ [0][0][RTW89_FCC][2][10] = 44,
+ [0][0][RTW89_ETSI][1][10] = 32,
+ [0][0][RTW89_ETSI][0][10] = -8,
+ [0][0][RTW89_MKK][1][10] = 30,
+ [0][0][RTW89_MKK][0][10] = -8,
+ [0][0][RTW89_IC][1][10] = -18,
+ [0][0][RTW89_KCC][1][10] = -2,
+ [0][0][RTW89_KCC][0][10] = -2,
+ [0][0][RTW89_ACMA][1][10] = 32,
+ [0][0][RTW89_ACMA][0][10] = -8,
+ [0][0][RTW89_CHILE][1][10] = -18,
+ [0][0][RTW89_QATAR][1][10] = 32,
+ [0][0][RTW89_QATAR][0][10] = -8,
+ [0][0][RTW89_UK][1][10] = 32,
+ [0][0][RTW89_UK][0][10] = -8,
+ [0][0][RTW89_FCC][1][12] = -18,
+ [0][0][RTW89_FCC][2][12] = 44,
+ [0][0][RTW89_ETSI][1][12] = 32,
+ [0][0][RTW89_ETSI][0][12] = -8,
+ [0][0][RTW89_MKK][1][12] = 30,
+ [0][0][RTW89_MKK][0][12] = -8,
+ [0][0][RTW89_IC][1][12] = -18,
+ [0][0][RTW89_KCC][1][12] = -2,
+ [0][0][RTW89_KCC][0][12] = -2,
+ [0][0][RTW89_ACMA][1][12] = 32,
+ [0][0][RTW89_ACMA][0][12] = -8,
+ [0][0][RTW89_CHILE][1][12] = -18,
+ [0][0][RTW89_QATAR][1][12] = 32,
+ [0][0][RTW89_QATAR][0][12] = -8,
+ [0][0][RTW89_UK][1][12] = 32,
+ [0][0][RTW89_UK][0][12] = -8,
+ [0][0][RTW89_FCC][1][14] = -18,
+ [0][0][RTW89_FCC][2][14] = 44,
+ [0][0][RTW89_ETSI][1][14] = 32,
+ [0][0][RTW89_ETSI][0][14] = -8,
+ [0][0][RTW89_MKK][1][14] = 30,
+ [0][0][RTW89_MKK][0][14] = -8,
+ [0][0][RTW89_IC][1][14] = -18,
+ [0][0][RTW89_KCC][1][14] = -2,
+ [0][0][RTW89_KCC][0][14] = -2,
+ [0][0][RTW89_ACMA][1][14] = 32,
+ [0][0][RTW89_ACMA][0][14] = -8,
+ [0][0][RTW89_CHILE][1][14] = -18,
+ [0][0][RTW89_QATAR][1][14] = 32,
+ [0][0][RTW89_QATAR][0][14] = -8,
+ [0][0][RTW89_UK][1][14] = 32,
+ [0][0][RTW89_UK][0][14] = -8,
+ [0][0][RTW89_FCC][1][15] = -18,
+ [0][0][RTW89_FCC][2][15] = 44,
+ [0][0][RTW89_ETSI][1][15] = 32,
+ [0][0][RTW89_ETSI][0][15] = -8,
+ [0][0][RTW89_MKK][1][15] = 30,
+ [0][0][RTW89_MKK][0][15] = -8,
+ [0][0][RTW89_IC][1][15] = -18,
+ [0][0][RTW89_KCC][1][15] = -2,
+ [0][0][RTW89_KCC][0][15] = -2,
+ [0][0][RTW89_ACMA][1][15] = 32,
+ [0][0][RTW89_ACMA][0][15] = -8,
+ [0][0][RTW89_CHILE][1][15] = -18,
+ [0][0][RTW89_QATAR][1][15] = 32,
+ [0][0][RTW89_QATAR][0][15] = -8,
+ [0][0][RTW89_UK][1][15] = 32,
+ [0][0][RTW89_UK][0][15] = -8,
+ [0][0][RTW89_FCC][1][17] = -18,
+ [0][0][RTW89_FCC][2][17] = 44,
+ [0][0][RTW89_ETSI][1][17] = 32,
+ [0][0][RTW89_ETSI][0][17] = -8,
+ [0][0][RTW89_MKK][1][17] = 30,
+ [0][0][RTW89_MKK][0][17] = -8,
+ [0][0][RTW89_IC][1][17] = -18,
+ [0][0][RTW89_KCC][1][17] = -2,
+ [0][0][RTW89_KCC][0][17] = -2,
+ [0][0][RTW89_ACMA][1][17] = 32,
+ [0][0][RTW89_ACMA][0][17] = -8,
+ [0][0][RTW89_CHILE][1][17] = -18,
+ [0][0][RTW89_QATAR][1][17] = 32,
+ [0][0][RTW89_QATAR][0][17] = -8,
+ [0][0][RTW89_UK][1][17] = 32,
+ [0][0][RTW89_UK][0][17] = -8,
+ [0][0][RTW89_FCC][1][19] = -18,
+ [0][0][RTW89_FCC][2][19] = 44,
+ [0][0][RTW89_ETSI][1][19] = 32,
+ [0][0][RTW89_ETSI][0][19] = -8,
+ [0][0][RTW89_MKK][1][19] = 30,
+ [0][0][RTW89_MKK][0][19] = -8,
+ [0][0][RTW89_IC][1][19] = -18,
+ [0][0][RTW89_KCC][1][19] = -2,
+ [0][0][RTW89_KCC][0][19] = -2,
+ [0][0][RTW89_ACMA][1][19] = 32,
+ [0][0][RTW89_ACMA][0][19] = -8,
+ [0][0][RTW89_CHILE][1][19] = -18,
+ [0][0][RTW89_QATAR][1][19] = 32,
+ [0][0][RTW89_QATAR][0][19] = -8,
+ [0][0][RTW89_UK][1][19] = 32,
+ [0][0][RTW89_UK][0][19] = -8,
+ [0][0][RTW89_FCC][1][21] = -18,
+ [0][0][RTW89_FCC][2][21] = 44,
+ [0][0][RTW89_ETSI][1][21] = 32,
+ [0][0][RTW89_ETSI][0][21] = -8,
+ [0][0][RTW89_MKK][1][21] = 30,
+ [0][0][RTW89_MKK][0][21] = -8,
+ [0][0][RTW89_IC][1][21] = -18,
+ [0][0][RTW89_KCC][1][21] = -2,
+ [0][0][RTW89_KCC][0][21] = -2,
+ [0][0][RTW89_ACMA][1][21] = 32,
+ [0][0][RTW89_ACMA][0][21] = -8,
+ [0][0][RTW89_CHILE][1][21] = -18,
+ [0][0][RTW89_QATAR][1][21] = 32,
+ [0][0][RTW89_QATAR][0][21] = -8,
+ [0][0][RTW89_UK][1][21] = 32,
+ [0][0][RTW89_UK][0][21] = -8,
+ [0][0][RTW89_FCC][1][23] = -18,
+ [0][0][RTW89_FCC][2][23] = 54,
+ [0][0][RTW89_ETSI][1][23] = 32,
+ [0][0][RTW89_ETSI][0][23] = -8,
+ [0][0][RTW89_MKK][1][23] = 30,
+ [0][0][RTW89_MKK][0][23] = -8,
+ [0][0][RTW89_IC][1][23] = -18,
+ [0][0][RTW89_KCC][1][23] = -2,
+ [0][0][RTW89_KCC][0][23] = -2,
+ [0][0][RTW89_ACMA][1][23] = 32,
+ [0][0][RTW89_ACMA][0][23] = -8,
+ [0][0][RTW89_CHILE][1][23] = -18,
+ [0][0][RTW89_QATAR][1][23] = 32,
+ [0][0][RTW89_QATAR][0][23] = -8,
+ [0][0][RTW89_UK][1][23] = 32,
+ [0][0][RTW89_UK][0][23] = -8,
+ [0][0][RTW89_FCC][1][25] = -18,
+ [0][0][RTW89_FCC][2][25] = 54,
+ [0][0][RTW89_ETSI][1][25] = 32,
+ [0][0][RTW89_ETSI][0][25] = -8,
+ [0][0][RTW89_MKK][1][25] = 30,
+ [0][0][RTW89_MKK][0][25] = -8,
+ [0][0][RTW89_IC][1][25] = -18,
+ [0][0][RTW89_KCC][1][25] = -2,
+ [0][0][RTW89_KCC][0][25] = -2,
+ [0][0][RTW89_ACMA][1][25] = 32,
+ [0][0][RTW89_ACMA][0][25] = -8,
+ [0][0][RTW89_CHILE][1][25] = -18,
+ [0][0][RTW89_QATAR][1][25] = 32,
+ [0][0][RTW89_QATAR][0][25] = -8,
+ [0][0][RTW89_UK][1][25] = 32,
+ [0][0][RTW89_UK][0][25] = -8,
+ [0][0][RTW89_FCC][1][27] = -18,
+ [0][0][RTW89_FCC][2][27] = 54,
+ [0][0][RTW89_ETSI][1][27] = 32,
+ [0][0][RTW89_ETSI][0][27] = -8,
+ [0][0][RTW89_MKK][1][27] = 30,
+ [0][0][RTW89_MKK][0][27] = -8,
+ [0][0][RTW89_IC][1][27] = -18,
+ [0][0][RTW89_KCC][1][27] = -2,
+ [0][0][RTW89_KCC][0][27] = -2,
+ [0][0][RTW89_ACMA][1][27] = 32,
+ [0][0][RTW89_ACMA][0][27] = -8,
+ [0][0][RTW89_CHILE][1][27] = -18,
+ [0][0][RTW89_QATAR][1][27] = 32,
+ [0][0][RTW89_QATAR][0][27] = -8,
+ [0][0][RTW89_UK][1][27] = 32,
+ [0][0][RTW89_UK][0][27] = -8,
+ [0][0][RTW89_FCC][1][29] = -18,
+ [0][0][RTW89_FCC][2][29] = 54,
+ [0][0][RTW89_ETSI][1][29] = 32,
+ [0][0][RTW89_ETSI][0][29] = -8,
+ [0][0][RTW89_MKK][1][29] = 30,
+ [0][0][RTW89_MKK][0][29] = -8,
+ [0][0][RTW89_IC][1][29] = -18,
+ [0][0][RTW89_KCC][1][29] = -2,
+ [0][0][RTW89_KCC][0][29] = -2,
+ [0][0][RTW89_ACMA][1][29] = 32,
+ [0][0][RTW89_ACMA][0][29] = -8,
+ [0][0][RTW89_CHILE][1][29] = -18,
+ [0][0][RTW89_QATAR][1][29] = 32,
+ [0][0][RTW89_QATAR][0][29] = -8,
+ [0][0][RTW89_UK][1][29] = 32,
+ [0][0][RTW89_UK][0][29] = -8,
+ [0][0][RTW89_FCC][1][30] = -18,
+ [0][0][RTW89_FCC][2][30] = 54,
+ [0][0][RTW89_ETSI][1][30] = 32,
+ [0][0][RTW89_ETSI][0][30] = -8,
+ [0][0][RTW89_MKK][1][30] = 30,
+ [0][0][RTW89_MKK][0][30] = -8,
+ [0][0][RTW89_IC][1][30] = -18,
+ [0][0][RTW89_KCC][1][30] = -2,
+ [0][0][RTW89_KCC][0][30] = -2,
+ [0][0][RTW89_ACMA][1][30] = 32,
+ [0][0][RTW89_ACMA][0][30] = -8,
+ [0][0][RTW89_CHILE][1][30] = -18,
+ [0][0][RTW89_QATAR][1][30] = 32,
+ [0][0][RTW89_QATAR][0][30] = -8,
+ [0][0][RTW89_UK][1][30] = 32,
+ [0][0][RTW89_UK][0][30] = -8,
+ [0][0][RTW89_FCC][1][32] = -18,
+ [0][0][RTW89_FCC][2][32] = 54,
+ [0][0][RTW89_ETSI][1][32] = 32,
+ [0][0][RTW89_ETSI][0][32] = -8,
+ [0][0][RTW89_MKK][1][32] = 30,
+ [0][0][RTW89_MKK][0][32] = -8,
+ [0][0][RTW89_IC][1][32] = -18,
+ [0][0][RTW89_KCC][1][32] = -2,
+ [0][0][RTW89_KCC][0][32] = -2,
+ [0][0][RTW89_ACMA][1][32] = 32,
+ [0][0][RTW89_ACMA][0][32] = -8,
+ [0][0][RTW89_CHILE][1][32] = -18,
+ [0][0][RTW89_QATAR][1][32] = 32,
+ [0][0][RTW89_QATAR][0][32] = -8,
+ [0][0][RTW89_UK][1][32] = 32,
+ [0][0][RTW89_UK][0][32] = -8,
+ [0][0][RTW89_FCC][1][34] = -18,
+ [0][0][RTW89_FCC][2][34] = 54,
+ [0][0][RTW89_ETSI][1][34] = 32,
+ [0][0][RTW89_ETSI][0][34] = -8,
+ [0][0][RTW89_MKK][1][34] = 30,
+ [0][0][RTW89_MKK][0][34] = -8,
+ [0][0][RTW89_IC][1][34] = -18,
+ [0][0][RTW89_KCC][1][34] = -2,
+ [0][0][RTW89_KCC][0][34] = -2,
+ [0][0][RTW89_ACMA][1][34] = 32,
+ [0][0][RTW89_ACMA][0][34] = -8,
+ [0][0][RTW89_CHILE][1][34] = -18,
+ [0][0][RTW89_QATAR][1][34] = 32,
+ [0][0][RTW89_QATAR][0][34] = -8,
+ [0][0][RTW89_UK][1][34] = 32,
+ [0][0][RTW89_UK][0][34] = -8,
+ [0][0][RTW89_FCC][1][36] = -18,
+ [0][0][RTW89_FCC][2][36] = 54,
+ [0][0][RTW89_ETSI][1][36] = 32,
+ [0][0][RTW89_ETSI][0][36] = -8,
+ [0][0][RTW89_MKK][1][36] = 30,
+ [0][0][RTW89_MKK][0][36] = -8,
+ [0][0][RTW89_IC][1][36] = -18,
+ [0][0][RTW89_KCC][1][36] = -2,
+ [0][0][RTW89_KCC][0][36] = -2,
+ [0][0][RTW89_ACMA][1][36] = 32,
+ [0][0][RTW89_ACMA][0][36] = -8,
+ [0][0][RTW89_CHILE][1][36] = -18,
+ [0][0][RTW89_QATAR][1][36] = 32,
+ [0][0][RTW89_QATAR][0][36] = -8,
+ [0][0][RTW89_UK][1][36] = 32,
+ [0][0][RTW89_UK][0][36] = -8,
+ [0][0][RTW89_FCC][1][38] = -18,
+ [0][0][RTW89_FCC][2][38] = 54,
+ [0][0][RTW89_ETSI][1][38] = 32,
+ [0][0][RTW89_ETSI][0][38] = -8,
+ [0][0][RTW89_MKK][1][38] = 30,
+ [0][0][RTW89_MKK][0][38] = -8,
+ [0][0][RTW89_IC][1][38] = -18,
+ [0][0][RTW89_KCC][1][38] = -2,
+ [0][0][RTW89_KCC][0][38] = -2,
+ [0][0][RTW89_ACMA][1][38] = 32,
+ [0][0][RTW89_ACMA][0][38] = -8,
+ [0][0][RTW89_CHILE][1][38] = -18,
+ [0][0][RTW89_QATAR][1][38] = 32,
+ [0][0][RTW89_QATAR][0][38] = -8,
+ [0][0][RTW89_UK][1][38] = 32,
+ [0][0][RTW89_UK][0][38] = -8,
+ [0][0][RTW89_FCC][1][40] = -18,
+ [0][0][RTW89_FCC][2][40] = 54,
+ [0][0][RTW89_ETSI][1][40] = 32,
+ [0][0][RTW89_ETSI][0][40] = -8,
+ [0][0][RTW89_MKK][1][40] = 30,
+ [0][0][RTW89_MKK][0][40] = -8,
+ [0][0][RTW89_IC][1][40] = -18,
+ [0][0][RTW89_KCC][1][40] = -2,
+ [0][0][RTW89_KCC][0][40] = -2,
+ [0][0][RTW89_ACMA][1][40] = 32,
+ [0][0][RTW89_ACMA][0][40] = -8,
+ [0][0][RTW89_CHILE][1][40] = -18,
+ [0][0][RTW89_QATAR][1][40] = 32,
+ [0][0][RTW89_QATAR][0][40] = -8,
+ [0][0][RTW89_UK][1][40] = 32,
+ [0][0][RTW89_UK][0][40] = -8,
+ [0][0][RTW89_FCC][1][42] = -18,
+ [0][0][RTW89_FCC][2][42] = 54,
+ [0][0][RTW89_ETSI][1][42] = 32,
+ [0][0][RTW89_ETSI][0][42] = -8,
+ [0][0][RTW89_MKK][1][42] = 30,
+ [0][0][RTW89_MKK][0][42] = -8,
+ [0][0][RTW89_IC][1][42] = -18,
+ [0][0][RTW89_KCC][1][42] = -2,
+ [0][0][RTW89_KCC][0][42] = -2,
+ [0][0][RTW89_ACMA][1][42] = 32,
+ [0][0][RTW89_ACMA][0][42] = -8,
+ [0][0][RTW89_CHILE][1][42] = -18,
+ [0][0][RTW89_QATAR][1][42] = 32,
+ [0][0][RTW89_QATAR][0][42] = -8,
+ [0][0][RTW89_UK][1][42] = 32,
+ [0][0][RTW89_UK][0][42] = -8,
+ [0][0][RTW89_FCC][1][44] = -16,
+ [0][0][RTW89_FCC][2][44] = 56,
+ [0][0][RTW89_ETSI][1][44] = 32,
+ [0][0][RTW89_ETSI][0][44] = -6,
+ [0][0][RTW89_MKK][1][44] = 8,
+ [0][0][RTW89_MKK][0][44] = -10,
+ [0][0][RTW89_IC][1][44] = -16,
+ [0][0][RTW89_KCC][1][44] = -2,
+ [0][0][RTW89_KCC][0][44] = -2,
+ [0][0][RTW89_ACMA][1][44] = 32,
+ [0][0][RTW89_ACMA][0][44] = -6,
+ [0][0][RTW89_CHILE][1][44] = -16,
+ [0][0][RTW89_QATAR][1][44] = 32,
+ [0][0][RTW89_QATAR][0][44] = -6,
+ [0][0][RTW89_UK][1][44] = 32,
+ [0][0][RTW89_UK][0][44] = -6,
+ [0][0][RTW89_FCC][1][45] = -16,
+ [0][0][RTW89_FCC][2][45] = 127,
+ [0][0][RTW89_ETSI][1][45] = 127,
+ [0][0][RTW89_ETSI][0][45] = 127,
+ [0][0][RTW89_MKK][1][45] = 127,
+ [0][0][RTW89_MKK][0][45] = 127,
+ [0][0][RTW89_IC][1][45] = -16,
+ [0][0][RTW89_KCC][1][45] = -2,
+ [0][0][RTW89_KCC][0][45] = 127,
+ [0][0][RTW89_ACMA][1][45] = 127,
+ [0][0][RTW89_ACMA][0][45] = 127,
+ [0][0][RTW89_CHILE][1][45] = 127,
+ [0][0][RTW89_QATAR][1][45] = 127,
+ [0][0][RTW89_QATAR][0][45] = 127,
+ [0][0][RTW89_UK][1][45] = 127,
+ [0][0][RTW89_UK][0][45] = 127,
+ [0][0][RTW89_FCC][1][47] = -18,
+ [0][0][RTW89_FCC][2][47] = 127,
+ [0][0][RTW89_ETSI][1][47] = 127,
+ [0][0][RTW89_ETSI][0][47] = 127,
+ [0][0][RTW89_MKK][1][47] = 127,
+ [0][0][RTW89_MKK][0][47] = 127,
+ [0][0][RTW89_IC][1][47] = -18,
+ [0][0][RTW89_KCC][1][47] = -2,
+ [0][0][RTW89_KCC][0][47] = 127,
+ [0][0][RTW89_ACMA][1][47] = 127,
+ [0][0][RTW89_ACMA][0][47] = 127,
+ [0][0][RTW89_CHILE][1][47] = 127,
+ [0][0][RTW89_QATAR][1][47] = 127,
+ [0][0][RTW89_QATAR][0][47] = 127,
+ [0][0][RTW89_UK][1][47] = 127,
+ [0][0][RTW89_UK][0][47] = 127,
+ [0][0][RTW89_FCC][1][49] = -18,
+ [0][0][RTW89_FCC][2][49] = 127,
+ [0][0][RTW89_ETSI][1][49] = 127,
+ [0][0][RTW89_ETSI][0][49] = 127,
+ [0][0][RTW89_MKK][1][49] = 127,
+ [0][0][RTW89_MKK][0][49] = 127,
+ [0][0][RTW89_IC][1][49] = -18,
+ [0][0][RTW89_KCC][1][49] = -2,
+ [0][0][RTW89_KCC][0][49] = 127,
+ [0][0][RTW89_ACMA][1][49] = 127,
+ [0][0][RTW89_ACMA][0][49] = 127,
+ [0][0][RTW89_CHILE][1][49] = 127,
+ [0][0][RTW89_QATAR][1][49] = 127,
+ [0][0][RTW89_QATAR][0][49] = 127,
+ [0][0][RTW89_UK][1][49] = 127,
+ [0][0][RTW89_UK][0][49] = 127,
+ [0][0][RTW89_FCC][1][51] = -18,
+ [0][0][RTW89_FCC][2][51] = 127,
+ [0][0][RTW89_ETSI][1][51] = 127,
+ [0][0][RTW89_ETSI][0][51] = 127,
+ [0][0][RTW89_MKK][1][51] = 127,
+ [0][0][RTW89_MKK][0][51] = 127,
+ [0][0][RTW89_IC][1][51] = -18,
+ [0][0][RTW89_KCC][1][51] = -2,
+ [0][0][RTW89_KCC][0][51] = 127,
+ [0][0][RTW89_ACMA][1][51] = 127,
+ [0][0][RTW89_ACMA][0][51] = 127,
+ [0][0][RTW89_CHILE][1][51] = 127,
+ [0][0][RTW89_QATAR][1][51] = 127,
+ [0][0][RTW89_QATAR][0][51] = 127,
+ [0][0][RTW89_UK][1][51] = 127,
+ [0][0][RTW89_UK][0][51] = 127,
+ [0][0][RTW89_FCC][1][53] = -16,
+ [0][0][RTW89_FCC][2][53] = 127,
+ [0][0][RTW89_ETSI][1][53] = 127,
+ [0][0][RTW89_ETSI][0][53] = 127,
+ [0][0][RTW89_MKK][1][53] = 127,
+ [0][0][RTW89_MKK][0][53] = 127,
+ [0][0][RTW89_IC][1][53] = -16,
+ [0][0][RTW89_KCC][1][53] = -2,
+ [0][0][RTW89_KCC][0][53] = 127,
+ [0][0][RTW89_ACMA][1][53] = 127,
+ [0][0][RTW89_ACMA][0][53] = 127,
+ [0][0][RTW89_CHILE][1][53] = 127,
+ [0][0][RTW89_QATAR][1][53] = 127,
+ [0][0][RTW89_QATAR][0][53] = 127,
+ [0][0][RTW89_UK][1][53] = 127,
+ [0][0][RTW89_UK][0][53] = 127,
+ [0][0][RTW89_FCC][1][55] = -18,
+ [0][0][RTW89_FCC][2][55] = 56,
+ [0][0][RTW89_ETSI][1][55] = 127,
+ [0][0][RTW89_ETSI][0][55] = 127,
+ [0][0][RTW89_MKK][1][55] = 127,
+ [0][0][RTW89_MKK][0][55] = 127,
+ [0][0][RTW89_IC][1][55] = -18,
+ [0][0][RTW89_KCC][1][55] = -2,
+ [0][0][RTW89_KCC][0][55] = 127,
+ [0][0][RTW89_ACMA][1][55] = 127,
+ [0][0][RTW89_ACMA][0][55] = 127,
+ [0][0][RTW89_CHILE][1][55] = 127,
+ [0][0][RTW89_QATAR][1][55] = 127,
+ [0][0][RTW89_QATAR][0][55] = 127,
+ [0][0][RTW89_UK][1][55] = 127,
+ [0][0][RTW89_UK][0][55] = 127,
+ [0][0][RTW89_FCC][1][57] = -18,
+ [0][0][RTW89_FCC][2][57] = 56,
+ [0][0][RTW89_ETSI][1][57] = 127,
+ [0][0][RTW89_ETSI][0][57] = 127,
+ [0][0][RTW89_MKK][1][57] = 127,
+ [0][0][RTW89_MKK][0][57] = 127,
+ [0][0][RTW89_IC][1][57] = -18,
+ [0][0][RTW89_KCC][1][57] = -2,
+ [0][0][RTW89_KCC][0][57] = 127,
+ [0][0][RTW89_ACMA][1][57] = 127,
+ [0][0][RTW89_ACMA][0][57] = 127,
+ [0][0][RTW89_CHILE][1][57] = 127,
+ [0][0][RTW89_QATAR][1][57] = 127,
+ [0][0][RTW89_QATAR][0][57] = 127,
+ [0][0][RTW89_UK][1][57] = 127,
+ [0][0][RTW89_UK][0][57] = 127,
+ [0][0][RTW89_FCC][1][59] = -18,
+ [0][0][RTW89_FCC][2][59] = 56,
+ [0][0][RTW89_ETSI][1][59] = 127,
+ [0][0][RTW89_ETSI][0][59] = 127,
+ [0][0][RTW89_MKK][1][59] = 127,
+ [0][0][RTW89_MKK][0][59] = 127,
+ [0][0][RTW89_IC][1][59] = -18,
+ [0][0][RTW89_KCC][1][59] = -2,
+ [0][0][RTW89_KCC][0][59] = 127,
+ [0][0][RTW89_ACMA][1][59] = 127,
+ [0][0][RTW89_ACMA][0][59] = 127,
+ [0][0][RTW89_CHILE][1][59] = 127,
+ [0][0][RTW89_QATAR][1][59] = 127,
+ [0][0][RTW89_QATAR][0][59] = 127,
+ [0][0][RTW89_UK][1][59] = 127,
+ [0][0][RTW89_UK][0][59] = 127,
+ [0][0][RTW89_FCC][1][60] = -18,
+ [0][0][RTW89_FCC][2][60] = 56,
+ [0][0][RTW89_ETSI][1][60] = 127,
+ [0][0][RTW89_ETSI][0][60] = 127,
+ [0][0][RTW89_MKK][1][60] = 127,
+ [0][0][RTW89_MKK][0][60] = 127,
+ [0][0][RTW89_IC][1][60] = -18,
+ [0][0][RTW89_KCC][1][60] = -2,
+ [0][0][RTW89_KCC][0][60] = 127,
+ [0][0][RTW89_ACMA][1][60] = 127,
+ [0][0][RTW89_ACMA][0][60] = 127,
+ [0][0][RTW89_CHILE][1][60] = 127,
+ [0][0][RTW89_QATAR][1][60] = 127,
+ [0][0][RTW89_QATAR][0][60] = 127,
+ [0][0][RTW89_UK][1][60] = 127,
+ [0][0][RTW89_UK][0][60] = 127,
+ [0][0][RTW89_FCC][1][62] = -18,
+ [0][0][RTW89_FCC][2][62] = 56,
+ [0][0][RTW89_ETSI][1][62] = 127,
+ [0][0][RTW89_ETSI][0][62] = 127,
+ [0][0][RTW89_MKK][1][62] = 127,
+ [0][0][RTW89_MKK][0][62] = 127,
+ [0][0][RTW89_IC][1][62] = -18,
+ [0][0][RTW89_KCC][1][62] = -2,
+ [0][0][RTW89_KCC][0][62] = 127,
+ [0][0][RTW89_ACMA][1][62] = 127,
+ [0][0][RTW89_ACMA][0][62] = 127,
+ [0][0][RTW89_CHILE][1][62] = 127,
+ [0][0][RTW89_QATAR][1][62] = 127,
+ [0][0][RTW89_QATAR][0][62] = 127,
+ [0][0][RTW89_UK][1][62] = 127,
+ [0][0][RTW89_UK][0][62] = 127,
+ [0][0][RTW89_FCC][1][64] = -18,
+ [0][0][RTW89_FCC][2][64] = 56,
+ [0][0][RTW89_ETSI][1][64] = 127,
+ [0][0][RTW89_ETSI][0][64] = 127,
+ [0][0][RTW89_MKK][1][64] = 127,
+ [0][0][RTW89_MKK][0][64] = 127,
+ [0][0][RTW89_IC][1][64] = -18,
+ [0][0][RTW89_KCC][1][64] = -2,
+ [0][0][RTW89_KCC][0][64] = 127,
+ [0][0][RTW89_ACMA][1][64] = 127,
+ [0][0][RTW89_ACMA][0][64] = 127,
+ [0][0][RTW89_CHILE][1][64] = 127,
+ [0][0][RTW89_QATAR][1][64] = 127,
+ [0][0][RTW89_QATAR][0][64] = 127,
+ [0][0][RTW89_UK][1][64] = 127,
+ [0][0][RTW89_UK][0][64] = 127,
+ [0][0][RTW89_FCC][1][66] = -18,
+ [0][0][RTW89_FCC][2][66] = 56,
+ [0][0][RTW89_ETSI][1][66] = 127,
+ [0][0][RTW89_ETSI][0][66] = 127,
+ [0][0][RTW89_MKK][1][66] = 127,
+ [0][0][RTW89_MKK][0][66] = 127,
+ [0][0][RTW89_IC][1][66] = -18,
+ [0][0][RTW89_KCC][1][66] = -2,
+ [0][0][RTW89_KCC][0][66] = 127,
+ [0][0][RTW89_ACMA][1][66] = 127,
+ [0][0][RTW89_ACMA][0][66] = 127,
+ [0][0][RTW89_CHILE][1][66] = 127,
+ [0][0][RTW89_QATAR][1][66] = 127,
+ [0][0][RTW89_QATAR][0][66] = 127,
+ [0][0][RTW89_UK][1][66] = 127,
+ [0][0][RTW89_UK][0][66] = 127,
+ [0][0][RTW89_FCC][1][68] = -18,
+ [0][0][RTW89_FCC][2][68] = 56,
+ [0][0][RTW89_ETSI][1][68] = 127,
+ [0][0][RTW89_ETSI][0][68] = 127,
+ [0][0][RTW89_MKK][1][68] = 127,
+ [0][0][RTW89_MKK][0][68] = 127,
+ [0][0][RTW89_IC][1][68] = -18,
+ [0][0][RTW89_KCC][1][68] = -2,
+ [0][0][RTW89_KCC][0][68] = 127,
+ [0][0][RTW89_ACMA][1][68] = 127,
+ [0][0][RTW89_ACMA][0][68] = 127,
+ [0][0][RTW89_CHILE][1][68] = 127,
+ [0][0][RTW89_QATAR][1][68] = 127,
+ [0][0][RTW89_QATAR][0][68] = 127,
+ [0][0][RTW89_UK][1][68] = 127,
+ [0][0][RTW89_UK][0][68] = 127,
+ [0][0][RTW89_FCC][1][70] = -16,
+ [0][0][RTW89_FCC][2][70] = 56,
+ [0][0][RTW89_ETSI][1][70] = 127,
+ [0][0][RTW89_ETSI][0][70] = 127,
+ [0][0][RTW89_MKK][1][70] = 127,
+ [0][0][RTW89_MKK][0][70] = 127,
+ [0][0][RTW89_IC][1][70] = -16,
+ [0][0][RTW89_KCC][1][70] = -2,
+ [0][0][RTW89_KCC][0][70] = 127,
+ [0][0][RTW89_ACMA][1][70] = 127,
+ [0][0][RTW89_ACMA][0][70] = 127,
+ [0][0][RTW89_CHILE][1][70] = 127,
+ [0][0][RTW89_QATAR][1][70] = 127,
+ [0][0][RTW89_QATAR][0][70] = 127,
+ [0][0][RTW89_UK][1][70] = 127,
+ [0][0][RTW89_UK][0][70] = 127,
+ [0][0][RTW89_FCC][1][72] = -18,
+ [0][0][RTW89_FCC][2][72] = 56,
+ [0][0][RTW89_ETSI][1][72] = 127,
+ [0][0][RTW89_ETSI][0][72] = 127,
+ [0][0][RTW89_MKK][1][72] = 127,
+ [0][0][RTW89_MKK][0][72] = 127,
+ [0][0][RTW89_IC][1][72] = -18,
+ [0][0][RTW89_KCC][1][72] = -2,
+ [0][0][RTW89_KCC][0][72] = 127,
+ [0][0][RTW89_ACMA][1][72] = 127,
+ [0][0][RTW89_ACMA][0][72] = 127,
+ [0][0][RTW89_CHILE][1][72] = 127,
+ [0][0][RTW89_QATAR][1][72] = 127,
+ [0][0][RTW89_QATAR][0][72] = 127,
+ [0][0][RTW89_UK][1][72] = 127,
+ [0][0][RTW89_UK][0][72] = 127,
+ [0][0][RTW89_FCC][1][74] = -18,
+ [0][0][RTW89_FCC][2][74] = 56,
+ [0][0][RTW89_ETSI][1][74] = 127,
+ [0][0][RTW89_ETSI][0][74] = 127,
+ [0][0][RTW89_MKK][1][74] = 127,
+ [0][0][RTW89_MKK][0][74] = 127,
+ [0][0][RTW89_IC][1][74] = -18,
+ [0][0][RTW89_KCC][1][74] = -2,
+ [0][0][RTW89_KCC][0][74] = 127,
+ [0][0][RTW89_ACMA][1][74] = 127,
+ [0][0][RTW89_ACMA][0][74] = 127,
+ [0][0][RTW89_CHILE][1][74] = 127,
+ [0][0][RTW89_QATAR][1][74] = 127,
+ [0][0][RTW89_QATAR][0][74] = 127,
+ [0][0][RTW89_UK][1][74] = 127,
+ [0][0][RTW89_UK][0][74] = 127,
+ [0][0][RTW89_FCC][1][75] = -18,
+ [0][0][RTW89_FCC][2][75] = 56,
+ [0][0][RTW89_ETSI][1][75] = 127,
+ [0][0][RTW89_ETSI][0][75] = 127,
+ [0][0][RTW89_MKK][1][75] = 127,
+ [0][0][RTW89_MKK][0][75] = 127,
+ [0][0][RTW89_IC][1][75] = -18,
+ [0][0][RTW89_KCC][1][75] = -2,
+ [0][0][RTW89_KCC][0][75] = 127,
+ [0][0][RTW89_ACMA][1][75] = 127,
+ [0][0][RTW89_ACMA][0][75] = 127,
+ [0][0][RTW89_CHILE][1][75] = 127,
+ [0][0][RTW89_QATAR][1][75] = 127,
+ [0][0][RTW89_QATAR][0][75] = 127,
+ [0][0][RTW89_UK][1][75] = 127,
+ [0][0][RTW89_UK][0][75] = 127,
+ [0][0][RTW89_FCC][1][77] = -18,
+ [0][0][RTW89_FCC][2][77] = 56,
+ [0][0][RTW89_ETSI][1][77] = 127,
+ [0][0][RTW89_ETSI][0][77] = 127,
+ [0][0][RTW89_MKK][1][77] = 127,
+ [0][0][RTW89_MKK][0][77] = 127,
+ [0][0][RTW89_IC][1][77] = -18,
+ [0][0][RTW89_KCC][1][77] = -2,
+ [0][0][RTW89_KCC][0][77] = 127,
+ [0][0][RTW89_ACMA][1][77] = 127,
+ [0][0][RTW89_ACMA][0][77] = 127,
+ [0][0][RTW89_CHILE][1][77] = 127,
+ [0][0][RTW89_QATAR][1][77] = 127,
+ [0][0][RTW89_QATAR][0][77] = 127,
+ [0][0][RTW89_UK][1][77] = 127,
+ [0][0][RTW89_UK][0][77] = 127,
+ [0][0][RTW89_FCC][1][79] = -18,
+ [0][0][RTW89_FCC][2][79] = 56,
+ [0][0][RTW89_ETSI][1][79] = 127,
+ [0][0][RTW89_ETSI][0][79] = 127,
+ [0][0][RTW89_MKK][1][79] = 127,
+ [0][0][RTW89_MKK][0][79] = 127,
+ [0][0][RTW89_IC][1][79] = -18,
+ [0][0][RTW89_KCC][1][79] = -2,
+ [0][0][RTW89_KCC][0][79] = 127,
+ [0][0][RTW89_ACMA][1][79] = 127,
+ [0][0][RTW89_ACMA][0][79] = 127,
+ [0][0][RTW89_CHILE][1][79] = 127,
+ [0][0][RTW89_QATAR][1][79] = 127,
+ [0][0][RTW89_QATAR][0][79] = 127,
+ [0][0][RTW89_UK][1][79] = 127,
+ [0][0][RTW89_UK][0][79] = 127,
+ [0][0][RTW89_FCC][1][81] = -18,
+ [0][0][RTW89_FCC][2][81] = 56,
+ [0][0][RTW89_ETSI][1][81] = 127,
+ [0][0][RTW89_ETSI][0][81] = 127,
+ [0][0][RTW89_MKK][1][81] = 127,
+ [0][0][RTW89_MKK][0][81] = 127,
+ [0][0][RTW89_IC][1][81] = -18,
+ [0][0][RTW89_KCC][1][81] = -2,
+ [0][0][RTW89_KCC][0][81] = 127,
+ [0][0][RTW89_ACMA][1][81] = 127,
+ [0][0][RTW89_ACMA][0][81] = 127,
+ [0][0][RTW89_CHILE][1][81] = 127,
+ [0][0][RTW89_QATAR][1][81] = 127,
+ [0][0][RTW89_QATAR][0][81] = 127,
+ [0][0][RTW89_UK][1][81] = 127,
+ [0][0][RTW89_UK][0][81] = 127,
+ [0][0][RTW89_FCC][1][83] = -18,
+ [0][0][RTW89_FCC][2][83] = 56,
+ [0][0][RTW89_ETSI][1][83] = 127,
+ [0][0][RTW89_ETSI][0][83] = 127,
+ [0][0][RTW89_MKK][1][83] = 127,
+ [0][0][RTW89_MKK][0][83] = 127,
+ [0][0][RTW89_IC][1][83] = -18,
+ [0][0][RTW89_KCC][1][83] = -2,
+ [0][0][RTW89_KCC][0][83] = 127,
+ [0][0][RTW89_ACMA][1][83] = 127,
+ [0][0][RTW89_ACMA][0][83] = 127,
+ [0][0][RTW89_CHILE][1][83] = 127,
+ [0][0][RTW89_QATAR][1][83] = 127,
+ [0][0][RTW89_QATAR][0][83] = 127,
+ [0][0][RTW89_UK][1][83] = 127,
+ [0][0][RTW89_UK][0][83] = 127,
+ [0][0][RTW89_FCC][1][85] = -18,
+ [0][0][RTW89_FCC][2][85] = 56,
+ [0][0][RTW89_ETSI][1][85] = 127,
+ [0][0][RTW89_ETSI][0][85] = 127,
+ [0][0][RTW89_MKK][1][85] = 127,
+ [0][0][RTW89_MKK][0][85] = 127,
+ [0][0][RTW89_IC][1][85] = -18,
+ [0][0][RTW89_KCC][1][85] = -2,
+ [0][0][RTW89_KCC][0][85] = 127,
+ [0][0][RTW89_ACMA][1][85] = 127,
+ [0][0][RTW89_ACMA][0][85] = 127,
+ [0][0][RTW89_CHILE][1][85] = 127,
+ [0][0][RTW89_QATAR][1][85] = 127,
+ [0][0][RTW89_QATAR][0][85] = 127,
+ [0][0][RTW89_UK][1][85] = 127,
+ [0][0][RTW89_UK][0][85] = 127,
+ [0][0][RTW89_FCC][1][87] = -16,
+ [0][0][RTW89_FCC][2][87] = 127,
+ [0][0][RTW89_ETSI][1][87] = 127,
+ [0][0][RTW89_ETSI][0][87] = 127,
+ [0][0][RTW89_MKK][1][87] = 127,
+ [0][0][RTW89_MKK][0][87] = 127,
+ [0][0][RTW89_IC][1][87] = -16,
+ [0][0][RTW89_KCC][1][87] = -2,
+ [0][0][RTW89_KCC][0][87] = 127,
+ [0][0][RTW89_ACMA][1][87] = 127,
+ [0][0][RTW89_ACMA][0][87] = 127,
+ [0][0][RTW89_CHILE][1][87] = 127,
+ [0][0][RTW89_QATAR][1][87] = 127,
+ [0][0][RTW89_QATAR][0][87] = 127,
+ [0][0][RTW89_UK][1][87] = 127,
+ [0][0][RTW89_UK][0][87] = 127,
+ [0][0][RTW89_FCC][1][89] = -16,
+ [0][0][RTW89_FCC][2][89] = 127,
+ [0][0][RTW89_ETSI][1][89] = 127,
+ [0][0][RTW89_ETSI][0][89] = 127,
+ [0][0][RTW89_MKK][1][89] = 127,
+ [0][0][RTW89_MKK][0][89] = 127,
+ [0][0][RTW89_IC][1][89] = -16,
+ [0][0][RTW89_KCC][1][89] = -2,
+ [0][0][RTW89_KCC][0][89] = 127,
+ [0][0][RTW89_ACMA][1][89] = 127,
+ [0][0][RTW89_ACMA][0][89] = 127,
+ [0][0][RTW89_CHILE][1][89] = 127,
+ [0][0][RTW89_QATAR][1][89] = 127,
+ [0][0][RTW89_QATAR][0][89] = 127,
+ [0][0][RTW89_UK][1][89] = 127,
+ [0][0][RTW89_UK][0][89] = 127,
+ [0][0][RTW89_FCC][1][90] = -16,
+ [0][0][RTW89_FCC][2][90] = 127,
+ [0][0][RTW89_ETSI][1][90] = 127,
+ [0][0][RTW89_ETSI][0][90] = 127,
+ [0][0][RTW89_MKK][1][90] = 127,
+ [0][0][RTW89_MKK][0][90] = 127,
+ [0][0][RTW89_IC][1][90] = -16,
+ [0][0][RTW89_KCC][1][90] = -2,
+ [0][0][RTW89_KCC][0][90] = 127,
+ [0][0][RTW89_ACMA][1][90] = 127,
+ [0][0][RTW89_ACMA][0][90] = 127,
+ [0][0][RTW89_CHILE][1][90] = 127,
+ [0][0][RTW89_QATAR][1][90] = 127,
+ [0][0][RTW89_QATAR][0][90] = 127,
+ [0][0][RTW89_UK][1][90] = 127,
+ [0][0][RTW89_UK][0][90] = 127,
+ [0][0][RTW89_FCC][1][92] = -16,
+ [0][0][RTW89_FCC][2][92] = 127,
+ [0][0][RTW89_ETSI][1][92] = 127,
+ [0][0][RTW89_ETSI][0][92] = 127,
+ [0][0][RTW89_MKK][1][92] = 127,
+ [0][0][RTW89_MKK][0][92] = 127,
+ [0][0][RTW89_IC][1][92] = -16,
+ [0][0][RTW89_KCC][1][92] = -2,
+ [0][0][RTW89_KCC][0][92] = 127,
+ [0][0][RTW89_ACMA][1][92] = 127,
+ [0][0][RTW89_ACMA][0][92] = 127,
+ [0][0][RTW89_CHILE][1][92] = 127,
+ [0][0][RTW89_QATAR][1][92] = 127,
+ [0][0][RTW89_QATAR][0][92] = 127,
+ [0][0][RTW89_UK][1][92] = 127,
+ [0][0][RTW89_UK][0][92] = 127,
+ [0][0][RTW89_FCC][1][94] = -16,
+ [0][0][RTW89_FCC][2][94] = 127,
+ [0][0][RTW89_ETSI][1][94] = 127,
+ [0][0][RTW89_ETSI][0][94] = 127,
+ [0][0][RTW89_MKK][1][94] = 127,
+ [0][0][RTW89_MKK][0][94] = 127,
+ [0][0][RTW89_IC][1][94] = -16,
+ [0][0][RTW89_KCC][1][94] = -2,
+ [0][0][RTW89_KCC][0][94] = 127,
+ [0][0][RTW89_ACMA][1][94] = 127,
+ [0][0][RTW89_ACMA][0][94] = 127,
+ [0][0][RTW89_CHILE][1][94] = 127,
+ [0][0][RTW89_QATAR][1][94] = 127,
+ [0][0][RTW89_QATAR][0][94] = 127,
+ [0][0][RTW89_UK][1][94] = 127,
+ [0][0][RTW89_UK][0][94] = 127,
+ [0][0][RTW89_FCC][1][96] = -16,
+ [0][0][RTW89_FCC][2][96] = 127,
+ [0][0][RTW89_ETSI][1][96] = 127,
+ [0][0][RTW89_ETSI][0][96] = 127,
+ [0][0][RTW89_MKK][1][96] = 127,
+ [0][0][RTW89_MKK][0][96] = 127,
+ [0][0][RTW89_IC][1][96] = -16,
+ [0][0][RTW89_KCC][1][96] = -2,
+ [0][0][RTW89_KCC][0][96] = 127,
+ [0][0][RTW89_ACMA][1][96] = 127,
+ [0][0][RTW89_ACMA][0][96] = 127,
+ [0][0][RTW89_CHILE][1][96] = 127,
+ [0][0][RTW89_QATAR][1][96] = 127,
+ [0][0][RTW89_QATAR][0][96] = 127,
+ [0][0][RTW89_UK][1][96] = 127,
+ [0][0][RTW89_UK][0][96] = 127,
+ [0][0][RTW89_FCC][1][98] = -16,
+ [0][0][RTW89_FCC][2][98] = 127,
+ [0][0][RTW89_ETSI][1][98] = 127,
+ [0][0][RTW89_ETSI][0][98] = 127,
+ [0][0][RTW89_MKK][1][98] = 127,
+ [0][0][RTW89_MKK][0][98] = 127,
+ [0][0][RTW89_IC][1][98] = -16,
+ [0][0][RTW89_KCC][1][98] = -2,
+ [0][0][RTW89_KCC][0][98] = 127,
+ [0][0][RTW89_ACMA][1][98] = 127,
+ [0][0][RTW89_ACMA][0][98] = 127,
+ [0][0][RTW89_CHILE][1][98] = 127,
+ [0][0][RTW89_QATAR][1][98] = 127,
+ [0][0][RTW89_QATAR][0][98] = 127,
+ [0][0][RTW89_UK][1][98] = 127,
+ [0][0][RTW89_UK][0][98] = 127,
+ [0][0][RTW89_FCC][1][100] = -16,
+ [0][0][RTW89_FCC][2][100] = 127,
+ [0][0][RTW89_ETSI][1][100] = 127,
+ [0][0][RTW89_ETSI][0][100] = 127,
+ [0][0][RTW89_MKK][1][100] = 127,
+ [0][0][RTW89_MKK][0][100] = 127,
+ [0][0][RTW89_IC][1][100] = -16,
+ [0][0][RTW89_KCC][1][100] = -2,
+ [0][0][RTW89_KCC][0][100] = 127,
+ [0][0][RTW89_ACMA][1][100] = 127,
+ [0][0][RTW89_ACMA][0][100] = 127,
+ [0][0][RTW89_CHILE][1][100] = 127,
+ [0][0][RTW89_QATAR][1][100] = 127,
+ [0][0][RTW89_QATAR][0][100] = 127,
+ [0][0][RTW89_UK][1][100] = 127,
+ [0][0][RTW89_UK][0][100] = 127,
+ [0][0][RTW89_FCC][1][102] = -16,
+ [0][0][RTW89_FCC][2][102] = 127,
+ [0][0][RTW89_ETSI][1][102] = 127,
+ [0][0][RTW89_ETSI][0][102] = 127,
+ [0][0][RTW89_MKK][1][102] = 127,
+ [0][0][RTW89_MKK][0][102] = 127,
+ [0][0][RTW89_IC][1][102] = -16,
+ [0][0][RTW89_KCC][1][102] = -2,
+ [0][0][RTW89_KCC][0][102] = 127,
+ [0][0][RTW89_ACMA][1][102] = 127,
+ [0][0][RTW89_ACMA][0][102] = 127,
+ [0][0][RTW89_CHILE][1][102] = 127,
+ [0][0][RTW89_QATAR][1][102] = 127,
+ [0][0][RTW89_QATAR][0][102] = 127,
+ [0][0][RTW89_UK][1][102] = 127,
+ [0][0][RTW89_UK][0][102] = 127,
+ [0][0][RTW89_FCC][1][104] = -16,
+ [0][0][RTW89_FCC][2][104] = 127,
+ [0][0][RTW89_ETSI][1][104] = 127,
+ [0][0][RTW89_ETSI][0][104] = 127,
+ [0][0][RTW89_MKK][1][104] = 127,
+ [0][0][RTW89_MKK][0][104] = 127,
+ [0][0][RTW89_IC][1][104] = -16,
+ [0][0][RTW89_KCC][1][104] = -2,
+ [0][0][RTW89_KCC][0][104] = 127,
+ [0][0][RTW89_ACMA][1][104] = 127,
+ [0][0][RTW89_ACMA][0][104] = 127,
+ [0][0][RTW89_CHILE][1][104] = 127,
+ [0][0][RTW89_QATAR][1][104] = 127,
+ [0][0][RTW89_QATAR][0][104] = 127,
+ [0][0][RTW89_UK][1][104] = 127,
+ [0][0][RTW89_UK][0][104] = 127,
+ [0][0][RTW89_FCC][1][105] = -16,
+ [0][0][RTW89_FCC][2][105] = 127,
+ [0][0][RTW89_ETSI][1][105] = 127,
+ [0][0][RTW89_ETSI][0][105] = 127,
+ [0][0][RTW89_MKK][1][105] = 127,
+ [0][0][RTW89_MKK][0][105] = 127,
+ [0][0][RTW89_IC][1][105] = -16,
+ [0][0][RTW89_KCC][1][105] = -2,
+ [0][0][RTW89_KCC][0][105] = 127,
+ [0][0][RTW89_ACMA][1][105] = 127,
+ [0][0][RTW89_ACMA][0][105] = 127,
+ [0][0][RTW89_CHILE][1][105] = 127,
+ [0][0][RTW89_QATAR][1][105] = 127,
+ [0][0][RTW89_QATAR][0][105] = 127,
+ [0][0][RTW89_UK][1][105] = 127,
+ [0][0][RTW89_UK][0][105] = 127,
+ [0][0][RTW89_FCC][1][107] = -12,
+ [0][0][RTW89_FCC][2][107] = 127,
+ [0][0][RTW89_ETSI][1][107] = 127,
+ [0][0][RTW89_ETSI][0][107] = 127,
+ [0][0][RTW89_MKK][1][107] = 127,
+ [0][0][RTW89_MKK][0][107] = 127,
+ [0][0][RTW89_IC][1][107] = -12,
+ [0][0][RTW89_KCC][1][107] = -2,
+ [0][0][RTW89_KCC][0][107] = 127,
+ [0][0][RTW89_ACMA][1][107] = 127,
+ [0][0][RTW89_ACMA][0][107] = 127,
+ [0][0][RTW89_CHILE][1][107] = 127,
+ [0][0][RTW89_QATAR][1][107] = 127,
+ [0][0][RTW89_QATAR][0][107] = 127,
+ [0][0][RTW89_UK][1][107] = 127,
+ [0][0][RTW89_UK][0][107] = 127,
+ [0][0][RTW89_FCC][1][109] = -12,
+ [0][0][RTW89_FCC][2][109] = 127,
+ [0][0][RTW89_ETSI][1][109] = 127,
+ [0][0][RTW89_ETSI][0][109] = 127,
+ [0][0][RTW89_MKK][1][109] = 127,
+ [0][0][RTW89_MKK][0][109] = 127,
+ [0][0][RTW89_IC][1][109] = -12,
+ [0][0][RTW89_KCC][1][109] = 127,
+ [0][0][RTW89_KCC][0][109] = 127,
+ [0][0][RTW89_ACMA][1][109] = 127,
+ [0][0][RTW89_ACMA][0][109] = 127,
+ [0][0][RTW89_CHILE][1][109] = 127,
+ [0][0][RTW89_QATAR][1][109] = 127,
+ [0][0][RTW89_QATAR][0][109] = 127,
+ [0][0][RTW89_UK][1][109] = 127,
+ [0][0][RTW89_UK][0][109] = 127,
+ [0][0][RTW89_FCC][1][111] = 127,
+ [0][0][RTW89_FCC][2][111] = 127,
+ [0][0][RTW89_ETSI][1][111] = 127,
+ [0][0][RTW89_ETSI][0][111] = 127,
+ [0][0][RTW89_MKK][1][111] = 127,
+ [0][0][RTW89_MKK][0][111] = 127,
+ [0][0][RTW89_IC][1][111] = 127,
+ [0][0][RTW89_KCC][1][111] = 127,
+ [0][0][RTW89_KCC][0][111] = 127,
+ [0][0][RTW89_ACMA][1][111] = 127,
+ [0][0][RTW89_ACMA][0][111] = 127,
+ [0][0][RTW89_CHILE][1][111] = 127,
+ [0][0][RTW89_QATAR][1][111] = 127,
+ [0][0][RTW89_QATAR][0][111] = 127,
+ [0][0][RTW89_UK][1][111] = 127,
+ [0][0][RTW89_UK][0][111] = 127,
+ [0][0][RTW89_FCC][1][113] = 127,
+ [0][0][RTW89_FCC][2][113] = 127,
+ [0][0][RTW89_ETSI][1][113] = 127,
+ [0][0][RTW89_ETSI][0][113] = 127,
+ [0][0][RTW89_MKK][1][113] = 127,
+ [0][0][RTW89_MKK][0][113] = 127,
+ [0][0][RTW89_IC][1][113] = 127,
+ [0][0][RTW89_KCC][1][113] = 127,
+ [0][0][RTW89_KCC][0][113] = 127,
+ [0][0][RTW89_ACMA][1][113] = 127,
+ [0][0][RTW89_ACMA][0][113] = 127,
+ [0][0][RTW89_CHILE][1][113] = 127,
+ [0][0][RTW89_QATAR][1][113] = 127,
+ [0][0][RTW89_QATAR][0][113] = 127,
+ [0][0][RTW89_UK][1][113] = 127,
+ [0][0][RTW89_UK][0][113] = 127,
+ [0][0][RTW89_FCC][1][115] = 127,
+ [0][0][RTW89_FCC][2][115] = 127,
+ [0][0][RTW89_ETSI][1][115] = 127,
+ [0][0][RTW89_ETSI][0][115] = 127,
+ [0][0][RTW89_MKK][1][115] = 127,
+ [0][0][RTW89_MKK][0][115] = 127,
+ [0][0][RTW89_IC][1][115] = 127,
+ [0][0][RTW89_KCC][1][115] = 127,
+ [0][0][RTW89_KCC][0][115] = 127,
+ [0][0][RTW89_ACMA][1][115] = 127,
+ [0][0][RTW89_ACMA][0][115] = 127,
+ [0][0][RTW89_CHILE][1][115] = 127,
+ [0][0][RTW89_QATAR][1][115] = 127,
+ [0][0][RTW89_QATAR][0][115] = 127,
+ [0][0][RTW89_UK][1][115] = 127,
+ [0][0][RTW89_UK][0][115] = 127,
+ [0][0][RTW89_FCC][1][117] = 127,
+ [0][0][RTW89_FCC][2][117] = 127,
+ [0][0][RTW89_ETSI][1][117] = 127,
+ [0][0][RTW89_ETSI][0][117] = 127,
+ [0][0][RTW89_MKK][1][117] = 127,
+ [0][0][RTW89_MKK][0][117] = 127,
+ [0][0][RTW89_IC][1][117] = 127,
+ [0][0][RTW89_KCC][1][117] = 127,
+ [0][0][RTW89_KCC][0][117] = 127,
+ [0][0][RTW89_ACMA][1][117] = 127,
+ [0][0][RTW89_ACMA][0][117] = 127,
+ [0][0][RTW89_CHILE][1][117] = 127,
+ [0][0][RTW89_QATAR][1][117] = 127,
+ [0][0][RTW89_QATAR][0][117] = 127,
+ [0][0][RTW89_UK][1][117] = 127,
+ [0][0][RTW89_UK][0][117] = 127,
+ [0][0][RTW89_FCC][1][119] = 127,
+ [0][0][RTW89_FCC][2][119] = 127,
+ [0][0][RTW89_ETSI][1][119] = 127,
+ [0][0][RTW89_ETSI][0][119] = 127,
+ [0][0][RTW89_MKK][1][119] = 127,
+ [0][0][RTW89_MKK][0][119] = 127,
+ [0][0][RTW89_IC][1][119] = 127,
+ [0][0][RTW89_KCC][1][119] = 127,
+ [0][0][RTW89_KCC][0][119] = 127,
+ [0][0][RTW89_ACMA][1][119] = 127,
+ [0][0][RTW89_ACMA][0][119] = 127,
+ [0][0][RTW89_CHILE][1][119] = 127,
+ [0][0][RTW89_QATAR][1][119] = 127,
+ [0][0][RTW89_QATAR][0][119] = 127,
+ [0][0][RTW89_UK][1][119] = 127,
+ [0][0][RTW89_UK][0][119] = 127,
+ [0][1][RTW89_FCC][1][0] = -40,
+ [0][1][RTW89_FCC][2][0] = 32,
+ [0][1][RTW89_ETSI][1][0] = 20,
+ [0][1][RTW89_ETSI][0][0] = -18,
+ [0][1][RTW89_MKK][1][0] = 18,
+ [0][1][RTW89_MKK][0][0] = -20,
+ [0][1][RTW89_IC][1][0] = -40,
+ [0][1][RTW89_KCC][1][0] = -14,
+ [0][1][RTW89_KCC][0][0] = -14,
+ [0][1][RTW89_ACMA][1][0] = 20,
+ [0][1][RTW89_ACMA][0][0] = -18,
+ [0][1][RTW89_CHILE][1][0] = -40,
+ [0][1][RTW89_QATAR][1][0] = 20,
+ [0][1][RTW89_QATAR][0][0] = -18,
+ [0][1][RTW89_UK][1][0] = 20,
+ [0][1][RTW89_UK][0][0] = -18,
+ [0][1][RTW89_FCC][1][2] = -40,
+ [0][1][RTW89_FCC][2][2] = 32,
+ [0][1][RTW89_ETSI][1][2] = 20,
+ [0][1][RTW89_ETSI][0][2] = -18,
+ [0][1][RTW89_MKK][1][2] = 18,
+ [0][1][RTW89_MKK][0][2] = -22,
+ [0][1][RTW89_IC][1][2] = -40,
+ [0][1][RTW89_KCC][1][2] = -14,
+ [0][1][RTW89_KCC][0][2] = -14,
+ [0][1][RTW89_ACMA][1][2] = 20,
+ [0][1][RTW89_ACMA][0][2] = -18,
+ [0][1][RTW89_CHILE][1][2] = -40,
+ [0][1][RTW89_QATAR][1][2] = 20,
+ [0][1][RTW89_QATAR][0][2] = -18,
+ [0][1][RTW89_UK][1][2] = 20,
+ [0][1][RTW89_UK][0][2] = -18,
+ [0][1][RTW89_FCC][1][4] = -40,
+ [0][1][RTW89_FCC][2][4] = 32,
+ [0][1][RTW89_ETSI][1][4] = 20,
+ [0][1][RTW89_ETSI][0][4] = -18,
+ [0][1][RTW89_MKK][1][4] = 18,
+ [0][1][RTW89_MKK][0][4] = -22,
+ [0][1][RTW89_IC][1][4] = -40,
+ [0][1][RTW89_KCC][1][4] = -14,
+ [0][1][RTW89_KCC][0][4] = -14,
+ [0][1][RTW89_ACMA][1][4] = 20,
+ [0][1][RTW89_ACMA][0][4] = -18,
+ [0][1][RTW89_CHILE][1][4] = -40,
+ [0][1][RTW89_QATAR][1][4] = 20,
+ [0][1][RTW89_QATAR][0][4] = -18,
+ [0][1][RTW89_UK][1][4] = 20,
+ [0][1][RTW89_UK][0][4] = -18,
+ [0][1][RTW89_FCC][1][6] = -40,
+ [0][1][RTW89_FCC][2][6] = 32,
+ [0][1][RTW89_ETSI][1][6] = 20,
+ [0][1][RTW89_ETSI][0][6] = -18,
+ [0][1][RTW89_MKK][1][6] = 18,
+ [0][1][RTW89_MKK][0][6] = -22,
+ [0][1][RTW89_IC][1][6] = -40,
+ [0][1][RTW89_KCC][1][6] = -14,
+ [0][1][RTW89_KCC][0][6] = -14,
+ [0][1][RTW89_ACMA][1][6] = 20,
+ [0][1][RTW89_ACMA][0][6] = -18,
+ [0][1][RTW89_CHILE][1][6] = -40,
+ [0][1][RTW89_QATAR][1][6] = 20,
+ [0][1][RTW89_QATAR][0][6] = -18,
+ [0][1][RTW89_UK][1][6] = 20,
+ [0][1][RTW89_UK][0][6] = -18,
+ [0][1][RTW89_FCC][1][8] = -40,
+ [0][1][RTW89_FCC][2][8] = 32,
+ [0][1][RTW89_ETSI][1][8] = 20,
+ [0][1][RTW89_ETSI][0][8] = -18,
+ [0][1][RTW89_MKK][1][8] = 18,
+ [0][1][RTW89_MKK][0][8] = -22,
+ [0][1][RTW89_IC][1][8] = -40,
+ [0][1][RTW89_KCC][1][8] = -14,
+ [0][1][RTW89_KCC][0][8] = -14,
+ [0][1][RTW89_ACMA][1][8] = 20,
+ [0][1][RTW89_ACMA][0][8] = -18,
+ [0][1][RTW89_CHILE][1][8] = -40,
+ [0][1][RTW89_QATAR][1][8] = 20,
+ [0][1][RTW89_QATAR][0][8] = -18,
+ [0][1][RTW89_UK][1][8] = 20,
+ [0][1][RTW89_UK][0][8] = -18,
+ [0][1][RTW89_FCC][1][10] = -40,
+ [0][1][RTW89_FCC][2][10] = 32,
+ [0][1][RTW89_ETSI][1][10] = 20,
+ [0][1][RTW89_ETSI][0][10] = -18,
+ [0][1][RTW89_MKK][1][10] = 18,
+ [0][1][RTW89_MKK][0][10] = -22,
+ [0][1][RTW89_IC][1][10] = -40,
+ [0][1][RTW89_KCC][1][10] = -14,
+ [0][1][RTW89_KCC][0][10] = -14,
+ [0][1][RTW89_ACMA][1][10] = 20,
+ [0][1][RTW89_ACMA][0][10] = -18,
+ [0][1][RTW89_CHILE][1][10] = -40,
+ [0][1][RTW89_QATAR][1][10] = 20,
+ [0][1][RTW89_QATAR][0][10] = -18,
+ [0][1][RTW89_UK][1][10] = 20,
+ [0][1][RTW89_UK][0][10] = -18,
+ [0][1][RTW89_FCC][1][12] = -40,
+ [0][1][RTW89_FCC][2][12] = 32,
+ [0][1][RTW89_ETSI][1][12] = 20,
+ [0][1][RTW89_ETSI][0][12] = -18,
+ [0][1][RTW89_MKK][1][12] = 18,
+ [0][1][RTW89_MKK][0][12] = -22,
+ [0][1][RTW89_IC][1][12] = -40,
+ [0][1][RTW89_KCC][1][12] = -14,
+ [0][1][RTW89_KCC][0][12] = -14,
+ [0][1][RTW89_ACMA][1][12] = 20,
+ [0][1][RTW89_ACMA][0][12] = -18,
+ [0][1][RTW89_CHILE][1][12] = -40,
+ [0][1][RTW89_QATAR][1][12] = 20,
+ [0][1][RTW89_QATAR][0][12] = -18,
+ [0][1][RTW89_UK][1][12] = 20,
+ [0][1][RTW89_UK][0][12] = -18,
+ [0][1][RTW89_FCC][1][14] = -40,
+ [0][1][RTW89_FCC][2][14] = 32,
+ [0][1][RTW89_ETSI][1][14] = 20,
+ [0][1][RTW89_ETSI][0][14] = -18,
+ [0][1][RTW89_MKK][1][14] = 18,
+ [0][1][RTW89_MKK][0][14] = -22,
+ [0][1][RTW89_IC][1][14] = -40,
+ [0][1][RTW89_KCC][1][14] = -14,
+ [0][1][RTW89_KCC][0][14] = -14,
+ [0][1][RTW89_ACMA][1][14] = 20,
+ [0][1][RTW89_ACMA][0][14] = -18,
+ [0][1][RTW89_CHILE][1][14] = -40,
+ [0][1][RTW89_QATAR][1][14] = 20,
+ [0][1][RTW89_QATAR][0][14] = -18,
+ [0][1][RTW89_UK][1][14] = 20,
+ [0][1][RTW89_UK][0][14] = -18,
+ [0][1][RTW89_FCC][1][15] = -40,
+ [0][1][RTW89_FCC][2][15] = 32,
+ [0][1][RTW89_ETSI][1][15] = 20,
+ [0][1][RTW89_ETSI][0][15] = -18,
+ [0][1][RTW89_MKK][1][15] = 18,
+ [0][1][RTW89_MKK][0][15] = -22,
+ [0][1][RTW89_IC][1][15] = -40,
+ [0][1][RTW89_KCC][1][15] = -14,
+ [0][1][RTW89_KCC][0][15] = -14,
+ [0][1][RTW89_ACMA][1][15] = 20,
+ [0][1][RTW89_ACMA][0][15] = -18,
+ [0][1][RTW89_CHILE][1][15] = -40,
+ [0][1][RTW89_QATAR][1][15] = 20,
+ [0][1][RTW89_QATAR][0][15] = -18,
+ [0][1][RTW89_UK][1][15] = 20,
+ [0][1][RTW89_UK][0][15] = -18,
+ [0][1][RTW89_FCC][1][17] = -40,
+ [0][1][RTW89_FCC][2][17] = 32,
+ [0][1][RTW89_ETSI][1][17] = 20,
+ [0][1][RTW89_ETSI][0][17] = -18,
+ [0][1][RTW89_MKK][1][17] = 18,
+ [0][1][RTW89_MKK][0][17] = -22,
+ [0][1][RTW89_IC][1][17] = -40,
+ [0][1][RTW89_KCC][1][17] = -14,
+ [0][1][RTW89_KCC][0][17] = -14,
+ [0][1][RTW89_ACMA][1][17] = 20,
+ [0][1][RTW89_ACMA][0][17] = -18,
+ [0][1][RTW89_CHILE][1][17] = -40,
+ [0][1][RTW89_QATAR][1][17] = 20,
+ [0][1][RTW89_QATAR][0][17] = -18,
+ [0][1][RTW89_UK][1][17] = 20,
+ [0][1][RTW89_UK][0][17] = -18,
+ [0][1][RTW89_FCC][1][19] = -40,
+ [0][1][RTW89_FCC][2][19] = 32,
+ [0][1][RTW89_ETSI][1][19] = 20,
+ [0][1][RTW89_ETSI][0][19] = -18,
+ [0][1][RTW89_MKK][1][19] = 18,
+ [0][1][RTW89_MKK][0][19] = -22,
+ [0][1][RTW89_IC][1][19] = -40,
+ [0][1][RTW89_KCC][1][19] = -14,
+ [0][1][RTW89_KCC][0][19] = -14,
+ [0][1][RTW89_ACMA][1][19] = 20,
+ [0][1][RTW89_ACMA][0][19] = -18,
+ [0][1][RTW89_CHILE][1][19] = -40,
+ [0][1][RTW89_QATAR][1][19] = 20,
+ [0][1][RTW89_QATAR][0][19] = -18,
+ [0][1][RTW89_UK][1][19] = 20,
+ [0][1][RTW89_UK][0][19] = -18,
+ [0][1][RTW89_FCC][1][21] = -40,
+ [0][1][RTW89_FCC][2][21] = 32,
+ [0][1][RTW89_ETSI][1][21] = 20,
+ [0][1][RTW89_ETSI][0][21] = -18,
+ [0][1][RTW89_MKK][1][21] = 18,
+ [0][1][RTW89_MKK][0][21] = -22,
+ [0][1][RTW89_IC][1][21] = -40,
+ [0][1][RTW89_KCC][1][21] = -14,
+ [0][1][RTW89_KCC][0][21] = -14,
+ [0][1][RTW89_ACMA][1][21] = 20,
+ [0][1][RTW89_ACMA][0][21] = -18,
+ [0][1][RTW89_CHILE][1][21] = -40,
+ [0][1][RTW89_QATAR][1][21] = 20,
+ [0][1][RTW89_QATAR][0][21] = -18,
+ [0][1][RTW89_UK][1][21] = 20,
+ [0][1][RTW89_UK][0][21] = -18,
+ [0][1][RTW89_FCC][1][23] = -40,
+ [0][1][RTW89_FCC][2][23] = 32,
+ [0][1][RTW89_ETSI][1][23] = 20,
+ [0][1][RTW89_ETSI][0][23] = -18,
+ [0][1][RTW89_MKK][1][23] = 18,
+ [0][1][RTW89_MKK][0][23] = -22,
+ [0][1][RTW89_IC][1][23] = -40,
+ [0][1][RTW89_KCC][1][23] = -14,
+ [0][1][RTW89_KCC][0][23] = -14,
+ [0][1][RTW89_ACMA][1][23] = 20,
+ [0][1][RTW89_ACMA][0][23] = -18,
+ [0][1][RTW89_CHILE][1][23] = -40,
+ [0][1][RTW89_QATAR][1][23] = 20,
+ [0][1][RTW89_QATAR][0][23] = -18,
+ [0][1][RTW89_UK][1][23] = 20,
+ [0][1][RTW89_UK][0][23] = -18,
+ [0][1][RTW89_FCC][1][25] = -40,
+ [0][1][RTW89_FCC][2][25] = 32,
+ [0][1][RTW89_ETSI][1][25] = 20,
+ [0][1][RTW89_ETSI][0][25] = -18,
+ [0][1][RTW89_MKK][1][25] = -4,
+ [0][1][RTW89_MKK][0][25] = -22,
+ [0][1][RTW89_IC][1][25] = -40,
+ [0][1][RTW89_KCC][1][25] = -14,
+ [0][1][RTW89_KCC][0][25] = -14,
+ [0][1][RTW89_ACMA][1][25] = 20,
+ [0][1][RTW89_ACMA][0][25] = -18,
+ [0][1][RTW89_CHILE][1][25] = -40,
+ [0][1][RTW89_QATAR][1][25] = 20,
+ [0][1][RTW89_QATAR][0][25] = -18,
+ [0][1][RTW89_UK][1][25] = 20,
+ [0][1][RTW89_UK][0][25] = -18,
+ [0][1][RTW89_FCC][1][27] = -40,
+ [0][1][RTW89_FCC][2][27] = 32,
+ [0][1][RTW89_ETSI][1][27] = 20,
+ [0][1][RTW89_ETSI][0][27] = -18,
+ [0][1][RTW89_MKK][1][27] = -4,
+ [0][1][RTW89_MKK][0][27] = -22,
+ [0][1][RTW89_IC][1][27] = -40,
+ [0][1][RTW89_KCC][1][27] = -14,
+ [0][1][RTW89_KCC][0][27] = -14,
+ [0][1][RTW89_ACMA][1][27] = 20,
+ [0][1][RTW89_ACMA][0][27] = -18,
+ [0][1][RTW89_CHILE][1][27] = -40,
+ [0][1][RTW89_QATAR][1][27] = 20,
+ [0][1][RTW89_QATAR][0][27] = -18,
+ [0][1][RTW89_UK][1][27] = 20,
+ [0][1][RTW89_UK][0][27] = -18,
+ [0][1][RTW89_FCC][1][29] = -40,
+ [0][1][RTW89_FCC][2][29] = 32,
+ [0][1][RTW89_ETSI][1][29] = 20,
+ [0][1][RTW89_ETSI][0][29] = -18,
+ [0][1][RTW89_MKK][1][29] = -4,
+ [0][1][RTW89_MKK][0][29] = -22,
+ [0][1][RTW89_IC][1][29] = -40,
+ [0][1][RTW89_KCC][1][29] = -14,
+ [0][1][RTW89_KCC][0][29] = -14,
+ [0][1][RTW89_ACMA][1][29] = 20,
+ [0][1][RTW89_ACMA][0][29] = -18,
+ [0][1][RTW89_CHILE][1][29] = -40,
+ [0][1][RTW89_QATAR][1][29] = 20,
+ [0][1][RTW89_QATAR][0][29] = -18,
+ [0][1][RTW89_UK][1][29] = 20,
+ [0][1][RTW89_UK][0][29] = -18,
+ [0][1][RTW89_FCC][1][30] = -40,
+ [0][1][RTW89_FCC][2][30] = 32,
+ [0][1][RTW89_ETSI][1][30] = 20,
+ [0][1][RTW89_ETSI][0][30] = -18,
+ [0][1][RTW89_MKK][1][30] = -4,
+ [0][1][RTW89_MKK][0][30] = -22,
+ [0][1][RTW89_IC][1][30] = -40,
+ [0][1][RTW89_KCC][1][30] = -14,
+ [0][1][RTW89_KCC][0][30] = -14,
+ [0][1][RTW89_ACMA][1][30] = 20,
+ [0][1][RTW89_ACMA][0][30] = -18,
+ [0][1][RTW89_CHILE][1][30] = -40,
+ [0][1][RTW89_QATAR][1][30] = 20,
+ [0][1][RTW89_QATAR][0][30] = -18,
+ [0][1][RTW89_UK][1][30] = 20,
+ [0][1][RTW89_UK][0][30] = -18,
+ [0][1][RTW89_FCC][1][32] = -40,
+ [0][1][RTW89_FCC][2][32] = 32,
+ [0][1][RTW89_ETSI][1][32] = 20,
+ [0][1][RTW89_ETSI][0][32] = -18,
+ [0][1][RTW89_MKK][1][32] = -4,
+ [0][1][RTW89_MKK][0][32] = -22,
+ [0][1][RTW89_IC][1][32] = -40,
+ [0][1][RTW89_KCC][1][32] = -14,
+ [0][1][RTW89_KCC][0][32] = -14,
+ [0][1][RTW89_ACMA][1][32] = 20,
+ [0][1][RTW89_ACMA][0][32] = -18,
+ [0][1][RTW89_CHILE][1][32] = -40,
+ [0][1][RTW89_QATAR][1][32] = 20,
+ [0][1][RTW89_QATAR][0][32] = -18,
+ [0][1][RTW89_UK][1][32] = 20,
+ [0][1][RTW89_UK][0][32] = -18,
+ [0][1][RTW89_FCC][1][34] = -40,
+ [0][1][RTW89_FCC][2][34] = 32,
+ [0][1][RTW89_ETSI][1][34] = 20,
+ [0][1][RTW89_ETSI][0][34] = -18,
+ [0][1][RTW89_MKK][1][34] = -4,
+ [0][1][RTW89_MKK][0][34] = -22,
+ [0][1][RTW89_IC][1][34] = -40,
+ [0][1][RTW89_KCC][1][34] = -14,
+ [0][1][RTW89_KCC][0][34] = -14,
+ [0][1][RTW89_ACMA][1][34] = 20,
+ [0][1][RTW89_ACMA][0][34] = -18,
+ [0][1][RTW89_CHILE][1][34] = -40,
+ [0][1][RTW89_QATAR][1][34] = 20,
+ [0][1][RTW89_QATAR][0][34] = -18,
+ [0][1][RTW89_UK][1][34] = 20,
+ [0][1][RTW89_UK][0][34] = -18,
+ [0][1][RTW89_FCC][1][36] = -40,
+ [0][1][RTW89_FCC][2][36] = 32,
+ [0][1][RTW89_ETSI][1][36] = 20,
+ [0][1][RTW89_ETSI][0][36] = -18,
+ [0][1][RTW89_MKK][1][36] = -4,
+ [0][1][RTW89_MKK][0][36] = -22,
+ [0][1][RTW89_IC][1][36] = -40,
+ [0][1][RTW89_KCC][1][36] = -14,
+ [0][1][RTW89_KCC][0][36] = -14,
+ [0][1][RTW89_ACMA][1][36] = 20,
+ [0][1][RTW89_ACMA][0][36] = -18,
+ [0][1][RTW89_CHILE][1][36] = -40,
+ [0][1][RTW89_QATAR][1][36] = 20,
+ [0][1][RTW89_QATAR][0][36] = -18,
+ [0][1][RTW89_UK][1][36] = 20,
+ [0][1][RTW89_UK][0][36] = -18,
+ [0][1][RTW89_FCC][1][38] = -40,
+ [0][1][RTW89_FCC][2][38] = 32,
+ [0][1][RTW89_ETSI][1][38] = 20,
+ [0][1][RTW89_ETSI][0][38] = -18,
+ [0][1][RTW89_MKK][1][38] = -4,
+ [0][1][RTW89_MKK][0][38] = -22,
+ [0][1][RTW89_IC][1][38] = -40,
+ [0][1][RTW89_KCC][1][38] = -14,
+ [0][1][RTW89_KCC][0][38] = -14,
+ [0][1][RTW89_ACMA][1][38] = 20,
+ [0][1][RTW89_ACMA][0][38] = -18,
+ [0][1][RTW89_CHILE][1][38] = -40,
+ [0][1][RTW89_QATAR][1][38] = 20,
+ [0][1][RTW89_QATAR][0][38] = -18,
+ [0][1][RTW89_UK][1][38] = 20,
+ [0][1][RTW89_UK][0][38] = -18,
+ [0][1][RTW89_FCC][1][40] = -40,
+ [0][1][RTW89_FCC][2][40] = 32,
+ [0][1][RTW89_ETSI][1][40] = 20,
+ [0][1][RTW89_ETSI][0][40] = -18,
+ [0][1][RTW89_MKK][1][40] = -4,
+ [0][1][RTW89_MKK][0][40] = -22,
+ [0][1][RTW89_IC][1][40] = -40,
+ [0][1][RTW89_KCC][1][40] = -14,
+ [0][1][RTW89_KCC][0][40] = -14,
+ [0][1][RTW89_ACMA][1][40] = 20,
+ [0][1][RTW89_ACMA][0][40] = -18,
+ [0][1][RTW89_CHILE][1][40] = -40,
+ [0][1][RTW89_QATAR][1][40] = 20,
+ [0][1][RTW89_QATAR][0][40] = -18,
+ [0][1][RTW89_UK][1][40] = 20,
+ [0][1][RTW89_UK][0][40] = -18,
+ [0][1][RTW89_FCC][1][42] = -40,
+ [0][1][RTW89_FCC][2][42] = 32,
+ [0][1][RTW89_ETSI][1][42] = 20,
+ [0][1][RTW89_ETSI][0][42] = -18,
+ [0][1][RTW89_MKK][1][42] = -4,
+ [0][1][RTW89_MKK][0][42] = -22,
+ [0][1][RTW89_IC][1][42] = -40,
+ [0][1][RTW89_KCC][1][42] = -14,
+ [0][1][RTW89_KCC][0][42] = -14,
+ [0][1][RTW89_ACMA][1][42] = 20,
+ [0][1][RTW89_ACMA][0][42] = -18,
+ [0][1][RTW89_CHILE][1][42] = -40,
+ [0][1][RTW89_QATAR][1][42] = 20,
+ [0][1][RTW89_QATAR][0][42] = -18,
+ [0][1][RTW89_UK][1][42] = 20,
+ [0][1][RTW89_UK][0][42] = -18,
+ [0][1][RTW89_FCC][1][44] = -40,
+ [0][1][RTW89_FCC][2][44] = 32,
+ [0][1][RTW89_ETSI][1][44] = 20,
+ [0][1][RTW89_ETSI][0][44] = -18,
+ [0][1][RTW89_MKK][1][44] = -4,
+ [0][1][RTW89_MKK][0][44] = -22,
+ [0][1][RTW89_IC][1][44] = -40,
+ [0][1][RTW89_KCC][1][44] = -14,
+ [0][1][RTW89_KCC][0][44] = -14,
+ [0][1][RTW89_ACMA][1][44] = 20,
+ [0][1][RTW89_ACMA][0][44] = -18,
+ [0][1][RTW89_CHILE][1][44] = -40,
+ [0][1][RTW89_QATAR][1][44] = 20,
+ [0][1][RTW89_QATAR][0][44] = -18,
+ [0][1][RTW89_UK][1][44] = 20,
+ [0][1][RTW89_UK][0][44] = -18,
+ [0][1][RTW89_FCC][1][45] = -40,
+ [0][1][RTW89_FCC][2][45] = 127,
+ [0][1][RTW89_ETSI][1][45] = 127,
+ [0][1][RTW89_ETSI][0][45] = 127,
+ [0][1][RTW89_MKK][1][45] = 127,
+ [0][1][RTW89_MKK][0][45] = 127,
+ [0][1][RTW89_IC][1][45] = -40,
+ [0][1][RTW89_KCC][1][45] = -14,
+ [0][1][RTW89_KCC][0][45] = 127,
+ [0][1][RTW89_ACMA][1][45] = 127,
+ [0][1][RTW89_ACMA][0][45] = 127,
+ [0][1][RTW89_CHILE][1][45] = 127,
+ [0][1][RTW89_QATAR][1][45] = 127,
+ [0][1][RTW89_QATAR][0][45] = 127,
+ [0][1][RTW89_UK][1][45] = 127,
+ [0][1][RTW89_UK][0][45] = 127,
+ [0][1][RTW89_FCC][1][47] = -40,
+ [0][1][RTW89_FCC][2][47] = 127,
+ [0][1][RTW89_ETSI][1][47] = 127,
+ [0][1][RTW89_ETSI][0][47] = 127,
+ [0][1][RTW89_MKK][1][47] = 127,
+ [0][1][RTW89_MKK][0][47] = 127,
+ [0][1][RTW89_IC][1][47] = -40,
+ [0][1][RTW89_KCC][1][47] = -14,
+ [0][1][RTW89_KCC][0][47] = 127,
+ [0][1][RTW89_ACMA][1][47] = 127,
+ [0][1][RTW89_ACMA][0][47] = 127,
+ [0][1][RTW89_CHILE][1][47] = 127,
+ [0][1][RTW89_QATAR][1][47] = 127,
+ [0][1][RTW89_QATAR][0][47] = 127,
+ [0][1][RTW89_UK][1][47] = 127,
+ [0][1][RTW89_UK][0][47] = 127,
+ [0][1][RTW89_FCC][1][49] = -40,
+ [0][1][RTW89_FCC][2][49] = 127,
+ [0][1][RTW89_ETSI][1][49] = 127,
+ [0][1][RTW89_ETSI][0][49] = 127,
+ [0][1][RTW89_MKK][1][49] = 127,
+ [0][1][RTW89_MKK][0][49] = 127,
+ [0][1][RTW89_IC][1][49] = -40,
+ [0][1][RTW89_KCC][1][49] = -14,
+ [0][1][RTW89_KCC][0][49] = 127,
+ [0][1][RTW89_ACMA][1][49] = 127,
+ [0][1][RTW89_ACMA][0][49] = 127,
+ [0][1][RTW89_CHILE][1][49] = 127,
+ [0][1][RTW89_QATAR][1][49] = 127,
+ [0][1][RTW89_QATAR][0][49] = 127,
+ [0][1][RTW89_UK][1][49] = 127,
+ [0][1][RTW89_UK][0][49] = 127,
+ [0][1][RTW89_FCC][1][51] = -40,
+ [0][1][RTW89_FCC][2][51] = 127,
+ [0][1][RTW89_ETSI][1][51] = 127,
+ [0][1][RTW89_ETSI][0][51] = 127,
+ [0][1][RTW89_MKK][1][51] = 127,
+ [0][1][RTW89_MKK][0][51] = 127,
+ [0][1][RTW89_IC][1][51] = -40,
+ [0][1][RTW89_KCC][1][51] = -14,
+ [0][1][RTW89_KCC][0][51] = 127,
+ [0][1][RTW89_ACMA][1][51] = 127,
+ [0][1][RTW89_ACMA][0][51] = 127,
+ [0][1][RTW89_CHILE][1][51] = 127,
+ [0][1][RTW89_QATAR][1][51] = 127,
+ [0][1][RTW89_QATAR][0][51] = 127,
+ [0][1][RTW89_UK][1][51] = 127,
+ [0][1][RTW89_UK][0][51] = 127,
+ [0][1][RTW89_FCC][1][53] = -40,
+ [0][1][RTW89_FCC][2][53] = 127,
+ [0][1][RTW89_ETSI][1][53] = 127,
+ [0][1][RTW89_ETSI][0][53] = 127,
+ [0][1][RTW89_MKK][1][53] = 127,
+ [0][1][RTW89_MKK][0][53] = 127,
+ [0][1][RTW89_IC][1][53] = -40,
+ [0][1][RTW89_KCC][1][53] = -14,
+ [0][1][RTW89_KCC][0][53] = 127,
+ [0][1][RTW89_ACMA][1][53] = 127,
+ [0][1][RTW89_ACMA][0][53] = 127,
+ [0][1][RTW89_CHILE][1][53] = 127,
+ [0][1][RTW89_QATAR][1][53] = 127,
+ [0][1][RTW89_QATAR][0][53] = 127,
+ [0][1][RTW89_UK][1][53] = 127,
+ [0][1][RTW89_UK][0][53] = 127,
+ [0][1][RTW89_FCC][1][55] = -40,
+ [0][1][RTW89_FCC][2][55] = 30,
+ [0][1][RTW89_ETSI][1][55] = 127,
+ [0][1][RTW89_ETSI][0][55] = 127,
+ [0][1][RTW89_MKK][1][55] = 127,
+ [0][1][RTW89_MKK][0][55] = 127,
+ [0][1][RTW89_IC][1][55] = -40,
+ [0][1][RTW89_KCC][1][55] = -14,
+ [0][1][RTW89_KCC][0][55] = 127,
+ [0][1][RTW89_ACMA][1][55] = 127,
+ [0][1][RTW89_ACMA][0][55] = 127,
+ [0][1][RTW89_CHILE][1][55] = 127,
+ [0][1][RTW89_QATAR][1][55] = 127,
+ [0][1][RTW89_QATAR][0][55] = 127,
+ [0][1][RTW89_UK][1][55] = 127,
+ [0][1][RTW89_UK][0][55] = 127,
+ [0][1][RTW89_FCC][1][57] = -40,
+ [0][1][RTW89_FCC][2][57] = 30,
+ [0][1][RTW89_ETSI][1][57] = 127,
+ [0][1][RTW89_ETSI][0][57] = 127,
+ [0][1][RTW89_MKK][1][57] = 127,
+ [0][1][RTW89_MKK][0][57] = 127,
+ [0][1][RTW89_IC][1][57] = -40,
+ [0][1][RTW89_KCC][1][57] = -14,
+ [0][1][RTW89_KCC][0][57] = 127,
+ [0][1][RTW89_ACMA][1][57] = 127,
+ [0][1][RTW89_ACMA][0][57] = 127,
+ [0][1][RTW89_CHILE][1][57] = 127,
+ [0][1][RTW89_QATAR][1][57] = 127,
+ [0][1][RTW89_QATAR][0][57] = 127,
+ [0][1][RTW89_UK][1][57] = 127,
+ [0][1][RTW89_UK][0][57] = 127,
+ [0][1][RTW89_FCC][1][59] = -40,
+ [0][1][RTW89_FCC][2][59] = 30,
+ [0][1][RTW89_ETSI][1][59] = 127,
+ [0][1][RTW89_ETSI][0][59] = 127,
+ [0][1][RTW89_MKK][1][59] = 127,
+ [0][1][RTW89_MKK][0][59] = 127,
+ [0][1][RTW89_IC][1][59] = -40,
+ [0][1][RTW89_KCC][1][59] = -14,
+ [0][1][RTW89_KCC][0][59] = 127,
+ [0][1][RTW89_ACMA][1][59] = 127,
+ [0][1][RTW89_ACMA][0][59] = 127,
+ [0][1][RTW89_CHILE][1][59] = 127,
+ [0][1][RTW89_QATAR][1][59] = 127,
+ [0][1][RTW89_QATAR][0][59] = 127,
+ [0][1][RTW89_UK][1][59] = 127,
+ [0][1][RTW89_UK][0][59] = 127,
+ [0][1][RTW89_FCC][1][60] = -40,
+ [0][1][RTW89_FCC][2][60] = 30,
+ [0][1][RTW89_ETSI][1][60] = 127,
+ [0][1][RTW89_ETSI][0][60] = 127,
+ [0][1][RTW89_MKK][1][60] = 127,
+ [0][1][RTW89_MKK][0][60] = 127,
+ [0][1][RTW89_IC][1][60] = -40,
+ [0][1][RTW89_KCC][1][60] = -14,
+ [0][1][RTW89_KCC][0][60] = 127,
+ [0][1][RTW89_ACMA][1][60] = 127,
+ [0][1][RTW89_ACMA][0][60] = 127,
+ [0][1][RTW89_CHILE][1][60] = 127,
+ [0][1][RTW89_QATAR][1][60] = 127,
+ [0][1][RTW89_QATAR][0][60] = 127,
+ [0][1][RTW89_UK][1][60] = 127,
+ [0][1][RTW89_UK][0][60] = 127,
+ [0][1][RTW89_FCC][1][62] = -40,
+ [0][1][RTW89_FCC][2][62] = 30,
+ [0][1][RTW89_ETSI][1][62] = 127,
+ [0][1][RTW89_ETSI][0][62] = 127,
+ [0][1][RTW89_MKK][1][62] = 127,
+ [0][1][RTW89_MKK][0][62] = 127,
+ [0][1][RTW89_IC][1][62] = -40,
+ [0][1][RTW89_KCC][1][62] = -14,
+ [0][1][RTW89_KCC][0][62] = 127,
+ [0][1][RTW89_ACMA][1][62] = 127,
+ [0][1][RTW89_ACMA][0][62] = 127,
+ [0][1][RTW89_CHILE][1][62] = 127,
+ [0][1][RTW89_QATAR][1][62] = 127,
+ [0][1][RTW89_QATAR][0][62] = 127,
+ [0][1][RTW89_UK][1][62] = 127,
+ [0][1][RTW89_UK][0][62] = 127,
+ [0][1][RTW89_FCC][1][64] = -40,
+ [0][1][RTW89_FCC][2][64] = 30,
+ [0][1][RTW89_ETSI][1][64] = 127,
+ [0][1][RTW89_ETSI][0][64] = 127,
+ [0][1][RTW89_MKK][1][64] = 127,
+ [0][1][RTW89_MKK][0][64] = 127,
+ [0][1][RTW89_IC][1][64] = -40,
+ [0][1][RTW89_KCC][1][64] = -14,
+ [0][1][RTW89_KCC][0][64] = 127,
+ [0][1][RTW89_ACMA][1][64] = 127,
+ [0][1][RTW89_ACMA][0][64] = 127,
+ [0][1][RTW89_CHILE][1][64] = 127,
+ [0][1][RTW89_QATAR][1][64] = 127,
+ [0][1][RTW89_QATAR][0][64] = 127,
+ [0][1][RTW89_UK][1][64] = 127,
+ [0][1][RTW89_UK][0][64] = 127,
+ [0][1][RTW89_FCC][1][66] = -40,
+ [0][1][RTW89_FCC][2][66] = 30,
+ [0][1][RTW89_ETSI][1][66] = 127,
+ [0][1][RTW89_ETSI][0][66] = 127,
+ [0][1][RTW89_MKK][1][66] = 127,
+ [0][1][RTW89_MKK][0][66] = 127,
+ [0][1][RTW89_IC][1][66] = -40,
+ [0][1][RTW89_KCC][1][66] = -14,
+ [0][1][RTW89_KCC][0][66] = 127,
+ [0][1][RTW89_ACMA][1][66] = 127,
+ [0][1][RTW89_ACMA][0][66] = 127,
+ [0][1][RTW89_CHILE][1][66] = 127,
+ [0][1][RTW89_QATAR][1][66] = 127,
+ [0][1][RTW89_QATAR][0][66] = 127,
+ [0][1][RTW89_UK][1][66] = 127,
+ [0][1][RTW89_UK][0][66] = 127,
+ [0][1][RTW89_FCC][1][68] = -40,
+ [0][1][RTW89_FCC][2][68] = 30,
+ [0][1][RTW89_ETSI][1][68] = 127,
+ [0][1][RTW89_ETSI][0][68] = 127,
+ [0][1][RTW89_MKK][1][68] = 127,
+ [0][1][RTW89_MKK][0][68] = 127,
+ [0][1][RTW89_IC][1][68] = -40,
+ [0][1][RTW89_KCC][1][68] = -14,
+ [0][1][RTW89_KCC][0][68] = 127,
+ [0][1][RTW89_ACMA][1][68] = 127,
+ [0][1][RTW89_ACMA][0][68] = 127,
+ [0][1][RTW89_CHILE][1][68] = 127,
+ [0][1][RTW89_QATAR][1][68] = 127,
+ [0][1][RTW89_QATAR][0][68] = 127,
+ [0][1][RTW89_UK][1][68] = 127,
+ [0][1][RTW89_UK][0][68] = 127,
+ [0][1][RTW89_FCC][1][70] = -38,
+ [0][1][RTW89_FCC][2][70] = 30,
+ [0][1][RTW89_ETSI][1][70] = 127,
+ [0][1][RTW89_ETSI][0][70] = 127,
+ [0][1][RTW89_MKK][1][70] = 127,
+ [0][1][RTW89_MKK][0][70] = 127,
+ [0][1][RTW89_IC][1][70] = -38,
+ [0][1][RTW89_KCC][1][70] = -14,
+ [0][1][RTW89_KCC][0][70] = 127,
+ [0][1][RTW89_ACMA][1][70] = 127,
+ [0][1][RTW89_ACMA][0][70] = 127,
+ [0][1][RTW89_CHILE][1][70] = 127,
+ [0][1][RTW89_QATAR][1][70] = 127,
+ [0][1][RTW89_QATAR][0][70] = 127,
+ [0][1][RTW89_UK][1][70] = 127,
+ [0][1][RTW89_UK][0][70] = 127,
+ [0][1][RTW89_FCC][1][72] = -38,
+ [0][1][RTW89_FCC][2][72] = 30,
+ [0][1][RTW89_ETSI][1][72] = 127,
+ [0][1][RTW89_ETSI][0][72] = 127,
+ [0][1][RTW89_MKK][1][72] = 127,
+ [0][1][RTW89_MKK][0][72] = 127,
+ [0][1][RTW89_IC][1][72] = -38,
+ [0][1][RTW89_KCC][1][72] = -14,
+ [0][1][RTW89_KCC][0][72] = 127,
+ [0][1][RTW89_ACMA][1][72] = 127,
+ [0][1][RTW89_ACMA][0][72] = 127,
+ [0][1][RTW89_CHILE][1][72] = 127,
+ [0][1][RTW89_QATAR][1][72] = 127,
+ [0][1][RTW89_QATAR][0][72] = 127,
+ [0][1][RTW89_UK][1][72] = 127,
+ [0][1][RTW89_UK][0][72] = 127,
+ [0][1][RTW89_FCC][1][74] = -38,
+ [0][1][RTW89_FCC][2][74] = 30,
+ [0][1][RTW89_ETSI][1][74] = 127,
+ [0][1][RTW89_ETSI][0][74] = 127,
+ [0][1][RTW89_MKK][1][74] = 127,
+ [0][1][RTW89_MKK][0][74] = 127,
+ [0][1][RTW89_IC][1][74] = -38,
+ [0][1][RTW89_KCC][1][74] = -14,
+ [0][1][RTW89_KCC][0][74] = 127,
+ [0][1][RTW89_ACMA][1][74] = 127,
+ [0][1][RTW89_ACMA][0][74] = 127,
+ [0][1][RTW89_CHILE][1][74] = 127,
+ [0][1][RTW89_QATAR][1][74] = 127,
+ [0][1][RTW89_QATAR][0][74] = 127,
+ [0][1][RTW89_UK][1][74] = 127,
+ [0][1][RTW89_UK][0][74] = 127,
+ [0][1][RTW89_FCC][1][75] = -38,
+ [0][1][RTW89_FCC][2][75] = 30,
+ [0][1][RTW89_ETSI][1][75] = 127,
+ [0][1][RTW89_ETSI][0][75] = 127,
+ [0][1][RTW89_MKK][1][75] = 127,
+ [0][1][RTW89_MKK][0][75] = 127,
+ [0][1][RTW89_IC][1][75] = -38,
+ [0][1][RTW89_KCC][1][75] = -14,
+ [0][1][RTW89_KCC][0][75] = 127,
+ [0][1][RTW89_ACMA][1][75] = 127,
+ [0][1][RTW89_ACMA][0][75] = 127,
+ [0][1][RTW89_CHILE][1][75] = 127,
+ [0][1][RTW89_QATAR][1][75] = 127,
+ [0][1][RTW89_QATAR][0][75] = 127,
+ [0][1][RTW89_UK][1][75] = 127,
+ [0][1][RTW89_UK][0][75] = 127,
+ [0][1][RTW89_FCC][1][77] = -38,
+ [0][1][RTW89_FCC][2][77] = 30,
+ [0][1][RTW89_ETSI][1][77] = 127,
+ [0][1][RTW89_ETSI][0][77] = 127,
+ [0][1][RTW89_MKK][1][77] = 127,
+ [0][1][RTW89_MKK][0][77] = 127,
+ [0][1][RTW89_IC][1][77] = -38,
+ [0][1][RTW89_KCC][1][77] = -14,
+ [0][1][RTW89_KCC][0][77] = 127,
+ [0][1][RTW89_ACMA][1][77] = 127,
+ [0][1][RTW89_ACMA][0][77] = 127,
+ [0][1][RTW89_CHILE][1][77] = 127,
+ [0][1][RTW89_QATAR][1][77] = 127,
+ [0][1][RTW89_QATAR][0][77] = 127,
+ [0][1][RTW89_UK][1][77] = 127,
+ [0][1][RTW89_UK][0][77] = 127,
+ [0][1][RTW89_FCC][1][79] = -38,
+ [0][1][RTW89_FCC][2][79] = 30,
+ [0][1][RTW89_ETSI][1][79] = 127,
+ [0][1][RTW89_ETSI][0][79] = 127,
+ [0][1][RTW89_MKK][1][79] = 127,
+ [0][1][RTW89_MKK][0][79] = 127,
+ [0][1][RTW89_IC][1][79] = -38,
+ [0][1][RTW89_KCC][1][79] = -14,
+ [0][1][RTW89_KCC][0][79] = 127,
+ [0][1][RTW89_ACMA][1][79] = 127,
+ [0][1][RTW89_ACMA][0][79] = 127,
+ [0][1][RTW89_CHILE][1][79] = 127,
+ [0][1][RTW89_QATAR][1][79] = 127,
+ [0][1][RTW89_QATAR][0][79] = 127,
+ [0][1][RTW89_UK][1][79] = 127,
+ [0][1][RTW89_UK][0][79] = 127,
+ [0][1][RTW89_FCC][1][81] = -38,
+ [0][1][RTW89_FCC][2][81] = 30,
+ [0][1][RTW89_ETSI][1][81] = 127,
+ [0][1][RTW89_ETSI][0][81] = 127,
+ [0][1][RTW89_MKK][1][81] = 127,
+ [0][1][RTW89_MKK][0][81] = 127,
+ [0][1][RTW89_IC][1][81] = -38,
+ [0][1][RTW89_KCC][1][81] = -14,
+ [0][1][RTW89_KCC][0][81] = 127,
+ [0][1][RTW89_ACMA][1][81] = 127,
+ [0][1][RTW89_ACMA][0][81] = 127,
+ [0][1][RTW89_CHILE][1][81] = 127,
+ [0][1][RTW89_QATAR][1][81] = 127,
+ [0][1][RTW89_QATAR][0][81] = 127,
+ [0][1][RTW89_UK][1][81] = 127,
+ [0][1][RTW89_UK][0][81] = 127,
+ [0][1][RTW89_FCC][1][83] = -38,
+ [0][1][RTW89_FCC][2][83] = 30,
+ [0][1][RTW89_ETSI][1][83] = 127,
+ [0][1][RTW89_ETSI][0][83] = 127,
+ [0][1][RTW89_MKK][1][83] = 127,
+ [0][1][RTW89_MKK][0][83] = 127,
+ [0][1][RTW89_IC][1][83] = -38,
+ [0][1][RTW89_KCC][1][83] = -14,
+ [0][1][RTW89_KCC][0][83] = 127,
+ [0][1][RTW89_ACMA][1][83] = 127,
+ [0][1][RTW89_ACMA][0][83] = 127,
+ [0][1][RTW89_CHILE][1][83] = 127,
+ [0][1][RTW89_QATAR][1][83] = 127,
+ [0][1][RTW89_QATAR][0][83] = 127,
+ [0][1][RTW89_UK][1][83] = 127,
+ [0][1][RTW89_UK][0][83] = 127,
+ [0][1][RTW89_FCC][1][85] = -38,
+ [0][1][RTW89_FCC][2][85] = 30,
+ [0][1][RTW89_ETSI][1][85] = 127,
+ [0][1][RTW89_ETSI][0][85] = 127,
+ [0][1][RTW89_MKK][1][85] = 127,
+ [0][1][RTW89_MKK][0][85] = 127,
+ [0][1][RTW89_IC][1][85] = -38,
+ [0][1][RTW89_KCC][1][85] = -14,
+ [0][1][RTW89_KCC][0][85] = 127,
+ [0][1][RTW89_ACMA][1][85] = 127,
+ [0][1][RTW89_ACMA][0][85] = 127,
+ [0][1][RTW89_CHILE][1][85] = 127,
+ [0][1][RTW89_QATAR][1][85] = 127,
+ [0][1][RTW89_QATAR][0][85] = 127,
+ [0][1][RTW89_UK][1][85] = 127,
+ [0][1][RTW89_UK][0][85] = 127,
+ [0][1][RTW89_FCC][1][87] = -40,
+ [0][1][RTW89_FCC][2][87] = 127,
+ [0][1][RTW89_ETSI][1][87] = 127,
+ [0][1][RTW89_ETSI][0][87] = 127,
+ [0][1][RTW89_MKK][1][87] = 127,
+ [0][1][RTW89_MKK][0][87] = 127,
+ [0][1][RTW89_IC][1][87] = -40,
+ [0][1][RTW89_KCC][1][87] = -14,
+ [0][1][RTW89_KCC][0][87] = 127,
+ [0][1][RTW89_ACMA][1][87] = 127,
+ [0][1][RTW89_ACMA][0][87] = 127,
+ [0][1][RTW89_CHILE][1][87] = 127,
+ [0][1][RTW89_QATAR][1][87] = 127,
+ [0][1][RTW89_QATAR][0][87] = 127,
+ [0][1][RTW89_UK][1][87] = 127,
+ [0][1][RTW89_UK][0][87] = 127,
+ [0][1][RTW89_FCC][1][89] = -38,
+ [0][1][RTW89_FCC][2][89] = 127,
+ [0][1][RTW89_ETSI][1][89] = 127,
+ [0][1][RTW89_ETSI][0][89] = 127,
+ [0][1][RTW89_MKK][1][89] = 127,
+ [0][1][RTW89_MKK][0][89] = 127,
+ [0][1][RTW89_IC][1][89] = -38,
+ [0][1][RTW89_KCC][1][89] = -14,
+ [0][1][RTW89_KCC][0][89] = 127,
+ [0][1][RTW89_ACMA][1][89] = 127,
+ [0][1][RTW89_ACMA][0][89] = 127,
+ [0][1][RTW89_CHILE][1][89] = 127,
+ [0][1][RTW89_QATAR][1][89] = 127,
+ [0][1][RTW89_QATAR][0][89] = 127,
+ [0][1][RTW89_UK][1][89] = 127,
+ [0][1][RTW89_UK][0][89] = 127,
+ [0][1][RTW89_FCC][1][90] = -38,
+ [0][1][RTW89_FCC][2][90] = 127,
+ [0][1][RTW89_ETSI][1][90] = 127,
+ [0][1][RTW89_ETSI][0][90] = 127,
+ [0][1][RTW89_MKK][1][90] = 127,
+ [0][1][RTW89_MKK][0][90] = 127,
+ [0][1][RTW89_IC][1][90] = -38,
+ [0][1][RTW89_KCC][1][90] = -14,
+ [0][1][RTW89_KCC][0][90] = 127,
+ [0][1][RTW89_ACMA][1][90] = 127,
+ [0][1][RTW89_ACMA][0][90] = 127,
+ [0][1][RTW89_CHILE][1][90] = 127,
+ [0][1][RTW89_QATAR][1][90] = 127,
+ [0][1][RTW89_QATAR][0][90] = 127,
+ [0][1][RTW89_UK][1][90] = 127,
+ [0][1][RTW89_UK][0][90] = 127,
+ [0][1][RTW89_FCC][1][92] = -38,
+ [0][1][RTW89_FCC][2][92] = 127,
+ [0][1][RTW89_ETSI][1][92] = 127,
+ [0][1][RTW89_ETSI][0][92] = 127,
+ [0][1][RTW89_MKK][1][92] = 127,
+ [0][1][RTW89_MKK][0][92] = 127,
+ [0][1][RTW89_IC][1][92] = -38,
+ [0][1][RTW89_KCC][1][92] = -14,
+ [0][1][RTW89_KCC][0][92] = 127,
+ [0][1][RTW89_ACMA][1][92] = 127,
+ [0][1][RTW89_ACMA][0][92] = 127,
+ [0][1][RTW89_CHILE][1][92] = 127,
+ [0][1][RTW89_QATAR][1][92] = 127,
+ [0][1][RTW89_QATAR][0][92] = 127,
+ [0][1][RTW89_UK][1][92] = 127,
+ [0][1][RTW89_UK][0][92] = 127,
+ [0][1][RTW89_FCC][1][94] = -38,
+ [0][1][RTW89_FCC][2][94] = 127,
+ [0][1][RTW89_ETSI][1][94] = 127,
+ [0][1][RTW89_ETSI][0][94] = 127,
+ [0][1][RTW89_MKK][1][94] = 127,
+ [0][1][RTW89_MKK][0][94] = 127,
+ [0][1][RTW89_IC][1][94] = -38,
+ [0][1][RTW89_KCC][1][94] = -14,
+ [0][1][RTW89_KCC][0][94] = 127,
+ [0][1][RTW89_ACMA][1][94] = 127,
+ [0][1][RTW89_ACMA][0][94] = 127,
+ [0][1][RTW89_CHILE][1][94] = 127,
+ [0][1][RTW89_QATAR][1][94] = 127,
+ [0][1][RTW89_QATAR][0][94] = 127,
+ [0][1][RTW89_UK][1][94] = 127,
+ [0][1][RTW89_UK][0][94] = 127,
+ [0][1][RTW89_FCC][1][96] = -38,
+ [0][1][RTW89_FCC][2][96] = 127,
+ [0][1][RTW89_ETSI][1][96] = 127,
+ [0][1][RTW89_ETSI][0][96] = 127,
+ [0][1][RTW89_MKK][1][96] = 127,
+ [0][1][RTW89_MKK][0][96] = 127,
+ [0][1][RTW89_IC][1][96] = -38,
+ [0][1][RTW89_KCC][1][96] = -14,
+ [0][1][RTW89_KCC][0][96] = 127,
+ [0][1][RTW89_ACMA][1][96] = 127,
+ [0][1][RTW89_ACMA][0][96] = 127,
+ [0][1][RTW89_CHILE][1][96] = 127,
+ [0][1][RTW89_QATAR][1][96] = 127,
+ [0][1][RTW89_QATAR][0][96] = 127,
+ [0][1][RTW89_UK][1][96] = 127,
+ [0][1][RTW89_UK][0][96] = 127,
+ [0][1][RTW89_FCC][1][98] = -38,
+ [0][1][RTW89_FCC][2][98] = 127,
+ [0][1][RTW89_ETSI][1][98] = 127,
+ [0][1][RTW89_ETSI][0][98] = 127,
+ [0][1][RTW89_MKK][1][98] = 127,
+ [0][1][RTW89_MKK][0][98] = 127,
+ [0][1][RTW89_IC][1][98] = -38,
+ [0][1][RTW89_KCC][1][98] = -14,
+ [0][1][RTW89_KCC][0][98] = 127,
+ [0][1][RTW89_ACMA][1][98] = 127,
+ [0][1][RTW89_ACMA][0][98] = 127,
+ [0][1][RTW89_CHILE][1][98] = 127,
+ [0][1][RTW89_QATAR][1][98] = 127,
+ [0][1][RTW89_QATAR][0][98] = 127,
+ [0][1][RTW89_UK][1][98] = 127,
+ [0][1][RTW89_UK][0][98] = 127,
+ [0][1][RTW89_FCC][1][100] = -38,
+ [0][1][RTW89_FCC][2][100] = 127,
+ [0][1][RTW89_ETSI][1][100] = 127,
+ [0][1][RTW89_ETSI][0][100] = 127,
+ [0][1][RTW89_MKK][1][100] = 127,
+ [0][1][RTW89_MKK][0][100] = 127,
+ [0][1][RTW89_IC][1][100] = -38,
+ [0][1][RTW89_KCC][1][100] = -14,
+ [0][1][RTW89_KCC][0][100] = 127,
+ [0][1][RTW89_ACMA][1][100] = 127,
+ [0][1][RTW89_ACMA][0][100] = 127,
+ [0][1][RTW89_CHILE][1][100] = 127,
+ [0][1][RTW89_QATAR][1][100] = 127,
+ [0][1][RTW89_QATAR][0][100] = 127,
+ [0][1][RTW89_UK][1][100] = 127,
+ [0][1][RTW89_UK][0][100] = 127,
+ [0][1][RTW89_FCC][1][102] = -38,
+ [0][1][RTW89_FCC][2][102] = 127,
+ [0][1][RTW89_ETSI][1][102] = 127,
+ [0][1][RTW89_ETSI][0][102] = 127,
+ [0][1][RTW89_MKK][1][102] = 127,
+ [0][1][RTW89_MKK][0][102] = 127,
+ [0][1][RTW89_IC][1][102] = -38,
+ [0][1][RTW89_KCC][1][102] = -14,
+ [0][1][RTW89_KCC][0][102] = 127,
+ [0][1][RTW89_ACMA][1][102] = 127,
+ [0][1][RTW89_ACMA][0][102] = 127,
+ [0][1][RTW89_CHILE][1][102] = 127,
+ [0][1][RTW89_QATAR][1][102] = 127,
+ [0][1][RTW89_QATAR][0][102] = 127,
+ [0][1][RTW89_UK][1][102] = 127,
+ [0][1][RTW89_UK][0][102] = 127,
+ [0][1][RTW89_FCC][1][104] = -38,
+ [0][1][RTW89_FCC][2][104] = 127,
+ [0][1][RTW89_ETSI][1][104] = 127,
+ [0][1][RTW89_ETSI][0][104] = 127,
+ [0][1][RTW89_MKK][1][104] = 127,
+ [0][1][RTW89_MKK][0][104] = 127,
+ [0][1][RTW89_IC][1][104] = -38,
+ [0][1][RTW89_KCC][1][104] = -14,
+ [0][1][RTW89_KCC][0][104] = 127,
+ [0][1][RTW89_ACMA][1][104] = 127,
+ [0][1][RTW89_ACMA][0][104] = 127,
+ [0][1][RTW89_CHILE][1][104] = 127,
+ [0][1][RTW89_QATAR][1][104] = 127,
+ [0][1][RTW89_QATAR][0][104] = 127,
+ [0][1][RTW89_UK][1][104] = 127,
+ [0][1][RTW89_UK][0][104] = 127,
+ [0][1][RTW89_FCC][1][105] = -38,
+ [0][1][RTW89_FCC][2][105] = 127,
+ [0][1][RTW89_ETSI][1][105] = 127,
+ [0][1][RTW89_ETSI][0][105] = 127,
+ [0][1][RTW89_MKK][1][105] = 127,
+ [0][1][RTW89_MKK][0][105] = 127,
+ [0][1][RTW89_IC][1][105] = -38,
+ [0][1][RTW89_KCC][1][105] = -14,
+ [0][1][RTW89_KCC][0][105] = 127,
+ [0][1][RTW89_ACMA][1][105] = 127,
+ [0][1][RTW89_ACMA][0][105] = 127,
+ [0][1][RTW89_CHILE][1][105] = 127,
+ [0][1][RTW89_QATAR][1][105] = 127,
+ [0][1][RTW89_QATAR][0][105] = 127,
+ [0][1][RTW89_UK][1][105] = 127,
+ [0][1][RTW89_UK][0][105] = 127,
+ [0][1][RTW89_FCC][1][107] = -34,
+ [0][1][RTW89_FCC][2][107] = 127,
+ [0][1][RTW89_ETSI][1][107] = 127,
+ [0][1][RTW89_ETSI][0][107] = 127,
+ [0][1][RTW89_MKK][1][107] = 127,
+ [0][1][RTW89_MKK][0][107] = 127,
+ [0][1][RTW89_IC][1][107] = -34,
+ [0][1][RTW89_KCC][1][107] = -14,
+ [0][1][RTW89_KCC][0][107] = 127,
+ [0][1][RTW89_ACMA][1][107] = 127,
+ [0][1][RTW89_ACMA][0][107] = 127,
+ [0][1][RTW89_CHILE][1][107] = 127,
+ [0][1][RTW89_QATAR][1][107] = 127,
+ [0][1][RTW89_QATAR][0][107] = 127,
+ [0][1][RTW89_UK][1][107] = 127,
+ [0][1][RTW89_UK][0][107] = 127,
+ [0][1][RTW89_FCC][1][109] = -34,
+ [0][1][RTW89_FCC][2][109] = 127,
+ [0][1][RTW89_ETSI][1][109] = 127,
+ [0][1][RTW89_ETSI][0][109] = 127,
+ [0][1][RTW89_MKK][1][109] = 127,
+ [0][1][RTW89_MKK][0][109] = 127,
+ [0][1][RTW89_IC][1][109] = -34,
+ [0][1][RTW89_KCC][1][109] = 127,
+ [0][1][RTW89_KCC][0][109] = 127,
+ [0][1][RTW89_ACMA][1][109] = 127,
+ [0][1][RTW89_ACMA][0][109] = 127,
+ [0][1][RTW89_CHILE][1][109] = 127,
+ [0][1][RTW89_QATAR][1][109] = 127,
+ [0][1][RTW89_QATAR][0][109] = 127,
+ [0][1][RTW89_UK][1][109] = 127,
+ [0][1][RTW89_UK][0][109] = 127,
+ [0][1][RTW89_FCC][1][111] = 127,
+ [0][1][RTW89_FCC][2][111] = 127,
+ [0][1][RTW89_ETSI][1][111] = 127,
+ [0][1][RTW89_ETSI][0][111] = 127,
+ [0][1][RTW89_MKK][1][111] = 127,
+ [0][1][RTW89_MKK][0][111] = 127,
+ [0][1][RTW89_IC][1][111] = 127,
+ [0][1][RTW89_KCC][1][111] = 127,
+ [0][1][RTW89_KCC][0][111] = 127,
+ [0][1][RTW89_ACMA][1][111] = 127,
+ [0][1][RTW89_ACMA][0][111] = 127,
+ [0][1][RTW89_CHILE][1][111] = 127,
+ [0][1][RTW89_QATAR][1][111] = 127,
+ [0][1][RTW89_QATAR][0][111] = 127,
+ [0][1][RTW89_UK][1][111] = 127,
+ [0][1][RTW89_UK][0][111] = 127,
+ [0][1][RTW89_FCC][1][113] = 127,
+ [0][1][RTW89_FCC][2][113] = 127,
+ [0][1][RTW89_ETSI][1][113] = 127,
+ [0][1][RTW89_ETSI][0][113] = 127,
+ [0][1][RTW89_MKK][1][113] = 127,
+ [0][1][RTW89_MKK][0][113] = 127,
+ [0][1][RTW89_IC][1][113] = 127,
+ [0][1][RTW89_KCC][1][113] = 127,
+ [0][1][RTW89_KCC][0][113] = 127,
+ [0][1][RTW89_ACMA][1][113] = 127,
+ [0][1][RTW89_ACMA][0][113] = 127,
+ [0][1][RTW89_CHILE][1][113] = 127,
+ [0][1][RTW89_QATAR][1][113] = 127,
+ [0][1][RTW89_QATAR][0][113] = 127,
+ [0][1][RTW89_UK][1][113] = 127,
+ [0][1][RTW89_UK][0][113] = 127,
+ [0][1][RTW89_FCC][1][115] = 127,
+ [0][1][RTW89_FCC][2][115] = 127,
+ [0][1][RTW89_ETSI][1][115] = 127,
+ [0][1][RTW89_ETSI][0][115] = 127,
+ [0][1][RTW89_MKK][1][115] = 127,
+ [0][1][RTW89_MKK][0][115] = 127,
+ [0][1][RTW89_IC][1][115] = 127,
+ [0][1][RTW89_KCC][1][115] = 127,
+ [0][1][RTW89_KCC][0][115] = 127,
+ [0][1][RTW89_ACMA][1][115] = 127,
+ [0][1][RTW89_ACMA][0][115] = 127,
+ [0][1][RTW89_CHILE][1][115] = 127,
+ [0][1][RTW89_QATAR][1][115] = 127,
+ [0][1][RTW89_QATAR][0][115] = 127,
+ [0][1][RTW89_UK][1][115] = 127,
+ [0][1][RTW89_UK][0][115] = 127,
+ [0][1][RTW89_FCC][1][117] = 127,
+ [0][1][RTW89_FCC][2][117] = 127,
+ [0][1][RTW89_ETSI][1][117] = 127,
+ [0][1][RTW89_ETSI][0][117] = 127,
+ [0][1][RTW89_MKK][1][117] = 127,
+ [0][1][RTW89_MKK][0][117] = 127,
+ [0][1][RTW89_IC][1][117] = 127,
+ [0][1][RTW89_KCC][1][117] = 127,
+ [0][1][RTW89_KCC][0][117] = 127,
+ [0][1][RTW89_ACMA][1][117] = 127,
+ [0][1][RTW89_ACMA][0][117] = 127,
+ [0][1][RTW89_CHILE][1][117] = 127,
+ [0][1][RTW89_QATAR][1][117] = 127,
+ [0][1][RTW89_QATAR][0][117] = 127,
+ [0][1][RTW89_UK][1][117] = 127,
+ [0][1][RTW89_UK][0][117] = 127,
+ [0][1][RTW89_FCC][1][119] = 127,
+ [0][1][RTW89_FCC][2][119] = 127,
+ [0][1][RTW89_ETSI][1][119] = 127,
+ [0][1][RTW89_ETSI][0][119] = 127,
+ [0][1][RTW89_MKK][1][119] = 127,
+ [0][1][RTW89_MKK][0][119] = 127,
+ [0][1][RTW89_IC][1][119] = 127,
+ [0][1][RTW89_KCC][1][119] = 127,
+ [0][1][RTW89_KCC][0][119] = 127,
+ [0][1][RTW89_ACMA][1][119] = 127,
+ [0][1][RTW89_ACMA][0][119] = 127,
+ [0][1][RTW89_CHILE][1][119] = 127,
+ [0][1][RTW89_QATAR][1][119] = 127,
+ [0][1][RTW89_QATAR][0][119] = 127,
+ [0][1][RTW89_UK][1][119] = 127,
+ [0][1][RTW89_UK][0][119] = 127,
+ [1][0][RTW89_FCC][1][0] = -4,
+ [1][0][RTW89_FCC][2][0] = 52,
+ [1][0][RTW89_ETSI][1][0] = 46,
+ [1][0][RTW89_ETSI][0][0] = 6,
+ [1][0][RTW89_MKK][1][0] = 42,
+ [1][0][RTW89_MKK][0][0] = 2,
+ [1][0][RTW89_IC][1][0] = -4,
+ [1][0][RTW89_KCC][1][0] = -2,
+ [1][0][RTW89_KCC][0][0] = -2,
+ [1][0][RTW89_ACMA][1][0] = 46,
+ [1][0][RTW89_ACMA][0][0] = 6,
+ [1][0][RTW89_CHILE][1][0] = -4,
+ [1][0][RTW89_QATAR][1][0] = 46,
+ [1][0][RTW89_QATAR][0][0] = 6,
+ [1][0][RTW89_UK][1][0] = 46,
+ [1][0][RTW89_UK][0][0] = 6,
+ [1][0][RTW89_FCC][1][2] = -4,
+ [1][0][RTW89_FCC][2][2] = 52,
+ [1][0][RTW89_ETSI][1][2] = 46,
+ [1][0][RTW89_ETSI][0][2] = 6,
+ [1][0][RTW89_MKK][1][2] = 42,
+ [1][0][RTW89_MKK][0][2] = 2,
+ [1][0][RTW89_IC][1][2] = -4,
+ [1][0][RTW89_KCC][1][2] = -2,
+ [1][0][RTW89_KCC][0][2] = -2,
+ [1][0][RTW89_ACMA][1][2] = 46,
+ [1][0][RTW89_ACMA][0][2] = 6,
+ [1][0][RTW89_CHILE][1][2] = -4,
+ [1][0][RTW89_QATAR][1][2] = 46,
+ [1][0][RTW89_QATAR][0][2] = 6,
+ [1][0][RTW89_UK][1][2] = 46,
+ [1][0][RTW89_UK][0][2] = 6,
+ [1][0][RTW89_FCC][1][4] = -4,
+ [1][0][RTW89_FCC][2][4] = 52,
+ [1][0][RTW89_ETSI][1][4] = 46,
+ [1][0][RTW89_ETSI][0][4] = 6,
+ [1][0][RTW89_MKK][1][4] = 42,
+ [1][0][RTW89_MKK][0][4] = 2,
+ [1][0][RTW89_IC][1][4] = -4,
+ [1][0][RTW89_KCC][1][4] = -2,
+ [1][0][RTW89_KCC][0][4] = -2,
+ [1][0][RTW89_ACMA][1][4] = 46,
+ [1][0][RTW89_ACMA][0][4] = 6,
+ [1][0][RTW89_CHILE][1][4] = -4,
+ [1][0][RTW89_QATAR][1][4] = 46,
+ [1][0][RTW89_QATAR][0][4] = 6,
+ [1][0][RTW89_UK][1][4] = 46,
+ [1][0][RTW89_UK][0][4] = 6,
+ [1][0][RTW89_FCC][1][6] = -4,
+ [1][0][RTW89_FCC][2][6] = 52,
+ [1][0][RTW89_ETSI][1][6] = 46,
+ [1][0][RTW89_ETSI][0][6] = 6,
+ [1][0][RTW89_MKK][1][6] = 42,
+ [1][0][RTW89_MKK][0][6] = 2,
+ [1][0][RTW89_IC][1][6] = -4,
+ [1][0][RTW89_KCC][1][6] = -2,
+ [1][0][RTW89_KCC][0][6] = -2,
+ [1][0][RTW89_ACMA][1][6] = 46,
+ [1][0][RTW89_ACMA][0][6] = 6,
+ [1][0][RTW89_CHILE][1][6] = -4,
+ [1][0][RTW89_QATAR][1][6] = 46,
+ [1][0][RTW89_QATAR][0][6] = 6,
+ [1][0][RTW89_UK][1][6] = 46,
+ [1][0][RTW89_UK][0][6] = 6,
+ [1][0][RTW89_FCC][1][8] = -4,
+ [1][0][RTW89_FCC][2][8] = 52,
+ [1][0][RTW89_ETSI][1][8] = 46,
+ [1][0][RTW89_ETSI][0][8] = 6,
+ [1][0][RTW89_MKK][1][8] = 42,
+ [1][0][RTW89_MKK][0][8] = 2,
+ [1][0][RTW89_IC][1][8] = -4,
+ [1][0][RTW89_KCC][1][8] = -2,
+ [1][0][RTW89_KCC][0][8] = -2,
+ [1][0][RTW89_ACMA][1][8] = 46,
+ [1][0][RTW89_ACMA][0][8] = 6,
+ [1][0][RTW89_CHILE][1][8] = -4,
+ [1][0][RTW89_QATAR][1][8] = 46,
+ [1][0][RTW89_QATAR][0][8] = 6,
+ [1][0][RTW89_UK][1][8] = 46,
+ [1][0][RTW89_UK][0][8] = 6,
+ [1][0][RTW89_FCC][1][10] = -4,
+ [1][0][RTW89_FCC][2][10] = 52,
+ [1][0][RTW89_ETSI][1][10] = 46,
+ [1][0][RTW89_ETSI][0][10] = 6,
+ [1][0][RTW89_MKK][1][10] = 42,
+ [1][0][RTW89_MKK][0][10] = 2,
+ [1][0][RTW89_IC][1][10] = -4,
+ [1][0][RTW89_KCC][1][10] = -2,
+ [1][0][RTW89_KCC][0][10] = -2,
+ [1][0][RTW89_ACMA][1][10] = 46,
+ [1][0][RTW89_ACMA][0][10] = 6,
+ [1][0][RTW89_CHILE][1][10] = -4,
+ [1][0][RTW89_QATAR][1][10] = 46,
+ [1][0][RTW89_QATAR][0][10] = 6,
+ [1][0][RTW89_UK][1][10] = 46,
+ [1][0][RTW89_UK][0][10] = 6,
+ [1][0][RTW89_FCC][1][12] = -4,
+ [1][0][RTW89_FCC][2][12] = 52,
+ [1][0][RTW89_ETSI][1][12] = 46,
+ [1][0][RTW89_ETSI][0][12] = 6,
+ [1][0][RTW89_MKK][1][12] = 42,
+ [1][0][RTW89_MKK][0][12] = 2,
+ [1][0][RTW89_IC][1][12] = -4,
+ [1][0][RTW89_KCC][1][12] = -2,
+ [1][0][RTW89_KCC][0][12] = -2,
+ [1][0][RTW89_ACMA][1][12] = 46,
+ [1][0][RTW89_ACMA][0][12] = 6,
+ [1][0][RTW89_CHILE][1][12] = -4,
+ [1][0][RTW89_QATAR][1][12] = 46,
+ [1][0][RTW89_QATAR][0][12] = 6,
+ [1][0][RTW89_UK][1][12] = 46,
+ [1][0][RTW89_UK][0][12] = 6,
+ [1][0][RTW89_FCC][1][14] = -4,
+ [1][0][RTW89_FCC][2][14] = 52,
+ [1][0][RTW89_ETSI][1][14] = 46,
+ [1][0][RTW89_ETSI][0][14] = 6,
+ [1][0][RTW89_MKK][1][14] = 42,
+ [1][0][RTW89_MKK][0][14] = 2,
+ [1][0][RTW89_IC][1][14] = -4,
+ [1][0][RTW89_KCC][1][14] = -2,
+ [1][0][RTW89_KCC][0][14] = -2,
+ [1][0][RTW89_ACMA][1][14] = 46,
+ [1][0][RTW89_ACMA][0][14] = 6,
+ [1][0][RTW89_CHILE][1][14] = -4,
+ [1][0][RTW89_QATAR][1][14] = 46,
+ [1][0][RTW89_QATAR][0][14] = 6,
+ [1][0][RTW89_UK][1][14] = 46,
+ [1][0][RTW89_UK][0][14] = 6,
+ [1][0][RTW89_FCC][1][15] = -4,
+ [1][0][RTW89_FCC][2][15] = 52,
+ [1][0][RTW89_ETSI][1][15] = 46,
+ [1][0][RTW89_ETSI][0][15] = 6,
+ [1][0][RTW89_MKK][1][15] = 42,
+ [1][0][RTW89_MKK][0][15] = 2,
+ [1][0][RTW89_IC][1][15] = -4,
+ [1][0][RTW89_KCC][1][15] = -2,
+ [1][0][RTW89_KCC][0][15] = -2,
+ [1][0][RTW89_ACMA][1][15] = 46,
+ [1][0][RTW89_ACMA][0][15] = 6,
+ [1][0][RTW89_CHILE][1][15] = -4,
+ [1][0][RTW89_QATAR][1][15] = 46,
+ [1][0][RTW89_QATAR][0][15] = 6,
+ [1][0][RTW89_UK][1][15] = 46,
+ [1][0][RTW89_UK][0][15] = 6,
+ [1][0][RTW89_FCC][1][17] = -4,
+ [1][0][RTW89_FCC][2][17] = 52,
+ [1][0][RTW89_ETSI][1][17] = 46,
+ [1][0][RTW89_ETSI][0][17] = 6,
+ [1][0][RTW89_MKK][1][17] = 42,
+ [1][0][RTW89_MKK][0][17] = 2,
+ [1][0][RTW89_IC][1][17] = -4,
+ [1][0][RTW89_KCC][1][17] = -2,
+ [1][0][RTW89_KCC][0][17] = -2,
+ [1][0][RTW89_ACMA][1][17] = 46,
+ [1][0][RTW89_ACMA][0][17] = 6,
+ [1][0][RTW89_CHILE][1][17] = -4,
+ [1][0][RTW89_QATAR][1][17] = 46,
+ [1][0][RTW89_QATAR][0][17] = 6,
+ [1][0][RTW89_UK][1][17] = 46,
+ [1][0][RTW89_UK][0][17] = 6,
+ [1][0][RTW89_FCC][1][19] = -4,
+ [1][0][RTW89_FCC][2][19] = 52,
+ [1][0][RTW89_ETSI][1][19] = 46,
+ [1][0][RTW89_ETSI][0][19] = 6,
+ [1][0][RTW89_MKK][1][19] = 42,
+ [1][0][RTW89_MKK][0][19] = 2,
+ [1][0][RTW89_IC][1][19] = -4,
+ [1][0][RTW89_KCC][1][19] = -2,
+ [1][0][RTW89_KCC][0][19] = -2,
+ [1][0][RTW89_ACMA][1][19] = 46,
+ [1][0][RTW89_ACMA][0][19] = 6,
+ [1][0][RTW89_CHILE][1][19] = -4,
+ [1][0][RTW89_QATAR][1][19] = 46,
+ [1][0][RTW89_QATAR][0][19] = 6,
+ [1][0][RTW89_UK][1][19] = 46,
+ [1][0][RTW89_UK][0][19] = 6,
+ [1][0][RTW89_FCC][1][21] = -4,
+ [1][0][RTW89_FCC][2][21] = 52,
+ [1][0][RTW89_ETSI][1][21] = 46,
+ [1][0][RTW89_ETSI][0][21] = 6,
+ [1][0][RTW89_MKK][1][21] = 42,
+ [1][0][RTW89_MKK][0][21] = 2,
+ [1][0][RTW89_IC][1][21] = -4,
+ [1][0][RTW89_KCC][1][21] = -2,
+ [1][0][RTW89_KCC][0][21] = -2,
+ [1][0][RTW89_ACMA][1][21] = 46,
+ [1][0][RTW89_ACMA][0][21] = 6,
+ [1][0][RTW89_CHILE][1][21] = -4,
+ [1][0][RTW89_QATAR][1][21] = 46,
+ [1][0][RTW89_QATAR][0][21] = 6,
+ [1][0][RTW89_UK][1][21] = 46,
+ [1][0][RTW89_UK][0][21] = 6,
+ [1][0][RTW89_FCC][1][23] = -4,
+ [1][0][RTW89_FCC][2][23] = 66,
+ [1][0][RTW89_ETSI][1][23] = 46,
+ [1][0][RTW89_ETSI][0][23] = 6,
+ [1][0][RTW89_MKK][1][23] = 42,
+ [1][0][RTW89_MKK][0][23] = 2,
+ [1][0][RTW89_IC][1][23] = -4,
+ [1][0][RTW89_KCC][1][23] = -2,
+ [1][0][RTW89_KCC][0][23] = -2,
+ [1][0][RTW89_ACMA][1][23] = 46,
+ [1][0][RTW89_ACMA][0][23] = 6,
+ [1][0][RTW89_CHILE][1][23] = -4,
+ [1][0][RTW89_QATAR][1][23] = 46,
+ [1][0][RTW89_QATAR][0][23] = 6,
+ [1][0][RTW89_UK][1][23] = 46,
+ [1][0][RTW89_UK][0][23] = 6,
+ [1][0][RTW89_FCC][1][25] = -4,
+ [1][0][RTW89_FCC][2][25] = 66,
+ [1][0][RTW89_ETSI][1][25] = 46,
+ [1][0][RTW89_ETSI][0][25] = 6,
+ [1][0][RTW89_MKK][1][25] = 42,
+ [1][0][RTW89_MKK][0][25] = 2,
+ [1][0][RTW89_IC][1][25] = -4,
+ [1][0][RTW89_KCC][1][25] = -2,
+ [1][0][RTW89_KCC][0][25] = -2,
+ [1][0][RTW89_ACMA][1][25] = 46,
+ [1][0][RTW89_ACMA][0][25] = 6,
+ [1][0][RTW89_CHILE][1][25] = -4,
+ [1][0][RTW89_QATAR][1][25] = 46,
+ [1][0][RTW89_QATAR][0][25] = 6,
+ [1][0][RTW89_UK][1][25] = 46,
+ [1][0][RTW89_UK][0][25] = 6,
+ [1][0][RTW89_FCC][1][27] = -4,
+ [1][0][RTW89_FCC][2][27] = 66,
+ [1][0][RTW89_ETSI][1][27] = 46,
+ [1][0][RTW89_ETSI][0][27] = 6,
+ [1][0][RTW89_MKK][1][27] = 42,
+ [1][0][RTW89_MKK][0][27] = 2,
+ [1][0][RTW89_IC][1][27] = -4,
+ [1][0][RTW89_KCC][1][27] = -2,
+ [1][0][RTW89_KCC][0][27] = -2,
+ [1][0][RTW89_ACMA][1][27] = 46,
+ [1][0][RTW89_ACMA][0][27] = 6,
+ [1][0][RTW89_CHILE][1][27] = -4,
+ [1][0][RTW89_QATAR][1][27] = 46,
+ [1][0][RTW89_QATAR][0][27] = 6,
+ [1][0][RTW89_UK][1][27] = 46,
+ [1][0][RTW89_UK][0][27] = 6,
+ [1][0][RTW89_FCC][1][29] = -4,
+ [1][0][RTW89_FCC][2][29] = 66,
+ [1][0][RTW89_ETSI][1][29] = 46,
+ [1][0][RTW89_ETSI][0][29] = 6,
+ [1][0][RTW89_MKK][1][29] = 42,
+ [1][0][RTW89_MKK][0][29] = 2,
+ [1][0][RTW89_IC][1][29] = -4,
+ [1][0][RTW89_KCC][1][29] = -2,
+ [1][0][RTW89_KCC][0][29] = -2,
+ [1][0][RTW89_ACMA][1][29] = 46,
+ [1][0][RTW89_ACMA][0][29] = 6,
+ [1][0][RTW89_CHILE][1][29] = -4,
+ [1][0][RTW89_QATAR][1][29] = 46,
+ [1][0][RTW89_QATAR][0][29] = 6,
+ [1][0][RTW89_UK][1][29] = 46,
+ [1][0][RTW89_UK][0][29] = 6,
+ [1][0][RTW89_FCC][1][30] = -4,
+ [1][0][RTW89_FCC][2][30] = 66,
+ [1][0][RTW89_ETSI][1][30] = 46,
+ [1][0][RTW89_ETSI][0][30] = 6,
+ [1][0][RTW89_MKK][1][30] = 42,
+ [1][0][RTW89_MKK][0][30] = 2,
+ [1][0][RTW89_IC][1][30] = -4,
+ [1][0][RTW89_KCC][1][30] = -2,
+ [1][0][RTW89_KCC][0][30] = -2,
+ [1][0][RTW89_ACMA][1][30] = 46,
+ [1][0][RTW89_ACMA][0][30] = 6,
+ [1][0][RTW89_CHILE][1][30] = -4,
+ [1][0][RTW89_QATAR][1][30] = 46,
+ [1][0][RTW89_QATAR][0][30] = 6,
+ [1][0][RTW89_UK][1][30] = 46,
+ [1][0][RTW89_UK][0][30] = 6,
+ [1][0][RTW89_FCC][1][32] = -4,
+ [1][0][RTW89_FCC][2][32] = 66,
+ [1][0][RTW89_ETSI][1][32] = 46,
+ [1][0][RTW89_ETSI][0][32] = 6,
+ [1][0][RTW89_MKK][1][32] = 42,
+ [1][0][RTW89_MKK][0][32] = 2,
+ [1][0][RTW89_IC][1][32] = -4,
+ [1][0][RTW89_KCC][1][32] = -2,
+ [1][0][RTW89_KCC][0][32] = -2,
+ [1][0][RTW89_ACMA][1][32] = 46,
+ [1][0][RTW89_ACMA][0][32] = 6,
+ [1][0][RTW89_CHILE][1][32] = -4,
+ [1][0][RTW89_QATAR][1][32] = 46,
+ [1][0][RTW89_QATAR][0][32] = 6,
+ [1][0][RTW89_UK][1][32] = 46,
+ [1][0][RTW89_UK][0][32] = 6,
+ [1][0][RTW89_FCC][1][34] = -4,
+ [1][0][RTW89_FCC][2][34] = 66,
+ [1][0][RTW89_ETSI][1][34] = 46,
+ [1][0][RTW89_ETSI][0][34] = 6,
+ [1][0][RTW89_MKK][1][34] = 42,
+ [1][0][RTW89_MKK][0][34] = 2,
+ [1][0][RTW89_IC][1][34] = -4,
+ [1][0][RTW89_KCC][1][34] = -2,
+ [1][0][RTW89_KCC][0][34] = -2,
+ [1][0][RTW89_ACMA][1][34] = 46,
+ [1][0][RTW89_ACMA][0][34] = 6,
+ [1][0][RTW89_CHILE][1][34] = -4,
+ [1][0][RTW89_QATAR][1][34] = 46,
+ [1][0][RTW89_QATAR][0][34] = 6,
+ [1][0][RTW89_UK][1][34] = 46,
+ [1][0][RTW89_UK][0][34] = 6,
+ [1][0][RTW89_FCC][1][36] = -4,
+ [1][0][RTW89_FCC][2][36] = 66,
+ [1][0][RTW89_ETSI][1][36] = 46,
+ [1][0][RTW89_ETSI][0][36] = 6,
+ [1][0][RTW89_MKK][1][36] = 42,
+ [1][0][RTW89_MKK][0][36] = 2,
+ [1][0][RTW89_IC][1][36] = -4,
+ [1][0][RTW89_KCC][1][36] = -2,
+ [1][0][RTW89_KCC][0][36] = -2,
+ [1][0][RTW89_ACMA][1][36] = 46,
+ [1][0][RTW89_ACMA][0][36] = 6,
+ [1][0][RTW89_CHILE][1][36] = -4,
+ [1][0][RTW89_QATAR][1][36] = 46,
+ [1][0][RTW89_QATAR][0][36] = 6,
+ [1][0][RTW89_UK][1][36] = 46,
+ [1][0][RTW89_UK][0][36] = 6,
+ [1][0][RTW89_FCC][1][38] = -4,
+ [1][0][RTW89_FCC][2][38] = 66,
+ [1][0][RTW89_ETSI][1][38] = 46,
+ [1][0][RTW89_ETSI][0][38] = 6,
+ [1][0][RTW89_MKK][1][38] = 42,
+ [1][0][RTW89_MKK][0][38] = 2,
+ [1][0][RTW89_IC][1][38] = -4,
+ [1][0][RTW89_KCC][1][38] = -2,
+ [1][0][RTW89_KCC][0][38] = -2,
+ [1][0][RTW89_ACMA][1][38] = 46,
+ [1][0][RTW89_ACMA][0][38] = 6,
+ [1][0][RTW89_CHILE][1][38] = -4,
+ [1][0][RTW89_QATAR][1][38] = 46,
+ [1][0][RTW89_QATAR][0][38] = 6,
+ [1][0][RTW89_UK][1][38] = 46,
+ [1][0][RTW89_UK][0][38] = 6,
+ [1][0][RTW89_FCC][1][40] = -4,
+ [1][0][RTW89_FCC][2][40] = 66,
+ [1][0][RTW89_ETSI][1][40] = 46,
+ [1][0][RTW89_ETSI][0][40] = 6,
+ [1][0][RTW89_MKK][1][40] = 42,
+ [1][0][RTW89_MKK][0][40] = 2,
+ [1][0][RTW89_IC][1][40] = -4,
+ [1][0][RTW89_KCC][1][40] = -2,
+ [1][0][RTW89_KCC][0][40] = -2,
+ [1][0][RTW89_ACMA][1][40] = 46,
+ [1][0][RTW89_ACMA][0][40] = 6,
+ [1][0][RTW89_CHILE][1][40] = -4,
+ [1][0][RTW89_QATAR][1][40] = 46,
+ [1][0][RTW89_QATAR][0][40] = 6,
+ [1][0][RTW89_UK][1][40] = 46,
+ [1][0][RTW89_UK][0][40] = 6,
+ [1][0][RTW89_FCC][1][42] = -4,
+ [1][0][RTW89_FCC][2][42] = 66,
+ [1][0][RTW89_ETSI][1][42] = 46,
+ [1][0][RTW89_ETSI][0][42] = 6,
+ [1][0][RTW89_MKK][1][42] = 42,
+ [1][0][RTW89_MKK][0][42] = 2,
+ [1][0][RTW89_IC][1][42] = -4,
+ [1][0][RTW89_KCC][1][42] = -2,
+ [1][0][RTW89_KCC][0][42] = -2,
+ [1][0][RTW89_ACMA][1][42] = 46,
+ [1][0][RTW89_ACMA][0][42] = 6,
+ [1][0][RTW89_CHILE][1][42] = -4,
+ [1][0][RTW89_QATAR][1][42] = 46,
+ [1][0][RTW89_QATAR][0][42] = 6,
+ [1][0][RTW89_UK][1][42] = 46,
+ [1][0][RTW89_UK][0][42] = 6,
+ [1][0][RTW89_FCC][1][44] = -4,
+ [1][0][RTW89_FCC][2][44] = 66,
+ [1][0][RTW89_ETSI][1][44] = 46,
+ [1][0][RTW89_ETSI][0][44] = 8,
+ [1][0][RTW89_MKK][1][44] = 22,
+ [1][0][RTW89_MKK][0][44] = 4,
+ [1][0][RTW89_IC][1][44] = -4,
+ [1][0][RTW89_KCC][1][44] = -2,
+ [1][0][RTW89_KCC][0][44] = -2,
+ [1][0][RTW89_ACMA][1][44] = 46,
+ [1][0][RTW89_ACMA][0][44] = 8,
+ [1][0][RTW89_CHILE][1][44] = -4,
+ [1][0][RTW89_QATAR][1][44] = 46,
+ [1][0][RTW89_QATAR][0][44] = 8,
+ [1][0][RTW89_UK][1][44] = 46,
+ [1][0][RTW89_UK][0][44] = 8,
+ [1][0][RTW89_FCC][1][45] = -4,
+ [1][0][RTW89_FCC][2][45] = 127,
+ [1][0][RTW89_ETSI][1][45] = 127,
+ [1][0][RTW89_ETSI][0][45] = 127,
+ [1][0][RTW89_MKK][1][45] = 127,
+ [1][0][RTW89_MKK][0][45] = 127,
+ [1][0][RTW89_IC][1][45] = -4,
+ [1][0][RTW89_KCC][1][45] = -2,
+ [1][0][RTW89_KCC][0][45] = 127,
+ [1][0][RTW89_ACMA][1][45] = 127,
+ [1][0][RTW89_ACMA][0][45] = 127,
+ [1][0][RTW89_CHILE][1][45] = 127,
+ [1][0][RTW89_QATAR][1][45] = 127,
+ [1][0][RTW89_QATAR][0][45] = 127,
+ [1][0][RTW89_UK][1][45] = 127,
+ [1][0][RTW89_UK][0][45] = 127,
+ [1][0][RTW89_FCC][1][47] = -4,
+ [1][0][RTW89_FCC][2][47] = 127,
+ [1][0][RTW89_ETSI][1][47] = 127,
+ [1][0][RTW89_ETSI][0][47] = 127,
+ [1][0][RTW89_MKK][1][47] = 127,
+ [1][0][RTW89_MKK][0][47] = 127,
+ [1][0][RTW89_IC][1][47] = -4,
+ [1][0][RTW89_KCC][1][47] = -2,
+ [1][0][RTW89_KCC][0][47] = 127,
+ [1][0][RTW89_ACMA][1][47] = 127,
+ [1][0][RTW89_ACMA][0][47] = 127,
+ [1][0][RTW89_CHILE][1][47] = 127,
+ [1][0][RTW89_QATAR][1][47] = 127,
+ [1][0][RTW89_QATAR][0][47] = 127,
+ [1][0][RTW89_UK][1][47] = 127,
+ [1][0][RTW89_UK][0][47] = 127,
+ [1][0][RTW89_FCC][1][49] = -4,
+ [1][0][RTW89_FCC][2][49] = 127,
+ [1][0][RTW89_ETSI][1][49] = 127,
+ [1][0][RTW89_ETSI][0][49] = 127,
+ [1][0][RTW89_MKK][1][49] = 127,
+ [1][0][RTW89_MKK][0][49] = 127,
+ [1][0][RTW89_IC][1][49] = -4,
+ [1][0][RTW89_KCC][1][49] = -2,
+ [1][0][RTW89_KCC][0][49] = 127,
+ [1][0][RTW89_ACMA][1][49] = 127,
+ [1][0][RTW89_ACMA][0][49] = 127,
+ [1][0][RTW89_CHILE][1][49] = 127,
+ [1][0][RTW89_QATAR][1][49] = 127,
+ [1][0][RTW89_QATAR][0][49] = 127,
+ [1][0][RTW89_UK][1][49] = 127,
+ [1][0][RTW89_UK][0][49] = 127,
+ [1][0][RTW89_FCC][1][51] = -4,
+ [1][0][RTW89_FCC][2][51] = 127,
+ [1][0][RTW89_ETSI][1][51] = 127,
+ [1][0][RTW89_ETSI][0][51] = 127,
+ [1][0][RTW89_MKK][1][51] = 127,
+ [1][0][RTW89_MKK][0][51] = 127,
+ [1][0][RTW89_IC][1][51] = -4,
+ [1][0][RTW89_KCC][1][51] = -2,
+ [1][0][RTW89_KCC][0][51] = 127,
+ [1][0][RTW89_ACMA][1][51] = 127,
+ [1][0][RTW89_ACMA][0][51] = 127,
+ [1][0][RTW89_CHILE][1][51] = 127,
+ [1][0][RTW89_QATAR][1][51] = 127,
+ [1][0][RTW89_QATAR][0][51] = 127,
+ [1][0][RTW89_UK][1][51] = 127,
+ [1][0][RTW89_UK][0][51] = 127,
+ [1][0][RTW89_FCC][1][53] = -4,
+ [1][0][RTW89_FCC][2][53] = 127,
+ [1][0][RTW89_ETSI][1][53] = 127,
+ [1][0][RTW89_ETSI][0][53] = 127,
+ [1][0][RTW89_MKK][1][53] = 127,
+ [1][0][RTW89_MKK][0][53] = 127,
+ [1][0][RTW89_IC][1][53] = -4,
+ [1][0][RTW89_KCC][1][53] = -2,
+ [1][0][RTW89_KCC][0][53] = 127,
+ [1][0][RTW89_ACMA][1][53] = 127,
+ [1][0][RTW89_ACMA][0][53] = 127,
+ [1][0][RTW89_CHILE][1][53] = 127,
+ [1][0][RTW89_QATAR][1][53] = 127,
+ [1][0][RTW89_QATAR][0][53] = 127,
+ [1][0][RTW89_UK][1][53] = 127,
+ [1][0][RTW89_UK][0][53] = 127,
+ [1][0][RTW89_FCC][1][55] = -4,
+ [1][0][RTW89_FCC][2][55] = 68,
+ [1][0][RTW89_ETSI][1][55] = 127,
+ [1][0][RTW89_ETSI][0][55] = 127,
+ [1][0][RTW89_MKK][1][55] = 127,
+ [1][0][RTW89_MKK][0][55] = 127,
+ [1][0][RTW89_IC][1][55] = -4,
+ [1][0][RTW89_KCC][1][55] = -2,
+ [1][0][RTW89_KCC][0][55] = 127,
+ [1][0][RTW89_ACMA][1][55] = 127,
+ [1][0][RTW89_ACMA][0][55] = 127,
+ [1][0][RTW89_CHILE][1][55] = 127,
+ [1][0][RTW89_QATAR][1][55] = 127,
+ [1][0][RTW89_QATAR][0][55] = 127,
+ [1][0][RTW89_UK][1][55] = 127,
+ [1][0][RTW89_UK][0][55] = 127,
+ [1][0][RTW89_FCC][1][57] = -4,
+ [1][0][RTW89_FCC][2][57] = 68,
+ [1][0][RTW89_ETSI][1][57] = 127,
+ [1][0][RTW89_ETSI][0][57] = 127,
+ [1][0][RTW89_MKK][1][57] = 127,
+ [1][0][RTW89_MKK][0][57] = 127,
+ [1][0][RTW89_IC][1][57] = -4,
+ [1][0][RTW89_KCC][1][57] = -2,
+ [1][0][RTW89_KCC][0][57] = 127,
+ [1][0][RTW89_ACMA][1][57] = 127,
+ [1][0][RTW89_ACMA][0][57] = 127,
+ [1][0][RTW89_CHILE][1][57] = 127,
+ [1][0][RTW89_QATAR][1][57] = 127,
+ [1][0][RTW89_QATAR][0][57] = 127,
+ [1][0][RTW89_UK][1][57] = 127,
+ [1][0][RTW89_UK][0][57] = 127,
+ [1][0][RTW89_FCC][1][59] = -4,
+ [1][0][RTW89_FCC][2][59] = 68,
+ [1][0][RTW89_ETSI][1][59] = 127,
+ [1][0][RTW89_ETSI][0][59] = 127,
+ [1][0][RTW89_MKK][1][59] = 127,
+ [1][0][RTW89_MKK][0][59] = 127,
+ [1][0][RTW89_IC][1][59] = -4,
+ [1][0][RTW89_KCC][1][59] = -2,
+ [1][0][RTW89_KCC][0][59] = 127,
+ [1][0][RTW89_ACMA][1][59] = 127,
+ [1][0][RTW89_ACMA][0][59] = 127,
+ [1][0][RTW89_CHILE][1][59] = 127,
+ [1][0][RTW89_QATAR][1][59] = 127,
+ [1][0][RTW89_QATAR][0][59] = 127,
+ [1][0][RTW89_UK][1][59] = 127,
+ [1][0][RTW89_UK][0][59] = 127,
+ [1][0][RTW89_FCC][1][60] = -4,
+ [1][0][RTW89_FCC][2][60] = 68,
+ [1][0][RTW89_ETSI][1][60] = 127,
+ [1][0][RTW89_ETSI][0][60] = 127,
+ [1][0][RTW89_MKK][1][60] = 127,
+ [1][0][RTW89_MKK][0][60] = 127,
+ [1][0][RTW89_IC][1][60] = -4,
+ [1][0][RTW89_KCC][1][60] = -2,
+ [1][0][RTW89_KCC][0][60] = 127,
+ [1][0][RTW89_ACMA][1][60] = 127,
+ [1][0][RTW89_ACMA][0][60] = 127,
+ [1][0][RTW89_CHILE][1][60] = 127,
+ [1][0][RTW89_QATAR][1][60] = 127,
+ [1][0][RTW89_QATAR][0][60] = 127,
+ [1][0][RTW89_UK][1][60] = 127,
+ [1][0][RTW89_UK][0][60] = 127,
+ [1][0][RTW89_FCC][1][62] = -4,
+ [1][0][RTW89_FCC][2][62] = 68,
+ [1][0][RTW89_ETSI][1][62] = 127,
+ [1][0][RTW89_ETSI][0][62] = 127,
+ [1][0][RTW89_MKK][1][62] = 127,
+ [1][0][RTW89_MKK][0][62] = 127,
+ [1][0][RTW89_IC][1][62] = -4,
+ [1][0][RTW89_KCC][1][62] = -2,
+ [1][0][RTW89_KCC][0][62] = 127,
+ [1][0][RTW89_ACMA][1][62] = 127,
+ [1][0][RTW89_ACMA][0][62] = 127,
+ [1][0][RTW89_CHILE][1][62] = 127,
+ [1][0][RTW89_QATAR][1][62] = 127,
+ [1][0][RTW89_QATAR][0][62] = 127,
+ [1][0][RTW89_UK][1][62] = 127,
+ [1][0][RTW89_UK][0][62] = 127,
+ [1][0][RTW89_FCC][1][64] = -4,
+ [1][0][RTW89_FCC][2][64] = 68,
+ [1][0][RTW89_ETSI][1][64] = 127,
+ [1][0][RTW89_ETSI][0][64] = 127,
+ [1][0][RTW89_MKK][1][64] = 127,
+ [1][0][RTW89_MKK][0][64] = 127,
+ [1][0][RTW89_IC][1][64] = -4,
+ [1][0][RTW89_KCC][1][64] = -2,
+ [1][0][RTW89_KCC][0][64] = 127,
+ [1][0][RTW89_ACMA][1][64] = 127,
+ [1][0][RTW89_ACMA][0][64] = 127,
+ [1][0][RTW89_CHILE][1][64] = 127,
+ [1][0][RTW89_QATAR][1][64] = 127,
+ [1][0][RTW89_QATAR][0][64] = 127,
+ [1][0][RTW89_UK][1][64] = 127,
+ [1][0][RTW89_UK][0][64] = 127,
+ [1][0][RTW89_FCC][1][66] = -4,
+ [1][0][RTW89_FCC][2][66] = 68,
+ [1][0][RTW89_ETSI][1][66] = 127,
+ [1][0][RTW89_ETSI][0][66] = 127,
+ [1][0][RTW89_MKK][1][66] = 127,
+ [1][0][RTW89_MKK][0][66] = 127,
+ [1][0][RTW89_IC][1][66] = -4,
+ [1][0][RTW89_KCC][1][66] = -2,
+ [1][0][RTW89_KCC][0][66] = 127,
+ [1][0][RTW89_ACMA][1][66] = 127,
+ [1][0][RTW89_ACMA][0][66] = 127,
+ [1][0][RTW89_CHILE][1][66] = 127,
+ [1][0][RTW89_QATAR][1][66] = 127,
+ [1][0][RTW89_QATAR][0][66] = 127,
+ [1][0][RTW89_UK][1][66] = 127,
+ [1][0][RTW89_UK][0][66] = 127,
+ [1][0][RTW89_FCC][1][68] = -4,
+ [1][0][RTW89_FCC][2][68] = 68,
+ [1][0][RTW89_ETSI][1][68] = 127,
+ [1][0][RTW89_ETSI][0][68] = 127,
+ [1][0][RTW89_MKK][1][68] = 127,
+ [1][0][RTW89_MKK][0][68] = 127,
+ [1][0][RTW89_IC][1][68] = -4,
+ [1][0][RTW89_KCC][1][68] = -2,
+ [1][0][RTW89_KCC][0][68] = 127,
+ [1][0][RTW89_ACMA][1][68] = 127,
+ [1][0][RTW89_ACMA][0][68] = 127,
+ [1][0][RTW89_CHILE][1][68] = 127,
+ [1][0][RTW89_QATAR][1][68] = 127,
+ [1][0][RTW89_QATAR][0][68] = 127,
+ [1][0][RTW89_UK][1][68] = 127,
+ [1][0][RTW89_UK][0][68] = 127,
+ [1][0][RTW89_FCC][1][70] = -4,
+ [1][0][RTW89_FCC][2][70] = 68,
+ [1][0][RTW89_ETSI][1][70] = 127,
+ [1][0][RTW89_ETSI][0][70] = 127,
+ [1][0][RTW89_MKK][1][70] = 127,
+ [1][0][RTW89_MKK][0][70] = 127,
+ [1][0][RTW89_IC][1][70] = -4,
+ [1][0][RTW89_KCC][1][70] = -2,
+ [1][0][RTW89_KCC][0][70] = 127,
+ [1][0][RTW89_ACMA][1][70] = 127,
+ [1][0][RTW89_ACMA][0][70] = 127,
+ [1][0][RTW89_CHILE][1][70] = 127,
+ [1][0][RTW89_QATAR][1][70] = 127,
+ [1][0][RTW89_QATAR][0][70] = 127,
+ [1][0][RTW89_UK][1][70] = 127,
+ [1][0][RTW89_UK][0][70] = 127,
+ [1][0][RTW89_FCC][1][72] = -4,
+ [1][0][RTW89_FCC][2][72] = 68,
+ [1][0][RTW89_ETSI][1][72] = 127,
+ [1][0][RTW89_ETSI][0][72] = 127,
+ [1][0][RTW89_MKK][1][72] = 127,
+ [1][0][RTW89_MKK][0][72] = 127,
+ [1][0][RTW89_IC][1][72] = -4,
+ [1][0][RTW89_KCC][1][72] = -2,
+ [1][0][RTW89_KCC][0][72] = 127,
+ [1][0][RTW89_ACMA][1][72] = 127,
+ [1][0][RTW89_ACMA][0][72] = 127,
+ [1][0][RTW89_CHILE][1][72] = 127,
+ [1][0][RTW89_QATAR][1][72] = 127,
+ [1][0][RTW89_QATAR][0][72] = 127,
+ [1][0][RTW89_UK][1][72] = 127,
+ [1][0][RTW89_UK][0][72] = 127,
+ [1][0][RTW89_FCC][1][74] = -4,
+ [1][0][RTW89_FCC][2][74] = 68,
+ [1][0][RTW89_ETSI][1][74] = 127,
+ [1][0][RTW89_ETSI][0][74] = 127,
+ [1][0][RTW89_MKK][1][74] = 127,
+ [1][0][RTW89_MKK][0][74] = 127,
+ [1][0][RTW89_IC][1][74] = -4,
+ [1][0][RTW89_KCC][1][74] = -2,
+ [1][0][RTW89_KCC][0][74] = 127,
+ [1][0][RTW89_ACMA][1][74] = 127,
+ [1][0][RTW89_ACMA][0][74] = 127,
+ [1][0][RTW89_CHILE][1][74] = 127,
+ [1][0][RTW89_QATAR][1][74] = 127,
+ [1][0][RTW89_QATAR][0][74] = 127,
+ [1][0][RTW89_UK][1][74] = 127,
+ [1][0][RTW89_UK][0][74] = 127,
+ [1][0][RTW89_FCC][1][75] = -4,
+ [1][0][RTW89_FCC][2][75] = 68,
+ [1][0][RTW89_ETSI][1][75] = 127,
+ [1][0][RTW89_ETSI][0][75] = 127,
+ [1][0][RTW89_MKK][1][75] = 127,
+ [1][0][RTW89_MKK][0][75] = 127,
+ [1][0][RTW89_IC][1][75] = -4,
+ [1][0][RTW89_KCC][1][75] = -2,
+ [1][0][RTW89_KCC][0][75] = 127,
+ [1][0][RTW89_ACMA][1][75] = 127,
+ [1][0][RTW89_ACMA][0][75] = 127,
+ [1][0][RTW89_CHILE][1][75] = 127,
+ [1][0][RTW89_QATAR][1][75] = 127,
+ [1][0][RTW89_QATAR][0][75] = 127,
+ [1][0][RTW89_UK][1][75] = 127,
+ [1][0][RTW89_UK][0][75] = 127,
+ [1][0][RTW89_FCC][1][77] = -4,
+ [1][0][RTW89_FCC][2][77] = 68,
+ [1][0][RTW89_ETSI][1][77] = 127,
+ [1][0][RTW89_ETSI][0][77] = 127,
+ [1][0][RTW89_MKK][1][77] = 127,
+ [1][0][RTW89_MKK][0][77] = 127,
+ [1][0][RTW89_IC][1][77] = -4,
+ [1][0][RTW89_KCC][1][77] = -2,
+ [1][0][RTW89_KCC][0][77] = 127,
+ [1][0][RTW89_ACMA][1][77] = 127,
+ [1][0][RTW89_ACMA][0][77] = 127,
+ [1][0][RTW89_CHILE][1][77] = 127,
+ [1][0][RTW89_QATAR][1][77] = 127,
+ [1][0][RTW89_QATAR][0][77] = 127,
+ [1][0][RTW89_UK][1][77] = 127,
+ [1][0][RTW89_UK][0][77] = 127,
+ [1][0][RTW89_FCC][1][79] = -4,
+ [1][0][RTW89_FCC][2][79] = 68,
+ [1][0][RTW89_ETSI][1][79] = 127,
+ [1][0][RTW89_ETSI][0][79] = 127,
+ [1][0][RTW89_MKK][1][79] = 127,
+ [1][0][RTW89_MKK][0][79] = 127,
+ [1][0][RTW89_IC][1][79] = -4,
+ [1][0][RTW89_KCC][1][79] = -2,
+ [1][0][RTW89_KCC][0][79] = 127,
+ [1][0][RTW89_ACMA][1][79] = 127,
+ [1][0][RTW89_ACMA][0][79] = 127,
+ [1][0][RTW89_CHILE][1][79] = 127,
+ [1][0][RTW89_QATAR][1][79] = 127,
+ [1][0][RTW89_QATAR][0][79] = 127,
+ [1][0][RTW89_UK][1][79] = 127,
+ [1][0][RTW89_UK][0][79] = 127,
+ [1][0][RTW89_FCC][1][81] = -4,
+ [1][0][RTW89_FCC][2][81] = 68,
+ [1][0][RTW89_ETSI][1][81] = 127,
+ [1][0][RTW89_ETSI][0][81] = 127,
+ [1][0][RTW89_MKK][1][81] = 127,
+ [1][0][RTW89_MKK][0][81] = 127,
+ [1][0][RTW89_IC][1][81] = -4,
+ [1][0][RTW89_KCC][1][81] = -2,
+ [1][0][RTW89_KCC][0][81] = 127,
+ [1][0][RTW89_ACMA][1][81] = 127,
+ [1][0][RTW89_ACMA][0][81] = 127,
+ [1][0][RTW89_CHILE][1][81] = 127,
+ [1][0][RTW89_QATAR][1][81] = 127,
+ [1][0][RTW89_QATAR][0][81] = 127,
+ [1][0][RTW89_UK][1][81] = 127,
+ [1][0][RTW89_UK][0][81] = 127,
+ [1][0][RTW89_FCC][1][83] = -4,
+ [1][0][RTW89_FCC][2][83] = 68,
+ [1][0][RTW89_ETSI][1][83] = 127,
+ [1][0][RTW89_ETSI][0][83] = 127,
+ [1][0][RTW89_MKK][1][83] = 127,
+ [1][0][RTW89_MKK][0][83] = 127,
+ [1][0][RTW89_IC][1][83] = -4,
+ [1][0][RTW89_KCC][1][83] = -2,
+ [1][0][RTW89_KCC][0][83] = 127,
+ [1][0][RTW89_ACMA][1][83] = 127,
+ [1][0][RTW89_ACMA][0][83] = 127,
+ [1][0][RTW89_CHILE][1][83] = 127,
+ [1][0][RTW89_QATAR][1][83] = 127,
+ [1][0][RTW89_QATAR][0][83] = 127,
+ [1][0][RTW89_UK][1][83] = 127,
+ [1][0][RTW89_UK][0][83] = 127,
+ [1][0][RTW89_FCC][1][85] = -4,
+ [1][0][RTW89_FCC][2][85] = 68,
+ [1][0][RTW89_ETSI][1][85] = 127,
+ [1][0][RTW89_ETSI][0][85] = 127,
+ [1][0][RTW89_MKK][1][85] = 127,
+ [1][0][RTW89_MKK][0][85] = 127,
+ [1][0][RTW89_IC][1][85] = -4,
+ [1][0][RTW89_KCC][1][85] = -2,
+ [1][0][RTW89_KCC][0][85] = 127,
+ [1][0][RTW89_ACMA][1][85] = 127,
+ [1][0][RTW89_ACMA][0][85] = 127,
+ [1][0][RTW89_CHILE][1][85] = 127,
+ [1][0][RTW89_QATAR][1][85] = 127,
+ [1][0][RTW89_QATAR][0][85] = 127,
+ [1][0][RTW89_UK][1][85] = 127,
+ [1][0][RTW89_UK][0][85] = 127,
+ [1][0][RTW89_FCC][1][87] = -4,
+ [1][0][RTW89_FCC][2][87] = 127,
+ [1][0][RTW89_ETSI][1][87] = 127,
+ [1][0][RTW89_ETSI][0][87] = 127,
+ [1][0][RTW89_MKK][1][87] = 127,
+ [1][0][RTW89_MKK][0][87] = 127,
+ [1][0][RTW89_IC][1][87] = -4,
+ [1][0][RTW89_KCC][1][87] = -2,
+ [1][0][RTW89_KCC][0][87] = 127,
+ [1][0][RTW89_ACMA][1][87] = 127,
+ [1][0][RTW89_ACMA][0][87] = 127,
+ [1][0][RTW89_CHILE][1][87] = 127,
+ [1][0][RTW89_QATAR][1][87] = 127,
+ [1][0][RTW89_QATAR][0][87] = 127,
+ [1][0][RTW89_UK][1][87] = 127,
+ [1][0][RTW89_UK][0][87] = 127,
+ [1][0][RTW89_FCC][1][89] = -4,
+ [1][0][RTW89_FCC][2][89] = 127,
+ [1][0][RTW89_ETSI][1][89] = 127,
+ [1][0][RTW89_ETSI][0][89] = 127,
+ [1][0][RTW89_MKK][1][89] = 127,
+ [1][0][RTW89_MKK][0][89] = 127,
+ [1][0][RTW89_IC][1][89] = -4,
+ [1][0][RTW89_KCC][1][89] = -2,
+ [1][0][RTW89_KCC][0][89] = 127,
+ [1][0][RTW89_ACMA][1][89] = 127,
+ [1][0][RTW89_ACMA][0][89] = 127,
+ [1][0][RTW89_CHILE][1][89] = 127,
+ [1][0][RTW89_QATAR][1][89] = 127,
+ [1][0][RTW89_QATAR][0][89] = 127,
+ [1][0][RTW89_UK][1][89] = 127,
+ [1][0][RTW89_UK][0][89] = 127,
+ [1][0][RTW89_FCC][1][90] = -4,
+ [1][0][RTW89_FCC][2][90] = 127,
+ [1][0][RTW89_ETSI][1][90] = 127,
+ [1][0][RTW89_ETSI][0][90] = 127,
+ [1][0][RTW89_MKK][1][90] = 127,
+ [1][0][RTW89_MKK][0][90] = 127,
+ [1][0][RTW89_IC][1][90] = -4,
+ [1][0][RTW89_KCC][1][90] = -2,
+ [1][0][RTW89_KCC][0][90] = 127,
+ [1][0][RTW89_ACMA][1][90] = 127,
+ [1][0][RTW89_ACMA][0][90] = 127,
+ [1][0][RTW89_CHILE][1][90] = 127,
+ [1][0][RTW89_QATAR][1][90] = 127,
+ [1][0][RTW89_QATAR][0][90] = 127,
+ [1][0][RTW89_UK][1][90] = 127,
+ [1][0][RTW89_UK][0][90] = 127,
+ [1][0][RTW89_FCC][1][92] = -4,
+ [1][0][RTW89_FCC][2][92] = 127,
+ [1][0][RTW89_ETSI][1][92] = 127,
+ [1][0][RTW89_ETSI][0][92] = 127,
+ [1][0][RTW89_MKK][1][92] = 127,
+ [1][0][RTW89_MKK][0][92] = 127,
+ [1][0][RTW89_IC][1][92] = -4,
+ [1][0][RTW89_KCC][1][92] = -2,
+ [1][0][RTW89_KCC][0][92] = 127,
+ [1][0][RTW89_ACMA][1][92] = 127,
+ [1][0][RTW89_ACMA][0][92] = 127,
+ [1][0][RTW89_CHILE][1][92] = 127,
+ [1][0][RTW89_QATAR][1][92] = 127,
+ [1][0][RTW89_QATAR][0][92] = 127,
+ [1][0][RTW89_UK][1][92] = 127,
+ [1][0][RTW89_UK][0][92] = 127,
+ [1][0][RTW89_FCC][1][94] = -4,
+ [1][0][RTW89_FCC][2][94] = 127,
+ [1][0][RTW89_ETSI][1][94] = 127,
+ [1][0][RTW89_ETSI][0][94] = 127,
+ [1][0][RTW89_MKK][1][94] = 127,
+ [1][0][RTW89_MKK][0][94] = 127,
+ [1][0][RTW89_IC][1][94] = -4,
+ [1][0][RTW89_KCC][1][94] = -2,
+ [1][0][RTW89_KCC][0][94] = 127,
+ [1][0][RTW89_ACMA][1][94] = 127,
+ [1][0][RTW89_ACMA][0][94] = 127,
+ [1][0][RTW89_CHILE][1][94] = 127,
+ [1][0][RTW89_QATAR][1][94] = 127,
+ [1][0][RTW89_QATAR][0][94] = 127,
+ [1][0][RTW89_UK][1][94] = 127,
+ [1][0][RTW89_UK][0][94] = 127,
+ [1][0][RTW89_FCC][1][96] = -4,
+ [1][0][RTW89_FCC][2][96] = 127,
+ [1][0][RTW89_ETSI][1][96] = 127,
+ [1][0][RTW89_ETSI][0][96] = 127,
+ [1][0][RTW89_MKK][1][96] = 127,
+ [1][0][RTW89_MKK][0][96] = 127,
+ [1][0][RTW89_IC][1][96] = -4,
+ [1][0][RTW89_KCC][1][96] = -2,
+ [1][0][RTW89_KCC][0][96] = 127,
+ [1][0][RTW89_ACMA][1][96] = 127,
+ [1][0][RTW89_ACMA][0][96] = 127,
+ [1][0][RTW89_CHILE][1][96] = 127,
+ [1][0][RTW89_QATAR][1][96] = 127,
+ [1][0][RTW89_QATAR][0][96] = 127,
+ [1][0][RTW89_UK][1][96] = 127,
+ [1][0][RTW89_UK][0][96] = 127,
+ [1][0][RTW89_FCC][1][98] = -4,
+ [1][0][RTW89_FCC][2][98] = 127,
+ [1][0][RTW89_ETSI][1][98] = 127,
+ [1][0][RTW89_ETSI][0][98] = 127,
+ [1][0][RTW89_MKK][1][98] = 127,
+ [1][0][RTW89_MKK][0][98] = 127,
+ [1][0][RTW89_IC][1][98] = -4,
+ [1][0][RTW89_KCC][1][98] = -2,
+ [1][0][RTW89_KCC][0][98] = 127,
+ [1][0][RTW89_ACMA][1][98] = 127,
+ [1][0][RTW89_ACMA][0][98] = 127,
+ [1][0][RTW89_CHILE][1][98] = 127,
+ [1][0][RTW89_QATAR][1][98] = 127,
+ [1][0][RTW89_QATAR][0][98] = 127,
+ [1][0][RTW89_UK][1][98] = 127,
+ [1][0][RTW89_UK][0][98] = 127,
+ [1][0][RTW89_FCC][1][100] = -4,
+ [1][0][RTW89_FCC][2][100] = 127,
+ [1][0][RTW89_ETSI][1][100] = 127,
+ [1][0][RTW89_ETSI][0][100] = 127,
+ [1][0][RTW89_MKK][1][100] = 127,
+ [1][0][RTW89_MKK][0][100] = 127,
+ [1][0][RTW89_IC][1][100] = -4,
+ [1][0][RTW89_KCC][1][100] = -2,
+ [1][0][RTW89_KCC][0][100] = 127,
+ [1][0][RTW89_ACMA][1][100] = 127,
+ [1][0][RTW89_ACMA][0][100] = 127,
+ [1][0][RTW89_CHILE][1][100] = 127,
+ [1][0][RTW89_QATAR][1][100] = 127,
+ [1][0][RTW89_QATAR][0][100] = 127,
+ [1][0][RTW89_UK][1][100] = 127,
+ [1][0][RTW89_UK][0][100] = 127,
+ [1][0][RTW89_FCC][1][102] = -4,
+ [1][0][RTW89_FCC][2][102] = 127,
+ [1][0][RTW89_ETSI][1][102] = 127,
+ [1][0][RTW89_ETSI][0][102] = 127,
+ [1][0][RTW89_MKK][1][102] = 127,
+ [1][0][RTW89_MKK][0][102] = 127,
+ [1][0][RTW89_IC][1][102] = -4,
+ [1][0][RTW89_KCC][1][102] = -2,
+ [1][0][RTW89_KCC][0][102] = 127,
+ [1][0][RTW89_ACMA][1][102] = 127,
+ [1][0][RTW89_ACMA][0][102] = 127,
+ [1][0][RTW89_CHILE][1][102] = 127,
+ [1][0][RTW89_QATAR][1][102] = 127,
+ [1][0][RTW89_QATAR][0][102] = 127,
+ [1][0][RTW89_UK][1][102] = 127,
+ [1][0][RTW89_UK][0][102] = 127,
+ [1][0][RTW89_FCC][1][104] = -4,
+ [1][0][RTW89_FCC][2][104] = 127,
+ [1][0][RTW89_ETSI][1][104] = 127,
+ [1][0][RTW89_ETSI][0][104] = 127,
+ [1][0][RTW89_MKK][1][104] = 127,
+ [1][0][RTW89_MKK][0][104] = 127,
+ [1][0][RTW89_IC][1][104] = -4,
+ [1][0][RTW89_KCC][1][104] = -2,
+ [1][0][RTW89_KCC][0][104] = 127,
+ [1][0][RTW89_ACMA][1][104] = 127,
+ [1][0][RTW89_ACMA][0][104] = 127,
+ [1][0][RTW89_CHILE][1][104] = 127,
+ [1][0][RTW89_QATAR][1][104] = 127,
+ [1][0][RTW89_QATAR][0][104] = 127,
+ [1][0][RTW89_UK][1][104] = 127,
+ [1][0][RTW89_UK][0][104] = 127,
+ [1][0][RTW89_FCC][1][105] = -4,
+ [1][0][RTW89_FCC][2][105] = 127,
+ [1][0][RTW89_ETSI][1][105] = 127,
+ [1][0][RTW89_ETSI][0][105] = 127,
+ [1][0][RTW89_MKK][1][105] = 127,
+ [1][0][RTW89_MKK][0][105] = 127,
+ [1][0][RTW89_IC][1][105] = -4,
+ [1][0][RTW89_KCC][1][105] = -2,
+ [1][0][RTW89_KCC][0][105] = 127,
+ [1][0][RTW89_ACMA][1][105] = 127,
+ [1][0][RTW89_ACMA][0][105] = 127,
+ [1][0][RTW89_CHILE][1][105] = 127,
+ [1][0][RTW89_QATAR][1][105] = 127,
+ [1][0][RTW89_QATAR][0][105] = 127,
+ [1][0][RTW89_UK][1][105] = 127,
+ [1][0][RTW89_UK][0][105] = 127,
+ [1][0][RTW89_FCC][1][107] = 1,
+ [1][0][RTW89_FCC][2][107] = 127,
+ [1][0][RTW89_ETSI][1][107] = 127,
+ [1][0][RTW89_ETSI][0][107] = 127,
+ [1][0][RTW89_MKK][1][107] = 127,
+ [1][0][RTW89_MKK][0][107] = 127,
+ [1][0][RTW89_IC][1][107] = 1,
+ [1][0][RTW89_KCC][1][107] = -2,
+ [1][0][RTW89_KCC][0][107] = 127,
+ [1][0][RTW89_ACMA][1][107] = 127,
+ [1][0][RTW89_ACMA][0][107] = 127,
+ [1][0][RTW89_CHILE][1][107] = 127,
+ [1][0][RTW89_QATAR][1][107] = 127,
+ [1][0][RTW89_QATAR][0][107] = 127,
+ [1][0][RTW89_UK][1][107] = 127,
+ [1][0][RTW89_UK][0][107] = 127,
+ [1][0][RTW89_FCC][1][109] = 2,
+ [1][0][RTW89_FCC][2][109] = 127,
+ [1][0][RTW89_ETSI][1][109] = 127,
+ [1][0][RTW89_ETSI][0][109] = 127,
+ [1][0][RTW89_MKK][1][109] = 127,
+ [1][0][RTW89_MKK][0][109] = 127,
+ [1][0][RTW89_IC][1][109] = 2,
+ [1][0][RTW89_KCC][1][109] = 127,
+ [1][0][RTW89_KCC][0][109] = 127,
+ [1][0][RTW89_ACMA][1][109] = 127,
+ [1][0][RTW89_ACMA][0][109] = 127,
+ [1][0][RTW89_CHILE][1][109] = 127,
+ [1][0][RTW89_QATAR][1][109] = 127,
+ [1][0][RTW89_QATAR][0][109] = 127,
+ [1][0][RTW89_UK][1][109] = 127,
+ [1][0][RTW89_UK][0][109] = 127,
+ [1][0][RTW89_FCC][1][111] = 127,
+ [1][0][RTW89_FCC][2][111] = 127,
+ [1][0][RTW89_ETSI][1][111] = 127,
+ [1][0][RTW89_ETSI][0][111] = 127,
+ [1][0][RTW89_MKK][1][111] = 127,
+ [1][0][RTW89_MKK][0][111] = 127,
+ [1][0][RTW89_IC][1][111] = 127,
+ [1][0][RTW89_KCC][1][111] = 127,
+ [1][0][RTW89_KCC][0][111] = 127,
+ [1][0][RTW89_ACMA][1][111] = 127,
+ [1][0][RTW89_ACMA][0][111] = 127,
+ [1][0][RTW89_CHILE][1][111] = 127,
+ [1][0][RTW89_QATAR][1][111] = 127,
+ [1][0][RTW89_QATAR][0][111] = 127,
+ [1][0][RTW89_UK][1][111] = 127,
+ [1][0][RTW89_UK][0][111] = 127,
+ [1][0][RTW89_FCC][1][113] = 127,
+ [1][0][RTW89_FCC][2][113] = 127,
+ [1][0][RTW89_ETSI][1][113] = 127,
+ [1][0][RTW89_ETSI][0][113] = 127,
+ [1][0][RTW89_MKK][1][113] = 127,
+ [1][0][RTW89_MKK][0][113] = 127,
+ [1][0][RTW89_IC][1][113] = 127,
+ [1][0][RTW89_KCC][1][113] = 127,
+ [1][0][RTW89_KCC][0][113] = 127,
+ [1][0][RTW89_ACMA][1][113] = 127,
+ [1][0][RTW89_ACMA][0][113] = 127,
+ [1][0][RTW89_CHILE][1][113] = 127,
+ [1][0][RTW89_QATAR][1][113] = 127,
+ [1][0][RTW89_QATAR][0][113] = 127,
+ [1][0][RTW89_UK][1][113] = 127,
+ [1][0][RTW89_UK][0][113] = 127,
+ [1][0][RTW89_FCC][1][115] = 127,
+ [1][0][RTW89_FCC][2][115] = 127,
+ [1][0][RTW89_ETSI][1][115] = 127,
+ [1][0][RTW89_ETSI][0][115] = 127,
+ [1][0][RTW89_MKK][1][115] = 127,
+ [1][0][RTW89_MKK][0][115] = 127,
+ [1][0][RTW89_IC][1][115] = 127,
+ [1][0][RTW89_KCC][1][115] = 127,
+ [1][0][RTW89_KCC][0][115] = 127,
+ [1][0][RTW89_ACMA][1][115] = 127,
+ [1][0][RTW89_ACMA][0][115] = 127,
+ [1][0][RTW89_CHILE][1][115] = 127,
+ [1][0][RTW89_QATAR][1][115] = 127,
+ [1][0][RTW89_QATAR][0][115] = 127,
+ [1][0][RTW89_UK][1][115] = 127,
+ [1][0][RTW89_UK][0][115] = 127,
+ [1][0][RTW89_FCC][1][117] = 127,
+ [1][0][RTW89_FCC][2][117] = 127,
+ [1][0][RTW89_ETSI][1][117] = 127,
+ [1][0][RTW89_ETSI][0][117] = 127,
+ [1][0][RTW89_MKK][1][117] = 127,
+ [1][0][RTW89_MKK][0][117] = 127,
+ [1][0][RTW89_IC][1][117] = 127,
+ [1][0][RTW89_KCC][1][117] = 127,
+ [1][0][RTW89_KCC][0][117] = 127,
+ [1][0][RTW89_ACMA][1][117] = 127,
+ [1][0][RTW89_ACMA][0][117] = 127,
+ [1][0][RTW89_CHILE][1][117] = 127,
+ [1][0][RTW89_QATAR][1][117] = 127,
+ [1][0][RTW89_QATAR][0][117] = 127,
+ [1][0][RTW89_UK][1][117] = 127,
+ [1][0][RTW89_UK][0][117] = 127,
+ [1][0][RTW89_FCC][1][119] = 127,
+ [1][0][RTW89_FCC][2][119] = 127,
+ [1][0][RTW89_ETSI][1][119] = 127,
+ [1][0][RTW89_ETSI][0][119] = 127,
+ [1][0][RTW89_MKK][1][119] = 127,
+ [1][0][RTW89_MKK][0][119] = 127,
+ [1][0][RTW89_IC][1][119] = 127,
+ [1][0][RTW89_KCC][1][119] = 127,
+ [1][0][RTW89_KCC][0][119] = 127,
+ [1][0][RTW89_ACMA][1][119] = 127,
+ [1][0][RTW89_ACMA][0][119] = 127,
+ [1][0][RTW89_CHILE][1][119] = 127,
+ [1][0][RTW89_QATAR][1][119] = 127,
+ [1][0][RTW89_QATAR][0][119] = 127,
+ [1][0][RTW89_UK][1][119] = 127,
+ [1][0][RTW89_UK][0][119] = 127,
+ [1][1][RTW89_FCC][1][0] = -26,
+ [1][1][RTW89_FCC][2][0] = 44,
+ [1][1][RTW89_ETSI][1][0] = 32,
+ [1][1][RTW89_ETSI][0][0] = -6,
+ [1][1][RTW89_MKK][1][0] = 30,
+ [1][1][RTW89_MKK][0][0] = -10,
+ [1][1][RTW89_IC][1][0] = -26,
+ [1][1][RTW89_KCC][1][0] = -14,
+ [1][1][RTW89_KCC][0][0] = -14,
+ [1][1][RTW89_ACMA][1][0] = 32,
+ [1][1][RTW89_ACMA][0][0] = -6,
+ [1][1][RTW89_CHILE][1][0] = -26,
+ [1][1][RTW89_QATAR][1][0] = 32,
+ [1][1][RTW89_QATAR][0][0] = -6,
+ [1][1][RTW89_UK][1][0] = 32,
+ [1][1][RTW89_UK][0][0] = -6,
+ [1][1][RTW89_FCC][1][2] = -28,
+ [1][1][RTW89_FCC][2][2] = 44,
+ [1][1][RTW89_ETSI][1][2] = 32,
+ [1][1][RTW89_ETSI][0][2] = -6,
+ [1][1][RTW89_MKK][1][2] = 30,
+ [1][1][RTW89_MKK][0][2] = -10,
+ [1][1][RTW89_IC][1][2] = -28,
+ [1][1][RTW89_KCC][1][2] = -14,
+ [1][1][RTW89_KCC][0][2] = -14,
+ [1][1][RTW89_ACMA][1][2] = 32,
+ [1][1][RTW89_ACMA][0][2] = -6,
+ [1][1][RTW89_CHILE][1][2] = -28,
+ [1][1][RTW89_QATAR][1][2] = 32,
+ [1][1][RTW89_QATAR][0][2] = -6,
+ [1][1][RTW89_UK][1][2] = 32,
+ [1][1][RTW89_UK][0][2] = -6,
+ [1][1][RTW89_FCC][1][4] = -28,
+ [1][1][RTW89_FCC][2][4] = 44,
+ [1][1][RTW89_ETSI][1][4] = 32,
+ [1][1][RTW89_ETSI][0][4] = -6,
+ [1][1][RTW89_MKK][1][4] = 30,
+ [1][1][RTW89_MKK][0][4] = -10,
+ [1][1][RTW89_IC][1][4] = -28,
+ [1][1][RTW89_KCC][1][4] = -14,
+ [1][1][RTW89_KCC][0][4] = -14,
+ [1][1][RTW89_ACMA][1][4] = 32,
+ [1][1][RTW89_ACMA][0][4] = -6,
+ [1][1][RTW89_CHILE][1][4] = -28,
+ [1][1][RTW89_QATAR][1][4] = 32,
+ [1][1][RTW89_QATAR][0][4] = -6,
+ [1][1][RTW89_UK][1][4] = 32,
+ [1][1][RTW89_UK][0][4] = -6,
+ [1][1][RTW89_FCC][1][6] = -28,
+ [1][1][RTW89_FCC][2][6] = 44,
+ [1][1][RTW89_ETSI][1][6] = 32,
+ [1][1][RTW89_ETSI][0][6] = -6,
+ [1][1][RTW89_MKK][1][6] = 30,
+ [1][1][RTW89_MKK][0][6] = -10,
+ [1][1][RTW89_IC][1][6] = -28,
+ [1][1][RTW89_KCC][1][6] = -14,
+ [1][1][RTW89_KCC][0][6] = -14,
+ [1][1][RTW89_ACMA][1][6] = 32,
+ [1][1][RTW89_ACMA][0][6] = -6,
+ [1][1][RTW89_CHILE][1][6] = -28,
+ [1][1][RTW89_QATAR][1][6] = 32,
+ [1][1][RTW89_QATAR][0][6] = -6,
+ [1][1][RTW89_UK][1][6] = 32,
+ [1][1][RTW89_UK][0][6] = -6,
+ [1][1][RTW89_FCC][1][8] = -28,
+ [1][1][RTW89_FCC][2][8] = 44,
+ [1][1][RTW89_ETSI][1][8] = 32,
+ [1][1][RTW89_ETSI][0][8] = -6,
+ [1][1][RTW89_MKK][1][8] = 30,
+ [1][1][RTW89_MKK][0][8] = -10,
+ [1][1][RTW89_IC][1][8] = -28,
+ [1][1][RTW89_KCC][1][8] = -14,
+ [1][1][RTW89_KCC][0][8] = -14,
+ [1][1][RTW89_ACMA][1][8] = 32,
+ [1][1][RTW89_ACMA][0][8] = -6,
+ [1][1][RTW89_CHILE][1][8] = -28,
+ [1][1][RTW89_QATAR][1][8] = 32,
+ [1][1][RTW89_QATAR][0][8] = -6,
+ [1][1][RTW89_UK][1][8] = 32,
+ [1][1][RTW89_UK][0][8] = -6,
+ [1][1][RTW89_FCC][1][10] = -28,
+ [1][1][RTW89_FCC][2][10] = 44,
+ [1][1][RTW89_ETSI][1][10] = 32,
+ [1][1][RTW89_ETSI][0][10] = -6,
+ [1][1][RTW89_MKK][1][10] = 30,
+ [1][1][RTW89_MKK][0][10] = -10,
+ [1][1][RTW89_IC][1][10] = -28,
+ [1][1][RTW89_KCC][1][10] = -14,
+ [1][1][RTW89_KCC][0][10] = -14,
+ [1][1][RTW89_ACMA][1][10] = 32,
+ [1][1][RTW89_ACMA][0][10] = -6,
+ [1][1][RTW89_CHILE][1][10] = -28,
+ [1][1][RTW89_QATAR][1][10] = 32,
+ [1][1][RTW89_QATAR][0][10] = -6,
+ [1][1][RTW89_UK][1][10] = 32,
+ [1][1][RTW89_UK][0][10] = -6,
+ [1][1][RTW89_FCC][1][12] = -28,
+ [1][1][RTW89_FCC][2][12] = 44,
+ [1][1][RTW89_ETSI][1][12] = 32,
+ [1][1][RTW89_ETSI][0][12] = -6,
+ [1][1][RTW89_MKK][1][12] = 30,
+ [1][1][RTW89_MKK][0][12] = -10,
+ [1][1][RTW89_IC][1][12] = -28,
+ [1][1][RTW89_KCC][1][12] = -14,
+ [1][1][RTW89_KCC][0][12] = -14,
+ [1][1][RTW89_ACMA][1][12] = 32,
+ [1][1][RTW89_ACMA][0][12] = -6,
+ [1][1][RTW89_CHILE][1][12] = -28,
+ [1][1][RTW89_QATAR][1][12] = 32,
+ [1][1][RTW89_QATAR][0][12] = -6,
+ [1][1][RTW89_UK][1][12] = 32,
+ [1][1][RTW89_UK][0][12] = -6,
+ [1][1][RTW89_FCC][1][14] = -28,
+ [1][1][RTW89_FCC][2][14] = 44,
+ [1][1][RTW89_ETSI][1][14] = 32,
+ [1][1][RTW89_ETSI][0][14] = -6,
+ [1][1][RTW89_MKK][1][14] = 30,
+ [1][1][RTW89_MKK][0][14] = -10,
+ [1][1][RTW89_IC][1][14] = -28,
+ [1][1][RTW89_KCC][1][14] = -14,
+ [1][1][RTW89_KCC][0][14] = -14,
+ [1][1][RTW89_ACMA][1][14] = 32,
+ [1][1][RTW89_ACMA][0][14] = -6,
+ [1][1][RTW89_CHILE][1][14] = -28,
+ [1][1][RTW89_QATAR][1][14] = 32,
+ [1][1][RTW89_QATAR][0][14] = -6,
+ [1][1][RTW89_UK][1][14] = 32,
+ [1][1][RTW89_UK][0][14] = -6,
+ [1][1][RTW89_FCC][1][15] = -28,
+ [1][1][RTW89_FCC][2][15] = 44,
+ [1][1][RTW89_ETSI][1][15] = 32,
+ [1][1][RTW89_ETSI][0][15] = -6,
+ [1][1][RTW89_MKK][1][15] = 30,
+ [1][1][RTW89_MKK][0][15] = -10,
+ [1][1][RTW89_IC][1][15] = -28,
+ [1][1][RTW89_KCC][1][15] = -14,
+ [1][1][RTW89_KCC][0][15] = -14,
+ [1][1][RTW89_ACMA][1][15] = 32,
+ [1][1][RTW89_ACMA][0][15] = -6,
+ [1][1][RTW89_CHILE][1][15] = -28,
+ [1][1][RTW89_QATAR][1][15] = 32,
+ [1][1][RTW89_QATAR][0][15] = -6,
+ [1][1][RTW89_UK][1][15] = 32,
+ [1][1][RTW89_UK][0][15] = -6,
+ [1][1][RTW89_FCC][1][17] = -28,
+ [1][1][RTW89_FCC][2][17] = 44,
+ [1][1][RTW89_ETSI][1][17] = 32,
+ [1][1][RTW89_ETSI][0][17] = -6,
+ [1][1][RTW89_MKK][1][17] = 30,
+ [1][1][RTW89_MKK][0][17] = -10,
+ [1][1][RTW89_IC][1][17] = -28,
+ [1][1][RTW89_KCC][1][17] = -14,
+ [1][1][RTW89_KCC][0][17] = -14,
+ [1][1][RTW89_ACMA][1][17] = 32,
+ [1][1][RTW89_ACMA][0][17] = -6,
+ [1][1][RTW89_CHILE][1][17] = -28,
+ [1][1][RTW89_QATAR][1][17] = 32,
+ [1][1][RTW89_QATAR][0][17] = -6,
+ [1][1][RTW89_UK][1][17] = 32,
+ [1][1][RTW89_UK][0][17] = -6,
+ [1][1][RTW89_FCC][1][19] = -28,
+ [1][1][RTW89_FCC][2][19] = 44,
+ [1][1][RTW89_ETSI][1][19] = 32,
+ [1][1][RTW89_ETSI][0][19] = -6,
+ [1][1][RTW89_MKK][1][19] = 30,
+ [1][1][RTW89_MKK][0][19] = -10,
+ [1][1][RTW89_IC][1][19] = -28,
+ [1][1][RTW89_KCC][1][19] = -14,
+ [1][1][RTW89_KCC][0][19] = -14,
+ [1][1][RTW89_ACMA][1][19] = 32,
+ [1][1][RTW89_ACMA][0][19] = -6,
+ [1][1][RTW89_CHILE][1][19] = -28,
+ [1][1][RTW89_QATAR][1][19] = 32,
+ [1][1][RTW89_QATAR][0][19] = -6,
+ [1][1][RTW89_UK][1][19] = 32,
+ [1][1][RTW89_UK][0][19] = -6,
+ [1][1][RTW89_FCC][1][21] = -28,
+ [1][1][RTW89_FCC][2][21] = 44,
+ [1][1][RTW89_ETSI][1][21] = 32,
+ [1][1][RTW89_ETSI][0][21] = -6,
+ [1][1][RTW89_MKK][1][21] = 30,
+ [1][1][RTW89_MKK][0][21] = -10,
+ [1][1][RTW89_IC][1][21] = -28,
+ [1][1][RTW89_KCC][1][21] = -14,
+ [1][1][RTW89_KCC][0][21] = -14,
+ [1][1][RTW89_ACMA][1][21] = 32,
+ [1][1][RTW89_ACMA][0][21] = -6,
+ [1][1][RTW89_CHILE][1][21] = -28,
+ [1][1][RTW89_QATAR][1][21] = 32,
+ [1][1][RTW89_QATAR][0][21] = -6,
+ [1][1][RTW89_UK][1][21] = 32,
+ [1][1][RTW89_UK][0][21] = -6,
+ [1][1][RTW89_FCC][1][23] = -28,
+ [1][1][RTW89_FCC][2][23] = 44,
+ [1][1][RTW89_ETSI][1][23] = 32,
+ [1][1][RTW89_ETSI][0][23] = -6,
+ [1][1][RTW89_MKK][1][23] = 32,
+ [1][1][RTW89_MKK][0][23] = -10,
+ [1][1][RTW89_IC][1][23] = -28,
+ [1][1][RTW89_KCC][1][23] = -14,
+ [1][1][RTW89_KCC][0][23] = -14,
+ [1][1][RTW89_ACMA][1][23] = 32,
+ [1][1][RTW89_ACMA][0][23] = -6,
+ [1][1][RTW89_CHILE][1][23] = -28,
+ [1][1][RTW89_QATAR][1][23] = 32,
+ [1][1][RTW89_QATAR][0][23] = -6,
+ [1][1][RTW89_UK][1][23] = 32,
+ [1][1][RTW89_UK][0][23] = -6,
+ [1][1][RTW89_FCC][1][25] = -28,
+ [1][1][RTW89_FCC][2][25] = 44,
+ [1][1][RTW89_ETSI][1][25] = 32,
+ [1][1][RTW89_ETSI][0][25] = -6,
+ [1][1][RTW89_MKK][1][25] = 32,
+ [1][1][RTW89_MKK][0][25] = -10,
+ [1][1][RTW89_IC][1][25] = -28,
+ [1][1][RTW89_KCC][1][25] = -14,
+ [1][1][RTW89_KCC][0][25] = -14,
+ [1][1][RTW89_ACMA][1][25] = 32,
+ [1][1][RTW89_ACMA][0][25] = -6,
+ [1][1][RTW89_CHILE][1][25] = -28,
+ [1][1][RTW89_QATAR][1][25] = 32,
+ [1][1][RTW89_QATAR][0][25] = -6,
+ [1][1][RTW89_UK][1][25] = 32,
+ [1][1][RTW89_UK][0][25] = -6,
+ [1][1][RTW89_FCC][1][27] = -28,
+ [1][1][RTW89_FCC][2][27] = 44,
+ [1][1][RTW89_ETSI][1][27] = 32,
+ [1][1][RTW89_ETSI][0][27] = -6,
+ [1][1][RTW89_MKK][1][27] = 32,
+ [1][1][RTW89_MKK][0][27] = -10,
+ [1][1][RTW89_IC][1][27] = -28,
+ [1][1][RTW89_KCC][1][27] = -14,
+ [1][1][RTW89_KCC][0][27] = -14,
+ [1][1][RTW89_ACMA][1][27] = 32,
+ [1][1][RTW89_ACMA][0][27] = -6,
+ [1][1][RTW89_CHILE][1][27] = -28,
+ [1][1][RTW89_QATAR][1][27] = 32,
+ [1][1][RTW89_QATAR][0][27] = -6,
+ [1][1][RTW89_UK][1][27] = 32,
+ [1][1][RTW89_UK][0][27] = -6,
+ [1][1][RTW89_FCC][1][29] = -28,
+ [1][1][RTW89_FCC][2][29] = 44,
+ [1][1][RTW89_ETSI][1][29] = 32,
+ [1][1][RTW89_ETSI][0][29] = -6,
+ [1][1][RTW89_MKK][1][29] = 32,
+ [1][1][RTW89_MKK][0][29] = -10,
+ [1][1][RTW89_IC][1][29] = -28,
+ [1][1][RTW89_KCC][1][29] = -14,
+ [1][1][RTW89_KCC][0][29] = -14,
+ [1][1][RTW89_ACMA][1][29] = 32,
+ [1][1][RTW89_ACMA][0][29] = -6,
+ [1][1][RTW89_CHILE][1][29] = -28,
+ [1][1][RTW89_QATAR][1][29] = 32,
+ [1][1][RTW89_QATAR][0][29] = -6,
+ [1][1][RTW89_UK][1][29] = 32,
+ [1][1][RTW89_UK][0][29] = -6,
+ [1][1][RTW89_FCC][1][30] = -28,
+ [1][1][RTW89_FCC][2][30] = 44,
+ [1][1][RTW89_ETSI][1][30] = 32,
+ [1][1][RTW89_ETSI][0][30] = -6,
+ [1][1][RTW89_MKK][1][30] = 32,
+ [1][1][RTW89_MKK][0][30] = -10,
+ [1][1][RTW89_IC][1][30] = -28,
+ [1][1][RTW89_KCC][1][30] = -14,
+ [1][1][RTW89_KCC][0][30] = -14,
+ [1][1][RTW89_ACMA][1][30] = 32,
+ [1][1][RTW89_ACMA][0][30] = -6,
+ [1][1][RTW89_CHILE][1][30] = -28,
+ [1][1][RTW89_QATAR][1][30] = 32,
+ [1][1][RTW89_QATAR][0][30] = -6,
+ [1][1][RTW89_UK][1][30] = 32,
+ [1][1][RTW89_UK][0][30] = -6,
+ [1][1][RTW89_FCC][1][32] = -28,
+ [1][1][RTW89_FCC][2][32] = 44,
+ [1][1][RTW89_ETSI][1][32] = 32,
+ [1][1][RTW89_ETSI][0][32] = -6,
+ [1][1][RTW89_MKK][1][32] = 32,
+ [1][1][RTW89_MKK][0][32] = -10,
+ [1][1][RTW89_IC][1][32] = -28,
+ [1][1][RTW89_KCC][1][32] = -14,
+ [1][1][RTW89_KCC][0][32] = -14,
+ [1][1][RTW89_ACMA][1][32] = 32,
+ [1][1][RTW89_ACMA][0][32] = -6,
+ [1][1][RTW89_CHILE][1][32] = -28,
+ [1][1][RTW89_QATAR][1][32] = 32,
+ [1][1][RTW89_QATAR][0][32] = -6,
+ [1][1][RTW89_UK][1][32] = 32,
+ [1][1][RTW89_UK][0][32] = -6,
+ [1][1][RTW89_FCC][1][34] = -28,
+ [1][1][RTW89_FCC][2][34] = 44,
+ [1][1][RTW89_ETSI][1][34] = 32,
+ [1][1][RTW89_ETSI][0][34] = -6,
+ [1][1][RTW89_MKK][1][34] = 32,
+ [1][1][RTW89_MKK][0][34] = -10,
+ [1][1][RTW89_IC][1][34] = -28,
+ [1][1][RTW89_KCC][1][34] = -14,
+ [1][1][RTW89_KCC][0][34] = -14,
+ [1][1][RTW89_ACMA][1][34] = 32,
+ [1][1][RTW89_ACMA][0][34] = -6,
+ [1][1][RTW89_CHILE][1][34] = -28,
+ [1][1][RTW89_QATAR][1][34] = 32,
+ [1][1][RTW89_QATAR][0][34] = -6,
+ [1][1][RTW89_UK][1][34] = 32,
+ [1][1][RTW89_UK][0][34] = -6,
+ [1][1][RTW89_FCC][1][36] = -28,
+ [1][1][RTW89_FCC][2][36] = 44,
+ [1][1][RTW89_ETSI][1][36] = 32,
+ [1][1][RTW89_ETSI][0][36] = -6,
+ [1][1][RTW89_MKK][1][36] = 32,
+ [1][1][RTW89_MKK][0][36] = -10,
+ [1][1][RTW89_IC][1][36] = -28,
+ [1][1][RTW89_KCC][1][36] = -14,
+ [1][1][RTW89_KCC][0][36] = -14,
+ [1][1][RTW89_ACMA][1][36] = 32,
+ [1][1][RTW89_ACMA][0][36] = -6,
+ [1][1][RTW89_CHILE][1][36] = -28,
+ [1][1][RTW89_QATAR][1][36] = 32,
+ [1][1][RTW89_QATAR][0][36] = -6,
+ [1][1][RTW89_UK][1][36] = 32,
+ [1][1][RTW89_UK][0][36] = -6,
+ [1][1][RTW89_FCC][1][38] = -28,
+ [1][1][RTW89_FCC][2][38] = 44,
+ [1][1][RTW89_ETSI][1][38] = 32,
+ [1][1][RTW89_ETSI][0][38] = -6,
+ [1][1][RTW89_MKK][1][38] = 32,
+ [1][1][RTW89_MKK][0][38] = -10,
+ [1][1][RTW89_IC][1][38] = -28,
+ [1][1][RTW89_KCC][1][38] = -14,
+ [1][1][RTW89_KCC][0][38] = -14,
+ [1][1][RTW89_ACMA][1][38] = 32,
+ [1][1][RTW89_ACMA][0][38] = -6,
+ [1][1][RTW89_CHILE][1][38] = -28,
+ [1][1][RTW89_QATAR][1][38] = 32,
+ [1][1][RTW89_QATAR][0][38] = -6,
+ [1][1][RTW89_UK][1][38] = 32,
+ [1][1][RTW89_UK][0][38] = -6,
+ [1][1][RTW89_FCC][1][40] = -28,
+ [1][1][RTW89_FCC][2][40] = 44,
+ [1][1][RTW89_ETSI][1][40] = 32,
+ [1][1][RTW89_ETSI][0][40] = -6,
+ [1][1][RTW89_MKK][1][40] = 32,
+ [1][1][RTW89_MKK][0][40] = -10,
+ [1][1][RTW89_IC][1][40] = -28,
+ [1][1][RTW89_KCC][1][40] = -14,
+ [1][1][RTW89_KCC][0][40] = -14,
+ [1][1][RTW89_ACMA][1][40] = 32,
+ [1][1][RTW89_ACMA][0][40] = -6,
+ [1][1][RTW89_CHILE][1][40] = -28,
+ [1][1][RTW89_QATAR][1][40] = 32,
+ [1][1][RTW89_QATAR][0][40] = -6,
+ [1][1][RTW89_UK][1][40] = 32,
+ [1][1][RTW89_UK][0][40] = -6,
+ [1][1][RTW89_FCC][1][42] = -28,
+ [1][1][RTW89_FCC][2][42] = 44,
+ [1][1][RTW89_ETSI][1][42] = 32,
+ [1][1][RTW89_ETSI][0][42] = -6,
+ [1][1][RTW89_MKK][1][42] = 32,
+ [1][1][RTW89_MKK][0][42] = -10,
+ [1][1][RTW89_IC][1][42] = -28,
+ [1][1][RTW89_KCC][1][42] = -14,
+ [1][1][RTW89_KCC][0][42] = -14,
+ [1][1][RTW89_ACMA][1][42] = 32,
+ [1][1][RTW89_ACMA][0][42] = -6,
+ [1][1][RTW89_CHILE][1][42] = -28,
+ [1][1][RTW89_QATAR][1][42] = 32,
+ [1][1][RTW89_QATAR][0][42] = -6,
+ [1][1][RTW89_UK][1][42] = 32,
+ [1][1][RTW89_UK][0][42] = -6,
+ [1][1][RTW89_FCC][1][44] = -28,
+ [1][1][RTW89_FCC][2][44] = 44,
+ [1][1][RTW89_ETSI][1][44] = 34,
+ [1][1][RTW89_ETSI][0][44] = -4,
+ [1][1][RTW89_MKK][1][44] = 4,
+ [1][1][RTW89_MKK][0][44] = -8,
+ [1][1][RTW89_IC][1][44] = -28,
+ [1][1][RTW89_KCC][1][44] = -14,
+ [1][1][RTW89_KCC][0][44] = -14,
+ [1][1][RTW89_ACMA][1][44] = 34,
+ [1][1][RTW89_ACMA][0][44] = -4,
+ [1][1][RTW89_CHILE][1][44] = -28,
+ [1][1][RTW89_QATAR][1][44] = 34,
+ [1][1][RTW89_QATAR][0][44] = -4,
+ [1][1][RTW89_UK][1][44] = 34,
+ [1][1][RTW89_UK][0][44] = -4,
+ [1][1][RTW89_FCC][1][45] = -26,
+ [1][1][RTW89_FCC][2][45] = 127,
+ [1][1][RTW89_ETSI][1][45] = 127,
+ [1][1][RTW89_ETSI][0][45] = 127,
+ [1][1][RTW89_MKK][1][45] = 127,
+ [1][1][RTW89_MKK][0][45] = 127,
+ [1][1][RTW89_IC][1][45] = -26,
+ [1][1][RTW89_KCC][1][45] = -14,
+ [1][1][RTW89_KCC][0][45] = 127,
+ [1][1][RTW89_ACMA][1][45] = 127,
+ [1][1][RTW89_ACMA][0][45] = 127,
+ [1][1][RTW89_CHILE][1][45] = 127,
+ [1][1][RTW89_QATAR][1][45] = 127,
+ [1][1][RTW89_QATAR][0][45] = 127,
+ [1][1][RTW89_UK][1][45] = 127,
+ [1][1][RTW89_UK][0][45] = 127,
+ [1][1][RTW89_FCC][1][47] = -28,
+ [1][1][RTW89_FCC][2][47] = 127,
+ [1][1][RTW89_ETSI][1][47] = 127,
+ [1][1][RTW89_ETSI][0][47] = 127,
+ [1][1][RTW89_MKK][1][47] = 127,
+ [1][1][RTW89_MKK][0][47] = 127,
+ [1][1][RTW89_IC][1][47] = -28,
+ [1][1][RTW89_KCC][1][47] = -14,
+ [1][1][RTW89_KCC][0][47] = 127,
+ [1][1][RTW89_ACMA][1][47] = 127,
+ [1][1][RTW89_ACMA][0][47] = 127,
+ [1][1][RTW89_CHILE][1][47] = 127,
+ [1][1][RTW89_QATAR][1][47] = 127,
+ [1][1][RTW89_QATAR][0][47] = 127,
+ [1][1][RTW89_UK][1][47] = 127,
+ [1][1][RTW89_UK][0][47] = 127,
+ [1][1][RTW89_FCC][1][49] = -28,
+ [1][1][RTW89_FCC][2][49] = 127,
+ [1][1][RTW89_ETSI][1][49] = 127,
+ [1][1][RTW89_ETSI][0][49] = 127,
+ [1][1][RTW89_MKK][1][49] = 127,
+ [1][1][RTW89_MKK][0][49] = 127,
+ [1][1][RTW89_IC][1][49] = -28,
+ [1][1][RTW89_KCC][1][49] = -14,
+ [1][1][RTW89_KCC][0][49] = 127,
+ [1][1][RTW89_ACMA][1][49] = 127,
+ [1][1][RTW89_ACMA][0][49] = 127,
+ [1][1][RTW89_CHILE][1][49] = 127,
+ [1][1][RTW89_QATAR][1][49] = 127,
+ [1][1][RTW89_QATAR][0][49] = 127,
+ [1][1][RTW89_UK][1][49] = 127,
+ [1][1][RTW89_UK][0][49] = 127,
+ [1][1][RTW89_FCC][1][51] = -28,
+ [1][1][RTW89_FCC][2][51] = 127,
+ [1][1][RTW89_ETSI][1][51] = 127,
+ [1][1][RTW89_ETSI][0][51] = 127,
+ [1][1][RTW89_MKK][1][51] = 127,
+ [1][1][RTW89_MKK][0][51] = 127,
+ [1][1][RTW89_IC][1][51] = -28,
+ [1][1][RTW89_KCC][1][51] = -14,
+ [1][1][RTW89_KCC][0][51] = 127,
+ [1][1][RTW89_ACMA][1][51] = 127,
+ [1][1][RTW89_ACMA][0][51] = 127,
+ [1][1][RTW89_CHILE][1][51] = 127,
+ [1][1][RTW89_QATAR][1][51] = 127,
+ [1][1][RTW89_QATAR][0][51] = 127,
+ [1][1][RTW89_UK][1][51] = 127,
+ [1][1][RTW89_UK][0][51] = 127,
+ [1][1][RTW89_FCC][1][53] = -26,
+ [1][1][RTW89_FCC][2][53] = 127,
+ [1][1][RTW89_ETSI][1][53] = 127,
+ [1][1][RTW89_ETSI][0][53] = 127,
+ [1][1][RTW89_MKK][1][53] = 127,
+ [1][1][RTW89_MKK][0][53] = 127,
+ [1][1][RTW89_IC][1][53] = -26,
+ [1][1][RTW89_KCC][1][53] = -14,
+ [1][1][RTW89_KCC][0][53] = 127,
+ [1][1][RTW89_ACMA][1][53] = 127,
+ [1][1][RTW89_ACMA][0][53] = 127,
+ [1][1][RTW89_CHILE][1][53] = 127,
+ [1][1][RTW89_QATAR][1][53] = 127,
+ [1][1][RTW89_QATAR][0][53] = 127,
+ [1][1][RTW89_UK][1][53] = 127,
+ [1][1][RTW89_UK][0][53] = 127,
+ [1][1][RTW89_FCC][1][55] = -28,
+ [1][1][RTW89_FCC][2][55] = 44,
+ [1][1][RTW89_ETSI][1][55] = 127,
+ [1][1][RTW89_ETSI][0][55] = 127,
+ [1][1][RTW89_MKK][1][55] = 127,
+ [1][1][RTW89_MKK][0][55] = 127,
+ [1][1][RTW89_IC][1][55] = -28,
+ [1][1][RTW89_KCC][1][55] = -14,
+ [1][1][RTW89_KCC][0][55] = 127,
+ [1][1][RTW89_ACMA][1][55] = 127,
+ [1][1][RTW89_ACMA][0][55] = 127,
+ [1][1][RTW89_CHILE][1][55] = 127,
+ [1][1][RTW89_QATAR][1][55] = 127,
+ [1][1][RTW89_QATAR][0][55] = 127,
+ [1][1][RTW89_UK][1][55] = 127,
+ [1][1][RTW89_UK][0][55] = 127,
+ [1][1][RTW89_FCC][1][57] = -28,
+ [1][1][RTW89_FCC][2][57] = 44,
+ [1][1][RTW89_ETSI][1][57] = 127,
+ [1][1][RTW89_ETSI][0][57] = 127,
+ [1][1][RTW89_MKK][1][57] = 127,
+ [1][1][RTW89_MKK][0][57] = 127,
+ [1][1][RTW89_IC][1][57] = -28,
+ [1][1][RTW89_KCC][1][57] = -14,
+ [1][1][RTW89_KCC][0][57] = 127,
+ [1][1][RTW89_ACMA][1][57] = 127,
+ [1][1][RTW89_ACMA][0][57] = 127,
+ [1][1][RTW89_CHILE][1][57] = 127,
+ [1][1][RTW89_QATAR][1][57] = 127,
+ [1][1][RTW89_QATAR][0][57] = 127,
+ [1][1][RTW89_UK][1][57] = 127,
+ [1][1][RTW89_UK][0][57] = 127,
+ [1][1][RTW89_FCC][1][59] = -28,
+ [1][1][RTW89_FCC][2][59] = 44,
+ [1][1][RTW89_ETSI][1][59] = 127,
+ [1][1][RTW89_ETSI][0][59] = 127,
+ [1][1][RTW89_MKK][1][59] = 127,
+ [1][1][RTW89_MKK][0][59] = 127,
+ [1][1][RTW89_IC][1][59] = -28,
+ [1][1][RTW89_KCC][1][59] = -14,
+ [1][1][RTW89_KCC][0][59] = 127,
+ [1][1][RTW89_ACMA][1][59] = 127,
+ [1][1][RTW89_ACMA][0][59] = 127,
+ [1][1][RTW89_CHILE][1][59] = 127,
+ [1][1][RTW89_QATAR][1][59] = 127,
+ [1][1][RTW89_QATAR][0][59] = 127,
+ [1][1][RTW89_UK][1][59] = 127,
+ [1][1][RTW89_UK][0][59] = 127,
+ [1][1][RTW89_FCC][1][60] = -28,
+ [1][1][RTW89_FCC][2][60] = 44,
+ [1][1][RTW89_ETSI][1][60] = 127,
+ [1][1][RTW89_ETSI][0][60] = 127,
+ [1][1][RTW89_MKK][1][60] = 127,
+ [1][1][RTW89_MKK][0][60] = 127,
+ [1][1][RTW89_IC][1][60] = -28,
+ [1][1][RTW89_KCC][1][60] = -14,
+ [1][1][RTW89_KCC][0][60] = 127,
+ [1][1][RTW89_ACMA][1][60] = 127,
+ [1][1][RTW89_ACMA][0][60] = 127,
+ [1][1][RTW89_CHILE][1][60] = 127,
+ [1][1][RTW89_QATAR][1][60] = 127,
+ [1][1][RTW89_QATAR][0][60] = 127,
+ [1][1][RTW89_UK][1][60] = 127,
+ [1][1][RTW89_UK][0][60] = 127,
+ [1][1][RTW89_FCC][1][62] = -28,
+ [1][1][RTW89_FCC][2][62] = 44,
+ [1][1][RTW89_ETSI][1][62] = 127,
+ [1][1][RTW89_ETSI][0][62] = 127,
+ [1][1][RTW89_MKK][1][62] = 127,
+ [1][1][RTW89_MKK][0][62] = 127,
+ [1][1][RTW89_IC][1][62] = -28,
+ [1][1][RTW89_KCC][1][62] = -14,
+ [1][1][RTW89_KCC][0][62] = 127,
+ [1][1][RTW89_ACMA][1][62] = 127,
+ [1][1][RTW89_ACMA][0][62] = 127,
+ [1][1][RTW89_CHILE][1][62] = 127,
+ [1][1][RTW89_QATAR][1][62] = 127,
+ [1][1][RTW89_QATAR][0][62] = 127,
+ [1][1][RTW89_UK][1][62] = 127,
+ [1][1][RTW89_UK][0][62] = 127,
+ [1][1][RTW89_FCC][1][64] = -28,
+ [1][1][RTW89_FCC][2][64] = 44,
+ [1][1][RTW89_ETSI][1][64] = 127,
+ [1][1][RTW89_ETSI][0][64] = 127,
+ [1][1][RTW89_MKK][1][64] = 127,
+ [1][1][RTW89_MKK][0][64] = 127,
+ [1][1][RTW89_IC][1][64] = -28,
+ [1][1][RTW89_KCC][1][64] = -14,
+ [1][1][RTW89_KCC][0][64] = 127,
+ [1][1][RTW89_ACMA][1][64] = 127,
+ [1][1][RTW89_ACMA][0][64] = 127,
+ [1][1][RTW89_CHILE][1][64] = 127,
+ [1][1][RTW89_QATAR][1][64] = 127,
+ [1][1][RTW89_QATAR][0][64] = 127,
+ [1][1][RTW89_UK][1][64] = 127,
+ [1][1][RTW89_UK][0][64] = 127,
+ [1][1][RTW89_FCC][1][66] = -28,
+ [1][1][RTW89_FCC][2][66] = 44,
+ [1][1][RTW89_ETSI][1][66] = 127,
+ [1][1][RTW89_ETSI][0][66] = 127,
+ [1][1][RTW89_MKK][1][66] = 127,
+ [1][1][RTW89_MKK][0][66] = 127,
+ [1][1][RTW89_IC][1][66] = -28,
+ [1][1][RTW89_KCC][1][66] = -14,
+ [1][1][RTW89_KCC][0][66] = 127,
+ [1][1][RTW89_ACMA][1][66] = 127,
+ [1][1][RTW89_ACMA][0][66] = 127,
+ [1][1][RTW89_CHILE][1][66] = 127,
+ [1][1][RTW89_QATAR][1][66] = 127,
+ [1][1][RTW89_QATAR][0][66] = 127,
+ [1][1][RTW89_UK][1][66] = 127,
+ [1][1][RTW89_UK][0][66] = 127,
+ [1][1][RTW89_FCC][1][68] = -28,
+ [1][1][RTW89_FCC][2][68] = 44,
+ [1][1][RTW89_ETSI][1][68] = 127,
+ [1][1][RTW89_ETSI][0][68] = 127,
+ [1][1][RTW89_MKK][1][68] = 127,
+ [1][1][RTW89_MKK][0][68] = 127,
+ [1][1][RTW89_IC][1][68] = -28,
+ [1][1][RTW89_KCC][1][68] = -14,
+ [1][1][RTW89_KCC][0][68] = 127,
+ [1][1][RTW89_ACMA][1][68] = 127,
+ [1][1][RTW89_ACMA][0][68] = 127,
+ [1][1][RTW89_CHILE][1][68] = 127,
+ [1][1][RTW89_QATAR][1][68] = 127,
+ [1][1][RTW89_QATAR][0][68] = 127,
+ [1][1][RTW89_UK][1][68] = 127,
+ [1][1][RTW89_UK][0][68] = 127,
+ [1][1][RTW89_FCC][1][70] = -26,
+ [1][1][RTW89_FCC][2][70] = 44,
+ [1][1][RTW89_ETSI][1][70] = 127,
+ [1][1][RTW89_ETSI][0][70] = 127,
+ [1][1][RTW89_MKK][1][70] = 127,
+ [1][1][RTW89_MKK][0][70] = 127,
+ [1][1][RTW89_IC][1][70] = -26,
+ [1][1][RTW89_KCC][1][70] = -14,
+ [1][1][RTW89_KCC][0][70] = 127,
+ [1][1][RTW89_ACMA][1][70] = 127,
+ [1][1][RTW89_ACMA][0][70] = 127,
+ [1][1][RTW89_CHILE][1][70] = 127,
+ [1][1][RTW89_QATAR][1][70] = 127,
+ [1][1][RTW89_QATAR][0][70] = 127,
+ [1][1][RTW89_UK][1][70] = 127,
+ [1][1][RTW89_UK][0][70] = 127,
+ [1][1][RTW89_FCC][1][72] = -28,
+ [1][1][RTW89_FCC][2][72] = 44,
+ [1][1][RTW89_ETSI][1][72] = 127,
+ [1][1][RTW89_ETSI][0][72] = 127,
+ [1][1][RTW89_MKK][1][72] = 127,
+ [1][1][RTW89_MKK][0][72] = 127,
+ [1][1][RTW89_IC][1][72] = -28,
+ [1][1][RTW89_KCC][1][72] = -14,
+ [1][1][RTW89_KCC][0][72] = 127,
+ [1][1][RTW89_ACMA][1][72] = 127,
+ [1][1][RTW89_ACMA][0][72] = 127,
+ [1][1][RTW89_CHILE][1][72] = 127,
+ [1][1][RTW89_QATAR][1][72] = 127,
+ [1][1][RTW89_QATAR][0][72] = 127,
+ [1][1][RTW89_UK][1][72] = 127,
+ [1][1][RTW89_UK][0][72] = 127,
+ [1][1][RTW89_FCC][1][74] = -28,
+ [1][1][RTW89_FCC][2][74] = 44,
+ [1][1][RTW89_ETSI][1][74] = 127,
+ [1][1][RTW89_ETSI][0][74] = 127,
+ [1][1][RTW89_MKK][1][74] = 127,
+ [1][1][RTW89_MKK][0][74] = 127,
+ [1][1][RTW89_IC][1][74] = -28,
+ [1][1][RTW89_KCC][1][74] = -14,
+ [1][1][RTW89_KCC][0][74] = 127,
+ [1][1][RTW89_ACMA][1][74] = 127,
+ [1][1][RTW89_ACMA][0][74] = 127,
+ [1][1][RTW89_CHILE][1][74] = 127,
+ [1][1][RTW89_QATAR][1][74] = 127,
+ [1][1][RTW89_QATAR][0][74] = 127,
+ [1][1][RTW89_UK][1][74] = 127,
+ [1][1][RTW89_UK][0][74] = 127,
+ [1][1][RTW89_FCC][1][75] = -28,
+ [1][1][RTW89_FCC][2][75] = 44,
+ [1][1][RTW89_ETSI][1][75] = 127,
+ [1][1][RTW89_ETSI][0][75] = 127,
+ [1][1][RTW89_MKK][1][75] = 127,
+ [1][1][RTW89_MKK][0][75] = 127,
+ [1][1][RTW89_IC][1][75] = -28,
+ [1][1][RTW89_KCC][1][75] = -14,
+ [1][1][RTW89_KCC][0][75] = 127,
+ [1][1][RTW89_ACMA][1][75] = 127,
+ [1][1][RTW89_ACMA][0][75] = 127,
+ [1][1][RTW89_CHILE][1][75] = 127,
+ [1][1][RTW89_QATAR][1][75] = 127,
+ [1][1][RTW89_QATAR][0][75] = 127,
+ [1][1][RTW89_UK][1][75] = 127,
+ [1][1][RTW89_UK][0][75] = 127,
+ [1][1][RTW89_FCC][1][77] = -28,
+ [1][1][RTW89_FCC][2][77] = 44,
+ [1][1][RTW89_ETSI][1][77] = 127,
+ [1][1][RTW89_ETSI][0][77] = 127,
+ [1][1][RTW89_MKK][1][77] = 127,
+ [1][1][RTW89_MKK][0][77] = 127,
+ [1][1][RTW89_IC][1][77] = -28,
+ [1][1][RTW89_KCC][1][77] = -14,
+ [1][1][RTW89_KCC][0][77] = 127,
+ [1][1][RTW89_ACMA][1][77] = 127,
+ [1][1][RTW89_ACMA][0][77] = 127,
+ [1][1][RTW89_CHILE][1][77] = 127,
+ [1][1][RTW89_QATAR][1][77] = 127,
+ [1][1][RTW89_QATAR][0][77] = 127,
+ [1][1][RTW89_UK][1][77] = 127,
+ [1][1][RTW89_UK][0][77] = 127,
+ [1][1][RTW89_FCC][1][79] = -28,
+ [1][1][RTW89_FCC][2][79] = 44,
+ [1][1][RTW89_ETSI][1][79] = 127,
+ [1][1][RTW89_ETSI][0][79] = 127,
+ [1][1][RTW89_MKK][1][79] = 127,
+ [1][1][RTW89_MKK][0][79] = 127,
+ [1][1][RTW89_IC][1][79] = -28,
+ [1][1][RTW89_KCC][1][79] = -14,
+ [1][1][RTW89_KCC][0][79] = 127,
+ [1][1][RTW89_ACMA][1][79] = 127,
+ [1][1][RTW89_ACMA][0][79] = 127,
+ [1][1][RTW89_CHILE][1][79] = 127,
+ [1][1][RTW89_QATAR][1][79] = 127,
+ [1][1][RTW89_QATAR][0][79] = 127,
+ [1][1][RTW89_UK][1][79] = 127,
+ [1][1][RTW89_UK][0][79] = 127,
+ [1][1][RTW89_FCC][1][81] = -28,
+ [1][1][RTW89_FCC][2][81] = 44,
+ [1][1][RTW89_ETSI][1][81] = 127,
+ [1][1][RTW89_ETSI][0][81] = 127,
+ [1][1][RTW89_MKK][1][81] = 127,
+ [1][1][RTW89_MKK][0][81] = 127,
+ [1][1][RTW89_IC][1][81] = -28,
+ [1][1][RTW89_KCC][1][81] = -14,
+ [1][1][RTW89_KCC][0][81] = 127,
+ [1][1][RTW89_ACMA][1][81] = 127,
+ [1][1][RTW89_ACMA][0][81] = 127,
+ [1][1][RTW89_CHILE][1][81] = 127,
+ [1][1][RTW89_QATAR][1][81] = 127,
+ [1][1][RTW89_QATAR][0][81] = 127,
+ [1][1][RTW89_UK][1][81] = 127,
+ [1][1][RTW89_UK][0][81] = 127,
+ [1][1][RTW89_FCC][1][83] = -28,
+ [1][1][RTW89_FCC][2][83] = 44,
+ [1][1][RTW89_ETSI][1][83] = 127,
+ [1][1][RTW89_ETSI][0][83] = 127,
+ [1][1][RTW89_MKK][1][83] = 127,
+ [1][1][RTW89_MKK][0][83] = 127,
+ [1][1][RTW89_IC][1][83] = -28,
+ [1][1][RTW89_KCC][1][83] = -14,
+ [1][1][RTW89_KCC][0][83] = 127,
+ [1][1][RTW89_ACMA][1][83] = 127,
+ [1][1][RTW89_ACMA][0][83] = 127,
+ [1][1][RTW89_CHILE][1][83] = 127,
+ [1][1][RTW89_QATAR][1][83] = 127,
+ [1][1][RTW89_QATAR][0][83] = 127,
+ [1][1][RTW89_UK][1][83] = 127,
+ [1][1][RTW89_UK][0][83] = 127,
+ [1][1][RTW89_FCC][1][85] = -28,
+ [1][1][RTW89_FCC][2][85] = 44,
+ [1][1][RTW89_ETSI][1][85] = 127,
+ [1][1][RTW89_ETSI][0][85] = 127,
+ [1][1][RTW89_MKK][1][85] = 127,
+ [1][1][RTW89_MKK][0][85] = 127,
+ [1][1][RTW89_IC][1][85] = -28,
+ [1][1][RTW89_KCC][1][85] = -14,
+ [1][1][RTW89_KCC][0][85] = 127,
+ [1][1][RTW89_ACMA][1][85] = 127,
+ [1][1][RTW89_ACMA][0][85] = 127,
+ [1][1][RTW89_CHILE][1][85] = 127,
+ [1][1][RTW89_QATAR][1][85] = 127,
+ [1][1][RTW89_QATAR][0][85] = 127,
+ [1][1][RTW89_UK][1][85] = 127,
+ [1][1][RTW89_UK][0][85] = 127,
+ [1][1][RTW89_FCC][1][87] = -28,
+ [1][1][RTW89_FCC][2][87] = 127,
+ [1][1][RTW89_ETSI][1][87] = 127,
+ [1][1][RTW89_ETSI][0][87] = 127,
+ [1][1][RTW89_MKK][1][87] = 127,
+ [1][1][RTW89_MKK][0][87] = 127,
+ [1][1][RTW89_IC][1][87] = -28,
+ [1][1][RTW89_KCC][1][87] = -14,
+ [1][1][RTW89_KCC][0][87] = 127,
+ [1][1][RTW89_ACMA][1][87] = 127,
+ [1][1][RTW89_ACMA][0][87] = 127,
+ [1][1][RTW89_CHILE][1][87] = 127,
+ [1][1][RTW89_QATAR][1][87] = 127,
+ [1][1][RTW89_QATAR][0][87] = 127,
+ [1][1][RTW89_UK][1][87] = 127,
+ [1][1][RTW89_UK][0][87] = 127,
+ [1][1][RTW89_FCC][1][89] = -26,
+ [1][1][RTW89_FCC][2][89] = 127,
+ [1][1][RTW89_ETSI][1][89] = 127,
+ [1][1][RTW89_ETSI][0][89] = 127,
+ [1][1][RTW89_MKK][1][89] = 127,
+ [1][1][RTW89_MKK][0][89] = 127,
+ [1][1][RTW89_IC][1][89] = -26,
+ [1][1][RTW89_KCC][1][89] = -14,
+ [1][1][RTW89_KCC][0][89] = 127,
+ [1][1][RTW89_ACMA][1][89] = 127,
+ [1][1][RTW89_ACMA][0][89] = 127,
+ [1][1][RTW89_CHILE][1][89] = 127,
+ [1][1][RTW89_QATAR][1][89] = 127,
+ [1][1][RTW89_QATAR][0][89] = 127,
+ [1][1][RTW89_UK][1][89] = 127,
+ [1][1][RTW89_UK][0][89] = 127,
+ [1][1][RTW89_FCC][1][90] = -26,
+ [1][1][RTW89_FCC][2][90] = 127,
+ [1][1][RTW89_ETSI][1][90] = 127,
+ [1][1][RTW89_ETSI][0][90] = 127,
+ [1][1][RTW89_MKK][1][90] = 127,
+ [1][1][RTW89_MKK][0][90] = 127,
+ [1][1][RTW89_IC][1][90] = -26,
+ [1][1][RTW89_KCC][1][90] = -14,
+ [1][1][RTW89_KCC][0][90] = 127,
+ [1][1][RTW89_ACMA][1][90] = 127,
+ [1][1][RTW89_ACMA][0][90] = 127,
+ [1][1][RTW89_CHILE][1][90] = 127,
+ [1][1][RTW89_QATAR][1][90] = 127,
+ [1][1][RTW89_QATAR][0][90] = 127,
+ [1][1][RTW89_UK][1][90] = 127,
+ [1][1][RTW89_UK][0][90] = 127,
+ [1][1][RTW89_FCC][1][92] = -26,
+ [1][1][RTW89_FCC][2][92] = 127,
+ [1][1][RTW89_ETSI][1][92] = 127,
+ [1][1][RTW89_ETSI][0][92] = 127,
+ [1][1][RTW89_MKK][1][92] = 127,
+ [1][1][RTW89_MKK][0][92] = 127,
+ [1][1][RTW89_IC][1][92] = -26,
+ [1][1][RTW89_KCC][1][92] = -14,
+ [1][1][RTW89_KCC][0][92] = 127,
+ [1][1][RTW89_ACMA][1][92] = 127,
+ [1][1][RTW89_ACMA][0][92] = 127,
+ [1][1][RTW89_CHILE][1][92] = 127,
+ [1][1][RTW89_QATAR][1][92] = 127,
+ [1][1][RTW89_QATAR][0][92] = 127,
+ [1][1][RTW89_UK][1][92] = 127,
+ [1][1][RTW89_UK][0][92] = 127,
+ [1][1][RTW89_FCC][1][94] = -26,
+ [1][1][RTW89_FCC][2][94] = 127,
+ [1][1][RTW89_ETSI][1][94] = 127,
+ [1][1][RTW89_ETSI][0][94] = 127,
+ [1][1][RTW89_MKK][1][94] = 127,
+ [1][1][RTW89_MKK][0][94] = 127,
+ [1][1][RTW89_IC][1][94] = -26,
+ [1][1][RTW89_KCC][1][94] = -14,
+ [1][1][RTW89_KCC][0][94] = 127,
+ [1][1][RTW89_ACMA][1][94] = 127,
+ [1][1][RTW89_ACMA][0][94] = 127,
+ [1][1][RTW89_CHILE][1][94] = 127,
+ [1][1][RTW89_QATAR][1][94] = 127,
+ [1][1][RTW89_QATAR][0][94] = 127,
+ [1][1][RTW89_UK][1][94] = 127,
+ [1][1][RTW89_UK][0][94] = 127,
+ [1][1][RTW89_FCC][1][96] = -26,
+ [1][1][RTW89_FCC][2][96] = 127,
+ [1][1][RTW89_ETSI][1][96] = 127,
+ [1][1][RTW89_ETSI][0][96] = 127,
+ [1][1][RTW89_MKK][1][96] = 127,
+ [1][1][RTW89_MKK][0][96] = 127,
+ [1][1][RTW89_IC][1][96] = -26,
+ [1][1][RTW89_KCC][1][96] = -14,
+ [1][1][RTW89_KCC][0][96] = 127,
+ [1][1][RTW89_ACMA][1][96] = 127,
+ [1][1][RTW89_ACMA][0][96] = 127,
+ [1][1][RTW89_CHILE][1][96] = 127,
+ [1][1][RTW89_QATAR][1][96] = 127,
+ [1][1][RTW89_QATAR][0][96] = 127,
+ [1][1][RTW89_UK][1][96] = 127,
+ [1][1][RTW89_UK][0][96] = 127,
+ [1][1][RTW89_FCC][1][98] = -26,
+ [1][1][RTW89_FCC][2][98] = 127,
+ [1][1][RTW89_ETSI][1][98] = 127,
+ [1][1][RTW89_ETSI][0][98] = 127,
+ [1][1][RTW89_MKK][1][98] = 127,
+ [1][1][RTW89_MKK][0][98] = 127,
+ [1][1][RTW89_IC][1][98] = -26,
+ [1][1][RTW89_KCC][1][98] = -14,
+ [1][1][RTW89_KCC][0][98] = 127,
+ [1][1][RTW89_ACMA][1][98] = 127,
+ [1][1][RTW89_ACMA][0][98] = 127,
+ [1][1][RTW89_CHILE][1][98] = 127,
+ [1][1][RTW89_QATAR][1][98] = 127,
+ [1][1][RTW89_QATAR][0][98] = 127,
+ [1][1][RTW89_UK][1][98] = 127,
+ [1][1][RTW89_UK][0][98] = 127,
+ [1][1][RTW89_FCC][1][100] = -26,
+ [1][1][RTW89_FCC][2][100] = 127,
+ [1][1][RTW89_ETSI][1][100] = 127,
+ [1][1][RTW89_ETSI][0][100] = 127,
+ [1][1][RTW89_MKK][1][100] = 127,
+ [1][1][RTW89_MKK][0][100] = 127,
+ [1][1][RTW89_IC][1][100] = -26,
+ [1][1][RTW89_KCC][1][100] = -14,
+ [1][1][RTW89_KCC][0][100] = 127,
+ [1][1][RTW89_ACMA][1][100] = 127,
+ [1][1][RTW89_ACMA][0][100] = 127,
+ [1][1][RTW89_CHILE][1][100] = 127,
+ [1][1][RTW89_QATAR][1][100] = 127,
+ [1][1][RTW89_QATAR][0][100] = 127,
+ [1][1][RTW89_UK][1][100] = 127,
+ [1][1][RTW89_UK][0][100] = 127,
+ [1][1][RTW89_FCC][1][102] = -26,
+ [1][1][RTW89_FCC][2][102] = 127,
+ [1][1][RTW89_ETSI][1][102] = 127,
+ [1][1][RTW89_ETSI][0][102] = 127,
+ [1][1][RTW89_MKK][1][102] = 127,
+ [1][1][RTW89_MKK][0][102] = 127,
+ [1][1][RTW89_IC][1][102] = -26,
+ [1][1][RTW89_KCC][1][102] = -14,
+ [1][1][RTW89_KCC][0][102] = 127,
+ [1][1][RTW89_ACMA][1][102] = 127,
+ [1][1][RTW89_ACMA][0][102] = 127,
+ [1][1][RTW89_CHILE][1][102] = 127,
+ [1][1][RTW89_QATAR][1][102] = 127,
+ [1][1][RTW89_QATAR][0][102] = 127,
+ [1][1][RTW89_UK][1][102] = 127,
+ [1][1][RTW89_UK][0][102] = 127,
+ [1][1][RTW89_FCC][1][104] = -26,
+ [1][1][RTW89_FCC][2][104] = 127,
+ [1][1][RTW89_ETSI][1][104] = 127,
+ [1][1][RTW89_ETSI][0][104] = 127,
+ [1][1][RTW89_MKK][1][104] = 127,
+ [1][1][RTW89_MKK][0][104] = 127,
+ [1][1][RTW89_IC][1][104] = -26,
+ [1][1][RTW89_KCC][1][104] = -14,
+ [1][1][RTW89_KCC][0][104] = 127,
+ [1][1][RTW89_ACMA][1][104] = 127,
+ [1][1][RTW89_ACMA][0][104] = 127,
+ [1][1][RTW89_CHILE][1][104] = 127,
+ [1][1][RTW89_QATAR][1][104] = 127,
+ [1][1][RTW89_QATAR][0][104] = 127,
+ [1][1][RTW89_UK][1][104] = 127,
+ [1][1][RTW89_UK][0][104] = 127,
+ [1][1][RTW89_FCC][1][105] = -26,
+ [1][1][RTW89_FCC][2][105] = 127,
+ [1][1][RTW89_ETSI][1][105] = 127,
+ [1][1][RTW89_ETSI][0][105] = 127,
+ [1][1][RTW89_MKK][1][105] = 127,
+ [1][1][RTW89_MKK][0][105] = 127,
+ [1][1][RTW89_IC][1][105] = -26,
+ [1][1][RTW89_KCC][1][105] = -14,
+ [1][1][RTW89_KCC][0][105] = 127,
+ [1][1][RTW89_ACMA][1][105] = 127,
+ [1][1][RTW89_ACMA][0][105] = 127,
+ [1][1][RTW89_CHILE][1][105] = 127,
+ [1][1][RTW89_QATAR][1][105] = 127,
+ [1][1][RTW89_QATAR][0][105] = 127,
+ [1][1][RTW89_UK][1][105] = 127,
+ [1][1][RTW89_UK][0][105] = 127,
+ [1][1][RTW89_FCC][1][107] = -22,
+ [1][1][RTW89_FCC][2][107] = 127,
+ [1][1][RTW89_ETSI][1][107] = 127,
+ [1][1][RTW89_ETSI][0][107] = 127,
+ [1][1][RTW89_MKK][1][107] = 127,
+ [1][1][RTW89_MKK][0][107] = 127,
+ [1][1][RTW89_IC][1][107] = -22,
+ [1][1][RTW89_KCC][1][107] = -14,
+ [1][1][RTW89_KCC][0][107] = 127,
+ [1][1][RTW89_ACMA][1][107] = 127,
+ [1][1][RTW89_ACMA][0][107] = 127,
+ [1][1][RTW89_CHILE][1][107] = 127,
+ [1][1][RTW89_QATAR][1][107] = 127,
+ [1][1][RTW89_QATAR][0][107] = 127,
+ [1][1][RTW89_UK][1][107] = 127,
+ [1][1][RTW89_UK][0][107] = 127,
+ [1][1][RTW89_FCC][1][109] = -22,
+ [1][1][RTW89_FCC][2][109] = 127,
+ [1][1][RTW89_ETSI][1][109] = 127,
+ [1][1][RTW89_ETSI][0][109] = 127,
+ [1][1][RTW89_MKK][1][109] = 127,
+ [1][1][RTW89_MKK][0][109] = 127,
+ [1][1][RTW89_IC][1][109] = -22,
+ [1][1][RTW89_KCC][1][109] = 127,
+ [1][1][RTW89_KCC][0][109] = 127,
+ [1][1][RTW89_ACMA][1][109] = 127,
+ [1][1][RTW89_ACMA][0][109] = 127,
+ [1][1][RTW89_CHILE][1][109] = 127,
+ [1][1][RTW89_QATAR][1][109] = 127,
+ [1][1][RTW89_QATAR][0][109] = 127,
+ [1][1][RTW89_UK][1][109] = 127,
+ [1][1][RTW89_UK][0][109] = 127,
+ [1][1][RTW89_FCC][1][111] = 127,
+ [1][1][RTW89_FCC][2][111] = 127,
+ [1][1][RTW89_ETSI][1][111] = 127,
+ [1][1][RTW89_ETSI][0][111] = 127,
+ [1][1][RTW89_MKK][1][111] = 127,
+ [1][1][RTW89_MKK][0][111] = 127,
+ [1][1][RTW89_IC][1][111] = 127,
+ [1][1][RTW89_KCC][1][111] = 127,
+ [1][1][RTW89_KCC][0][111] = 127,
+ [1][1][RTW89_ACMA][1][111] = 127,
+ [1][1][RTW89_ACMA][0][111] = 127,
+ [1][1][RTW89_CHILE][1][111] = 127,
+ [1][1][RTW89_QATAR][1][111] = 127,
+ [1][1][RTW89_QATAR][0][111] = 127,
+ [1][1][RTW89_UK][1][111] = 127,
+ [1][1][RTW89_UK][0][111] = 127,
+ [1][1][RTW89_FCC][1][113] = 127,
+ [1][1][RTW89_FCC][2][113] = 127,
+ [1][1][RTW89_ETSI][1][113] = 127,
+ [1][1][RTW89_ETSI][0][113] = 127,
+ [1][1][RTW89_MKK][1][113] = 127,
+ [1][1][RTW89_MKK][0][113] = 127,
+ [1][1][RTW89_IC][1][113] = 127,
+ [1][1][RTW89_KCC][1][113] = 127,
+ [1][1][RTW89_KCC][0][113] = 127,
+ [1][1][RTW89_ACMA][1][113] = 127,
+ [1][1][RTW89_ACMA][0][113] = 127,
+ [1][1][RTW89_CHILE][1][113] = 127,
+ [1][1][RTW89_QATAR][1][113] = 127,
+ [1][1][RTW89_QATAR][0][113] = 127,
+ [1][1][RTW89_UK][1][113] = 127,
+ [1][1][RTW89_UK][0][113] = 127,
+ [1][1][RTW89_FCC][1][115] = 127,
+ [1][1][RTW89_FCC][2][115] = 127,
+ [1][1][RTW89_ETSI][1][115] = 127,
+ [1][1][RTW89_ETSI][0][115] = 127,
+ [1][1][RTW89_MKK][1][115] = 127,
+ [1][1][RTW89_MKK][0][115] = 127,
+ [1][1][RTW89_IC][1][115] = 127,
+ [1][1][RTW89_KCC][1][115] = 127,
+ [1][1][RTW89_KCC][0][115] = 127,
+ [1][1][RTW89_ACMA][1][115] = 127,
+ [1][1][RTW89_ACMA][0][115] = 127,
+ [1][1][RTW89_CHILE][1][115] = 127,
+ [1][1][RTW89_QATAR][1][115] = 127,
+ [1][1][RTW89_QATAR][0][115] = 127,
+ [1][1][RTW89_UK][1][115] = 127,
+ [1][1][RTW89_UK][0][115] = 127,
+ [1][1][RTW89_FCC][1][117] = 127,
+ [1][1][RTW89_FCC][2][117] = 127,
+ [1][1][RTW89_ETSI][1][117] = 127,
+ [1][1][RTW89_ETSI][0][117] = 127,
+ [1][1][RTW89_MKK][1][117] = 127,
+ [1][1][RTW89_MKK][0][117] = 127,
+ [1][1][RTW89_IC][1][117] = 127,
+ [1][1][RTW89_KCC][1][117] = 127,
+ [1][1][RTW89_KCC][0][117] = 127,
+ [1][1][RTW89_ACMA][1][117] = 127,
+ [1][1][RTW89_ACMA][0][117] = 127,
+ [1][1][RTW89_CHILE][1][117] = 127,
+ [1][1][RTW89_QATAR][1][117] = 127,
+ [1][1][RTW89_QATAR][0][117] = 127,
+ [1][1][RTW89_UK][1][117] = 127,
+ [1][1][RTW89_UK][0][117] = 127,
+ [1][1][RTW89_FCC][1][119] = 127,
+ [1][1][RTW89_FCC][2][119] = 127,
+ [1][1][RTW89_ETSI][1][119] = 127,
+ [1][1][RTW89_ETSI][0][119] = 127,
+ [1][1][RTW89_MKK][1][119] = 127,
+ [1][1][RTW89_MKK][0][119] = 127,
+ [1][1][RTW89_IC][1][119] = 127,
+ [1][1][RTW89_KCC][1][119] = 127,
+ [1][1][RTW89_KCC][0][119] = 127,
+ [1][1][RTW89_ACMA][1][119] = 127,
+ [1][1][RTW89_ACMA][0][119] = 127,
+ [1][1][RTW89_CHILE][1][119] = 127,
+ [1][1][RTW89_QATAR][1][119] = 127,
+ [1][1][RTW89_QATAR][0][119] = 127,
+ [1][1][RTW89_UK][1][119] = 127,
+ [1][1][RTW89_UK][0][119] = 127,
+ [2][0][RTW89_FCC][1][0] = 8,
+ [2][0][RTW89_FCC][2][0] = 60,
+ [2][0][RTW89_ETSI][1][0] = 56,
+ [2][0][RTW89_ETSI][0][0] = 18,
+ [2][0][RTW89_MKK][1][0] = 54,
+ [2][0][RTW89_MKK][0][0] = 14,
+ [2][0][RTW89_IC][1][0] = 8,
+ [2][0][RTW89_KCC][1][0] = -2,
+ [2][0][RTW89_KCC][0][0] = -2,
+ [2][0][RTW89_ACMA][1][0] = 56,
+ [2][0][RTW89_ACMA][0][0] = 18,
+ [2][0][RTW89_CHILE][1][0] = 8,
+ [2][0][RTW89_QATAR][1][0] = 56,
+ [2][0][RTW89_QATAR][0][0] = 18,
+ [2][0][RTW89_UK][1][0] = 56,
+ [2][0][RTW89_UK][0][0] = 18,
+ [2][0][RTW89_FCC][1][2] = 8,
+ [2][0][RTW89_FCC][2][2] = 60,
+ [2][0][RTW89_ETSI][1][2] = 56,
+ [2][0][RTW89_ETSI][0][2] = 18,
+ [2][0][RTW89_MKK][1][2] = 54,
+ [2][0][RTW89_MKK][0][2] = 14,
+ [2][0][RTW89_IC][1][2] = 8,
+ [2][0][RTW89_KCC][1][2] = -2,
+ [2][0][RTW89_KCC][0][2] = -2,
+ [2][0][RTW89_ACMA][1][2] = 56,
+ [2][0][RTW89_ACMA][0][2] = 18,
+ [2][0][RTW89_CHILE][1][2] = 8,
+ [2][0][RTW89_QATAR][1][2] = 56,
+ [2][0][RTW89_QATAR][0][2] = 18,
+ [2][0][RTW89_UK][1][2] = 56,
+ [2][0][RTW89_UK][0][2] = 18,
+ [2][0][RTW89_FCC][1][4] = 8,
+ [2][0][RTW89_FCC][2][4] = 60,
+ [2][0][RTW89_ETSI][1][4] = 56,
+ [2][0][RTW89_ETSI][0][4] = 18,
+ [2][0][RTW89_MKK][1][4] = 54,
+ [2][0][RTW89_MKK][0][4] = 14,
+ [2][0][RTW89_IC][1][4] = 8,
+ [2][0][RTW89_KCC][1][4] = -2,
+ [2][0][RTW89_KCC][0][4] = -2,
+ [2][0][RTW89_ACMA][1][4] = 56,
+ [2][0][RTW89_ACMA][0][4] = 18,
+ [2][0][RTW89_CHILE][1][4] = 8,
+ [2][0][RTW89_QATAR][1][4] = 56,
+ [2][0][RTW89_QATAR][0][4] = 18,
+ [2][0][RTW89_UK][1][4] = 56,
+ [2][0][RTW89_UK][0][4] = 18,
+ [2][0][RTW89_FCC][1][6] = 8,
+ [2][0][RTW89_FCC][2][6] = 60,
+ [2][0][RTW89_ETSI][1][6] = 56,
+ [2][0][RTW89_ETSI][0][6] = 18,
+ [2][0][RTW89_MKK][1][6] = 54,
+ [2][0][RTW89_MKK][0][6] = 14,
+ [2][0][RTW89_IC][1][6] = 8,
+ [2][0][RTW89_KCC][1][6] = -2,
+ [2][0][RTW89_KCC][0][6] = -2,
+ [2][0][RTW89_ACMA][1][6] = 56,
+ [2][0][RTW89_ACMA][0][6] = 18,
+ [2][0][RTW89_CHILE][1][6] = 8,
+ [2][0][RTW89_QATAR][1][6] = 56,
+ [2][0][RTW89_QATAR][0][6] = 18,
+ [2][0][RTW89_UK][1][6] = 56,
+ [2][0][RTW89_UK][0][6] = 18,
+ [2][0][RTW89_FCC][1][8] = 8,
+ [2][0][RTW89_FCC][2][8] = 60,
+ [2][0][RTW89_ETSI][1][8] = 56,
+ [2][0][RTW89_ETSI][0][8] = 18,
+ [2][0][RTW89_MKK][1][8] = 54,
+ [2][0][RTW89_MKK][0][8] = 14,
+ [2][0][RTW89_IC][1][8] = 8,
+ [2][0][RTW89_KCC][1][8] = -2,
+ [2][0][RTW89_KCC][0][8] = -2,
+ [2][0][RTW89_ACMA][1][8] = 56,
+ [2][0][RTW89_ACMA][0][8] = 18,
+ [2][0][RTW89_CHILE][1][8] = 8,
+ [2][0][RTW89_QATAR][1][8] = 56,
+ [2][0][RTW89_QATAR][0][8] = 18,
+ [2][0][RTW89_UK][1][8] = 56,
+ [2][0][RTW89_UK][0][8] = 18,
+ [2][0][RTW89_FCC][1][10] = 8,
+ [2][0][RTW89_FCC][2][10] = 60,
+ [2][0][RTW89_ETSI][1][10] = 56,
+ [2][0][RTW89_ETSI][0][10] = 18,
+ [2][0][RTW89_MKK][1][10] = 54,
+ [2][0][RTW89_MKK][0][10] = 14,
+ [2][0][RTW89_IC][1][10] = 8,
+ [2][0][RTW89_KCC][1][10] = -2,
+ [2][0][RTW89_KCC][0][10] = -2,
+ [2][0][RTW89_ACMA][1][10] = 56,
+ [2][0][RTW89_ACMA][0][10] = 18,
+ [2][0][RTW89_CHILE][1][10] = 8,
+ [2][0][RTW89_QATAR][1][10] = 56,
+ [2][0][RTW89_QATAR][0][10] = 18,
+ [2][0][RTW89_UK][1][10] = 56,
+ [2][0][RTW89_UK][0][10] = 18,
+ [2][0][RTW89_FCC][1][12] = 8,
+ [2][0][RTW89_FCC][2][12] = 60,
+ [2][0][RTW89_ETSI][1][12] = 56,
+ [2][0][RTW89_ETSI][0][12] = 18,
+ [2][0][RTW89_MKK][1][12] = 54,
+ [2][0][RTW89_MKK][0][12] = 14,
+ [2][0][RTW89_IC][1][12] = 8,
+ [2][0][RTW89_KCC][1][12] = -2,
+ [2][0][RTW89_KCC][0][12] = -2,
+ [2][0][RTW89_ACMA][1][12] = 56,
+ [2][0][RTW89_ACMA][0][12] = 18,
+ [2][0][RTW89_CHILE][1][12] = 8,
+ [2][0][RTW89_QATAR][1][12] = 56,
+ [2][0][RTW89_QATAR][0][12] = 18,
+ [2][0][RTW89_UK][1][12] = 56,
+ [2][0][RTW89_UK][0][12] = 18,
+ [2][0][RTW89_FCC][1][14] = 8,
+ [2][0][RTW89_FCC][2][14] = 60,
+ [2][0][RTW89_ETSI][1][14] = 56,
+ [2][0][RTW89_ETSI][0][14] = 18,
+ [2][0][RTW89_MKK][1][14] = 54,
+ [2][0][RTW89_MKK][0][14] = 14,
+ [2][0][RTW89_IC][1][14] = 8,
+ [2][0][RTW89_KCC][1][14] = -2,
+ [2][0][RTW89_KCC][0][14] = -2,
+ [2][0][RTW89_ACMA][1][14] = 56,
+ [2][0][RTW89_ACMA][0][14] = 18,
+ [2][0][RTW89_CHILE][1][14] = 8,
+ [2][0][RTW89_QATAR][1][14] = 56,
+ [2][0][RTW89_QATAR][0][14] = 18,
+ [2][0][RTW89_UK][1][14] = 56,
+ [2][0][RTW89_UK][0][14] = 18,
+ [2][0][RTW89_FCC][1][15] = 8,
+ [2][0][RTW89_FCC][2][15] = 60,
+ [2][0][RTW89_ETSI][1][15] = 56,
+ [2][0][RTW89_ETSI][0][15] = 18,
+ [2][0][RTW89_MKK][1][15] = 54,
+ [2][0][RTW89_MKK][0][15] = 14,
+ [2][0][RTW89_IC][1][15] = 8,
+ [2][0][RTW89_KCC][1][15] = -2,
+ [2][0][RTW89_KCC][0][15] = -2,
+ [2][0][RTW89_ACMA][1][15] = 56,
+ [2][0][RTW89_ACMA][0][15] = 18,
+ [2][0][RTW89_CHILE][1][15] = 8,
+ [2][0][RTW89_QATAR][1][15] = 56,
+ [2][0][RTW89_QATAR][0][15] = 18,
+ [2][0][RTW89_UK][1][15] = 56,
+ [2][0][RTW89_UK][0][15] = 18,
+ [2][0][RTW89_FCC][1][17] = 8,
+ [2][0][RTW89_FCC][2][17] = 60,
+ [2][0][RTW89_ETSI][1][17] = 56,
+ [2][0][RTW89_ETSI][0][17] = 18,
+ [2][0][RTW89_MKK][1][17] = 54,
+ [2][0][RTW89_MKK][0][17] = 14,
+ [2][0][RTW89_IC][1][17] = 8,
+ [2][0][RTW89_KCC][1][17] = -2,
+ [2][0][RTW89_KCC][0][17] = -2,
+ [2][0][RTW89_ACMA][1][17] = 56,
+ [2][0][RTW89_ACMA][0][17] = 18,
+ [2][0][RTW89_CHILE][1][17] = 8,
+ [2][0][RTW89_QATAR][1][17] = 56,
+ [2][0][RTW89_QATAR][0][17] = 18,
+ [2][0][RTW89_UK][1][17] = 56,
+ [2][0][RTW89_UK][0][17] = 18,
+ [2][0][RTW89_FCC][1][19] = 8,
+ [2][0][RTW89_FCC][2][19] = 60,
+ [2][0][RTW89_ETSI][1][19] = 56,
+ [2][0][RTW89_ETSI][0][19] = 18,
+ [2][0][RTW89_MKK][1][19] = 54,
+ [2][0][RTW89_MKK][0][19] = 14,
+ [2][0][RTW89_IC][1][19] = 8,
+ [2][0][RTW89_KCC][1][19] = -2,
+ [2][0][RTW89_KCC][0][19] = -2,
+ [2][0][RTW89_ACMA][1][19] = 56,
+ [2][0][RTW89_ACMA][0][19] = 18,
+ [2][0][RTW89_CHILE][1][19] = 8,
+ [2][0][RTW89_QATAR][1][19] = 56,
+ [2][0][RTW89_QATAR][0][19] = 18,
+ [2][0][RTW89_UK][1][19] = 56,
+ [2][0][RTW89_UK][0][19] = 18,
+ [2][0][RTW89_FCC][1][21] = 8,
+ [2][0][RTW89_FCC][2][21] = 60,
+ [2][0][RTW89_ETSI][1][21] = 56,
+ [2][0][RTW89_ETSI][0][21] = 18,
+ [2][0][RTW89_MKK][1][21] = 54,
+ [2][0][RTW89_MKK][0][21] = 14,
+ [2][0][RTW89_IC][1][21] = 8,
+ [2][0][RTW89_KCC][1][21] = -2,
+ [2][0][RTW89_KCC][0][21] = -2,
+ [2][0][RTW89_ACMA][1][21] = 56,
+ [2][0][RTW89_ACMA][0][21] = 18,
+ [2][0][RTW89_CHILE][1][21] = 8,
+ [2][0][RTW89_QATAR][1][21] = 56,
+ [2][0][RTW89_QATAR][0][21] = 18,
+ [2][0][RTW89_UK][1][21] = 56,
+ [2][0][RTW89_UK][0][21] = 18,
+ [2][0][RTW89_FCC][1][23] = 8,
+ [2][0][RTW89_FCC][2][23] = 78,
+ [2][0][RTW89_ETSI][1][23] = 56,
+ [2][0][RTW89_ETSI][0][23] = 18,
+ [2][0][RTW89_MKK][1][23] = 56,
+ [2][0][RTW89_MKK][0][23] = 14,
+ [2][0][RTW89_IC][1][23] = 8,
+ [2][0][RTW89_KCC][1][23] = -2,
+ [2][0][RTW89_KCC][0][23] = -2,
+ [2][0][RTW89_ACMA][1][23] = 56,
+ [2][0][RTW89_ACMA][0][23] = 18,
+ [2][0][RTW89_CHILE][1][23] = 8,
+ [2][0][RTW89_QATAR][1][23] = 56,
+ [2][0][RTW89_QATAR][0][23] = 18,
+ [2][0][RTW89_UK][1][23] = 56,
+ [2][0][RTW89_UK][0][23] = 18,
+ [2][0][RTW89_FCC][1][25] = 8,
+ [2][0][RTW89_FCC][2][25] = 78,
+ [2][0][RTW89_ETSI][1][25] = 56,
+ [2][0][RTW89_ETSI][0][25] = 18,
+ [2][0][RTW89_MKK][1][25] = 56,
+ [2][0][RTW89_MKK][0][25] = 14,
+ [2][0][RTW89_IC][1][25] = 8,
+ [2][0][RTW89_KCC][1][25] = -2,
+ [2][0][RTW89_KCC][0][25] = -2,
+ [2][0][RTW89_ACMA][1][25] = 56,
+ [2][0][RTW89_ACMA][0][25] = 18,
+ [2][0][RTW89_CHILE][1][25] = 8,
+ [2][0][RTW89_QATAR][1][25] = 56,
+ [2][0][RTW89_QATAR][0][25] = 18,
+ [2][0][RTW89_UK][1][25] = 56,
+ [2][0][RTW89_UK][0][25] = 18,
+ [2][0][RTW89_FCC][1][27] = 8,
+ [2][0][RTW89_FCC][2][27] = 78,
+ [2][0][RTW89_ETSI][1][27] = 56,
+ [2][0][RTW89_ETSI][0][27] = 18,
+ [2][0][RTW89_MKK][1][27] = 56,
+ [2][0][RTW89_MKK][0][27] = 14,
+ [2][0][RTW89_IC][1][27] = 8,
+ [2][0][RTW89_KCC][1][27] = -2,
+ [2][0][RTW89_KCC][0][27] = -2,
+ [2][0][RTW89_ACMA][1][27] = 56,
+ [2][0][RTW89_ACMA][0][27] = 18,
+ [2][0][RTW89_CHILE][1][27] = 8,
+ [2][0][RTW89_QATAR][1][27] = 56,
+ [2][0][RTW89_QATAR][0][27] = 18,
+ [2][0][RTW89_UK][1][27] = 56,
+ [2][0][RTW89_UK][0][27] = 18,
+ [2][0][RTW89_FCC][1][29] = 8,
+ [2][0][RTW89_FCC][2][29] = 78,
+ [2][0][RTW89_ETSI][1][29] = 56,
+ [2][0][RTW89_ETSI][0][29] = 18,
+ [2][0][RTW89_MKK][1][29] = 56,
+ [2][0][RTW89_MKK][0][29] = 14,
+ [2][0][RTW89_IC][1][29] = 8,
+ [2][0][RTW89_KCC][1][29] = -2,
+ [2][0][RTW89_KCC][0][29] = -2,
+ [2][0][RTW89_ACMA][1][29] = 56,
+ [2][0][RTW89_ACMA][0][29] = 18,
+ [2][0][RTW89_CHILE][1][29] = 8,
+ [2][0][RTW89_QATAR][1][29] = 56,
+ [2][0][RTW89_QATAR][0][29] = 18,
+ [2][0][RTW89_UK][1][29] = 56,
+ [2][0][RTW89_UK][0][29] = 18,
+ [2][0][RTW89_FCC][1][30] = 8,
+ [2][0][RTW89_FCC][2][30] = 78,
+ [2][0][RTW89_ETSI][1][30] = 56,
+ [2][0][RTW89_ETSI][0][30] = 18,
+ [2][0][RTW89_MKK][1][30] = 56,
+ [2][0][RTW89_MKK][0][30] = 14,
+ [2][0][RTW89_IC][1][30] = 8,
+ [2][0][RTW89_KCC][1][30] = -2,
+ [2][0][RTW89_KCC][0][30] = -2,
+ [2][0][RTW89_ACMA][1][30] = 56,
+ [2][0][RTW89_ACMA][0][30] = 18,
+ [2][0][RTW89_CHILE][1][30] = 8,
+ [2][0][RTW89_QATAR][1][30] = 56,
+ [2][0][RTW89_QATAR][0][30] = 18,
+ [2][0][RTW89_UK][1][30] = 56,
+ [2][0][RTW89_UK][0][30] = 18,
+ [2][0][RTW89_FCC][1][32] = 8,
+ [2][0][RTW89_FCC][2][32] = 78,
+ [2][0][RTW89_ETSI][1][32] = 56,
+ [2][0][RTW89_ETSI][0][32] = 18,
+ [2][0][RTW89_MKK][1][32] = 56,
+ [2][0][RTW89_MKK][0][32] = 14,
+ [2][0][RTW89_IC][1][32] = 8,
+ [2][0][RTW89_KCC][1][32] = -2,
+ [2][0][RTW89_KCC][0][32] = -2,
+ [2][0][RTW89_ACMA][1][32] = 56,
+ [2][0][RTW89_ACMA][0][32] = 18,
+ [2][0][RTW89_CHILE][1][32] = 8,
+ [2][0][RTW89_QATAR][1][32] = 56,
+ [2][0][RTW89_QATAR][0][32] = 18,
+ [2][0][RTW89_UK][1][32] = 56,
+ [2][0][RTW89_UK][0][32] = 18,
+ [2][0][RTW89_FCC][1][34] = 8,
+ [2][0][RTW89_FCC][2][34] = 78,
+ [2][0][RTW89_ETSI][1][34] = 56,
+ [2][0][RTW89_ETSI][0][34] = 18,
+ [2][0][RTW89_MKK][1][34] = 56,
+ [2][0][RTW89_MKK][0][34] = 14,
+ [2][0][RTW89_IC][1][34] = 8,
+ [2][0][RTW89_KCC][1][34] = -2,
+ [2][0][RTW89_KCC][0][34] = -2,
+ [2][0][RTW89_ACMA][1][34] = 56,
+ [2][0][RTW89_ACMA][0][34] = 18,
+ [2][0][RTW89_CHILE][1][34] = 8,
+ [2][0][RTW89_QATAR][1][34] = 56,
+ [2][0][RTW89_QATAR][0][34] = 18,
+ [2][0][RTW89_UK][1][34] = 56,
+ [2][0][RTW89_UK][0][34] = 18,
+ [2][0][RTW89_FCC][1][36] = 8,
+ [2][0][RTW89_FCC][2][36] = 78,
+ [2][0][RTW89_ETSI][1][36] = 56,
+ [2][0][RTW89_ETSI][0][36] = 18,
+ [2][0][RTW89_MKK][1][36] = 56,
+ [2][0][RTW89_MKK][0][36] = 14,
+ [2][0][RTW89_IC][1][36] = 8,
+ [2][0][RTW89_KCC][1][36] = -2,
+ [2][0][RTW89_KCC][0][36] = -2,
+ [2][0][RTW89_ACMA][1][36] = 56,
+ [2][0][RTW89_ACMA][0][36] = 18,
+ [2][0][RTW89_CHILE][1][36] = 8,
+ [2][0][RTW89_QATAR][1][36] = 56,
+ [2][0][RTW89_QATAR][0][36] = 18,
+ [2][0][RTW89_UK][1][36] = 56,
+ [2][0][RTW89_UK][0][36] = 18,
+ [2][0][RTW89_FCC][1][38] = 8,
+ [2][0][RTW89_FCC][2][38] = 78,
+ [2][0][RTW89_ETSI][1][38] = 56,
+ [2][0][RTW89_ETSI][0][38] = 18,
+ [2][0][RTW89_MKK][1][38] = 56,
+ [2][0][RTW89_MKK][0][38] = 14,
+ [2][0][RTW89_IC][1][38] = 8,
+ [2][0][RTW89_KCC][1][38] = -2,
+ [2][0][RTW89_KCC][0][38] = -2,
+ [2][0][RTW89_ACMA][1][38] = 56,
+ [2][0][RTW89_ACMA][0][38] = 18,
+ [2][0][RTW89_CHILE][1][38] = 8,
+ [2][0][RTW89_QATAR][1][38] = 56,
+ [2][0][RTW89_QATAR][0][38] = 18,
+ [2][0][RTW89_UK][1][38] = 56,
+ [2][0][RTW89_UK][0][38] = 18,
+ [2][0][RTW89_FCC][1][40] = 8,
+ [2][0][RTW89_FCC][2][40] = 78,
+ [2][0][RTW89_ETSI][1][40] = 56,
+ [2][0][RTW89_ETSI][0][40] = 18,
+ [2][0][RTW89_MKK][1][40] = 56,
+ [2][0][RTW89_MKK][0][40] = 14,
+ [2][0][RTW89_IC][1][40] = 8,
+ [2][0][RTW89_KCC][1][40] = -2,
+ [2][0][RTW89_KCC][0][40] = -2,
+ [2][0][RTW89_ACMA][1][40] = 56,
+ [2][0][RTW89_ACMA][0][40] = 18,
+ [2][0][RTW89_CHILE][1][40] = 8,
+ [2][0][RTW89_QATAR][1][40] = 56,
+ [2][0][RTW89_QATAR][0][40] = 18,
+ [2][0][RTW89_UK][1][40] = 56,
+ [2][0][RTW89_UK][0][40] = 18,
+ [2][0][RTW89_FCC][1][42] = 8,
+ [2][0][RTW89_FCC][2][42] = 78,
+ [2][0][RTW89_ETSI][1][42] = 56,
+ [2][0][RTW89_ETSI][0][42] = 18,
+ [2][0][RTW89_MKK][1][42] = 56,
+ [2][0][RTW89_MKK][0][42] = 14,
+ [2][0][RTW89_IC][1][42] = 8,
+ [2][0][RTW89_KCC][1][42] = -2,
+ [2][0][RTW89_KCC][0][42] = -2,
+ [2][0][RTW89_ACMA][1][42] = 56,
+ [2][0][RTW89_ACMA][0][42] = 18,
+ [2][0][RTW89_CHILE][1][42] = 8,
+ [2][0][RTW89_QATAR][1][42] = 56,
+ [2][0][RTW89_QATAR][0][42] = 18,
+ [2][0][RTW89_UK][1][42] = 56,
+ [2][0][RTW89_UK][0][42] = 18,
+ [2][0][RTW89_FCC][1][44] = 8,
+ [2][0][RTW89_FCC][2][44] = 78,
+ [2][0][RTW89_ETSI][1][44] = 56,
+ [2][0][RTW89_ETSI][0][44] = 18,
+ [2][0][RTW89_MKK][1][44] = 32,
+ [2][0][RTW89_MKK][0][44] = 14,
+ [2][0][RTW89_IC][1][44] = 8,
+ [2][0][RTW89_KCC][1][44] = -2,
+ [2][0][RTW89_KCC][0][44] = -2,
+ [2][0][RTW89_ACMA][1][44] = 56,
+ [2][0][RTW89_ACMA][0][44] = 18,
+ [2][0][RTW89_CHILE][1][44] = 8,
+ [2][0][RTW89_QATAR][1][44] = 56,
+ [2][0][RTW89_QATAR][0][44] = 18,
+ [2][0][RTW89_UK][1][44] = 56,
+ [2][0][RTW89_UK][0][44] = 18,
+ [2][0][RTW89_FCC][1][45] = 8,
+ [2][0][RTW89_FCC][2][45] = 127,
+ [2][0][RTW89_ETSI][1][45] = 127,
+ [2][0][RTW89_ETSI][0][45] = 127,
+ [2][0][RTW89_MKK][1][45] = 127,
+ [2][0][RTW89_MKK][0][45] = 127,
+ [2][0][RTW89_IC][1][45] = 8,
+ [2][0][RTW89_KCC][1][45] = -2,
+ [2][0][RTW89_KCC][0][45] = 127,
+ [2][0][RTW89_ACMA][1][45] = 127,
+ [2][0][RTW89_ACMA][0][45] = 127,
+ [2][0][RTW89_CHILE][1][45] = 127,
+ [2][0][RTW89_QATAR][1][45] = 127,
+ [2][0][RTW89_QATAR][0][45] = 127,
+ [2][0][RTW89_UK][1][45] = 127,
+ [2][0][RTW89_UK][0][45] = 127,
+ [2][0][RTW89_FCC][1][47] = 8,
+ [2][0][RTW89_FCC][2][47] = 127,
+ [2][0][RTW89_ETSI][1][47] = 127,
+ [2][0][RTW89_ETSI][0][47] = 127,
+ [2][0][RTW89_MKK][1][47] = 127,
+ [2][0][RTW89_MKK][0][47] = 127,
+ [2][0][RTW89_IC][1][47] = 8,
+ [2][0][RTW89_KCC][1][47] = -2,
+ [2][0][RTW89_KCC][0][47] = 127,
+ [2][0][RTW89_ACMA][1][47] = 127,
+ [2][0][RTW89_ACMA][0][47] = 127,
+ [2][0][RTW89_CHILE][1][47] = 127,
+ [2][0][RTW89_QATAR][1][47] = 127,
+ [2][0][RTW89_QATAR][0][47] = 127,
+ [2][0][RTW89_UK][1][47] = 127,
+ [2][0][RTW89_UK][0][47] = 127,
+ [2][0][RTW89_FCC][1][49] = 8,
+ [2][0][RTW89_FCC][2][49] = 127,
+ [2][0][RTW89_ETSI][1][49] = 127,
+ [2][0][RTW89_ETSI][0][49] = 127,
+ [2][0][RTW89_MKK][1][49] = 127,
+ [2][0][RTW89_MKK][0][49] = 127,
+ [2][0][RTW89_IC][1][49] = 8,
+ [2][0][RTW89_KCC][1][49] = -2,
+ [2][0][RTW89_KCC][0][49] = 127,
+ [2][0][RTW89_ACMA][1][49] = 127,
+ [2][0][RTW89_ACMA][0][49] = 127,
+ [2][0][RTW89_CHILE][1][49] = 127,
+ [2][0][RTW89_QATAR][1][49] = 127,
+ [2][0][RTW89_QATAR][0][49] = 127,
+ [2][0][RTW89_UK][1][49] = 127,
+ [2][0][RTW89_UK][0][49] = 127,
+ [2][0][RTW89_FCC][1][51] = 8,
+ [2][0][RTW89_FCC][2][51] = 127,
+ [2][0][RTW89_ETSI][1][51] = 127,
+ [2][0][RTW89_ETSI][0][51] = 127,
+ [2][0][RTW89_MKK][1][51] = 127,
+ [2][0][RTW89_MKK][0][51] = 127,
+ [2][0][RTW89_IC][1][51] = 8,
+ [2][0][RTW89_KCC][1][51] = -2,
+ [2][0][RTW89_KCC][0][51] = 127,
+ [2][0][RTW89_ACMA][1][51] = 127,
+ [2][0][RTW89_ACMA][0][51] = 127,
+ [2][0][RTW89_CHILE][1][51] = 127,
+ [2][0][RTW89_QATAR][1][51] = 127,
+ [2][0][RTW89_QATAR][0][51] = 127,
+ [2][0][RTW89_UK][1][51] = 127,
+ [2][0][RTW89_UK][0][51] = 127,
+ [2][0][RTW89_FCC][1][53] = 8,
+ [2][0][RTW89_FCC][2][53] = 127,
+ [2][0][RTW89_ETSI][1][53] = 127,
+ [2][0][RTW89_ETSI][0][53] = 127,
+ [2][0][RTW89_MKK][1][53] = 127,
+ [2][0][RTW89_MKK][0][53] = 127,
+ [2][0][RTW89_IC][1][53] = 8,
+ [2][0][RTW89_KCC][1][53] = -2,
+ [2][0][RTW89_KCC][0][53] = 127,
+ [2][0][RTW89_ACMA][1][53] = 127,
+ [2][0][RTW89_ACMA][0][53] = 127,
+ [2][0][RTW89_CHILE][1][53] = 127,
+ [2][0][RTW89_QATAR][1][53] = 127,
+ [2][0][RTW89_QATAR][0][53] = 127,
+ [2][0][RTW89_UK][1][53] = 127,
+ [2][0][RTW89_UK][0][53] = 127,
+ [2][0][RTW89_FCC][1][55] = 8,
+ [2][0][RTW89_FCC][2][55] = 78,
+ [2][0][RTW89_ETSI][1][55] = 127,
+ [2][0][RTW89_ETSI][0][55] = 127,
+ [2][0][RTW89_MKK][1][55] = 127,
+ [2][0][RTW89_MKK][0][55] = 127,
+ [2][0][RTW89_IC][1][55] = 8,
+ [2][0][RTW89_KCC][1][55] = -2,
+ [2][0][RTW89_KCC][0][55] = 127,
+ [2][0][RTW89_ACMA][1][55] = 127,
+ [2][0][RTW89_ACMA][0][55] = 127,
+ [2][0][RTW89_CHILE][1][55] = 127,
+ [2][0][RTW89_QATAR][1][55] = 127,
+ [2][0][RTW89_QATAR][0][55] = 127,
+ [2][0][RTW89_UK][1][55] = 127,
+ [2][0][RTW89_UK][0][55] = 127,
+ [2][0][RTW89_FCC][1][57] = 8,
+ [2][0][RTW89_FCC][2][57] = 78,
+ [2][0][RTW89_ETSI][1][57] = 127,
+ [2][0][RTW89_ETSI][0][57] = 127,
+ [2][0][RTW89_MKK][1][57] = 127,
+ [2][0][RTW89_MKK][0][57] = 127,
+ [2][0][RTW89_IC][1][57] = 8,
+ [2][0][RTW89_KCC][1][57] = -2,
+ [2][0][RTW89_KCC][0][57] = 127,
+ [2][0][RTW89_ACMA][1][57] = 127,
+ [2][0][RTW89_ACMA][0][57] = 127,
+ [2][0][RTW89_CHILE][1][57] = 127,
+ [2][0][RTW89_QATAR][1][57] = 127,
+ [2][0][RTW89_QATAR][0][57] = 127,
+ [2][0][RTW89_UK][1][57] = 127,
+ [2][0][RTW89_UK][0][57] = 127,
+ [2][0][RTW89_FCC][1][59] = 8,
+ [2][0][RTW89_FCC][2][59] = 78,
+ [2][0][RTW89_ETSI][1][59] = 127,
+ [2][0][RTW89_ETSI][0][59] = 127,
+ [2][0][RTW89_MKK][1][59] = 127,
+ [2][0][RTW89_MKK][0][59] = 127,
+ [2][0][RTW89_IC][1][59] = 8,
+ [2][0][RTW89_KCC][1][59] = -2,
+ [2][0][RTW89_KCC][0][59] = 127,
+ [2][0][RTW89_ACMA][1][59] = 127,
+ [2][0][RTW89_ACMA][0][59] = 127,
+ [2][0][RTW89_CHILE][1][59] = 127,
+ [2][0][RTW89_QATAR][1][59] = 127,
+ [2][0][RTW89_QATAR][0][59] = 127,
+ [2][0][RTW89_UK][1][59] = 127,
+ [2][0][RTW89_UK][0][59] = 127,
+ [2][0][RTW89_FCC][1][60] = 8,
+ [2][0][RTW89_FCC][2][60] = 78,
+ [2][0][RTW89_ETSI][1][60] = 127,
+ [2][0][RTW89_ETSI][0][60] = 127,
+ [2][0][RTW89_MKK][1][60] = 127,
+ [2][0][RTW89_MKK][0][60] = 127,
+ [2][0][RTW89_IC][1][60] = 8,
+ [2][0][RTW89_KCC][1][60] = -2,
+ [2][0][RTW89_KCC][0][60] = 127,
+ [2][0][RTW89_ACMA][1][60] = 127,
+ [2][0][RTW89_ACMA][0][60] = 127,
+ [2][0][RTW89_CHILE][1][60] = 127,
+ [2][0][RTW89_QATAR][1][60] = 127,
+ [2][0][RTW89_QATAR][0][60] = 127,
+ [2][0][RTW89_UK][1][60] = 127,
+ [2][0][RTW89_UK][0][60] = 127,
+ [2][0][RTW89_FCC][1][62] = 8,
+ [2][0][RTW89_FCC][2][62] = 78,
+ [2][0][RTW89_ETSI][1][62] = 127,
+ [2][0][RTW89_ETSI][0][62] = 127,
+ [2][0][RTW89_MKK][1][62] = 127,
+ [2][0][RTW89_MKK][0][62] = 127,
+ [2][0][RTW89_IC][1][62] = 8,
+ [2][0][RTW89_KCC][1][62] = -2,
+ [2][0][RTW89_KCC][0][62] = 127,
+ [2][0][RTW89_ACMA][1][62] = 127,
+ [2][0][RTW89_ACMA][0][62] = 127,
+ [2][0][RTW89_CHILE][1][62] = 127,
+ [2][0][RTW89_QATAR][1][62] = 127,
+ [2][0][RTW89_QATAR][0][62] = 127,
+ [2][0][RTW89_UK][1][62] = 127,
+ [2][0][RTW89_UK][0][62] = 127,
+ [2][0][RTW89_FCC][1][64] = 8,
+ [2][0][RTW89_FCC][2][64] = 78,
+ [2][0][RTW89_ETSI][1][64] = 127,
+ [2][0][RTW89_ETSI][0][64] = 127,
+ [2][0][RTW89_MKK][1][64] = 127,
+ [2][0][RTW89_MKK][0][64] = 127,
+ [2][0][RTW89_IC][1][64] = 8,
+ [2][0][RTW89_KCC][1][64] = -2,
+ [2][0][RTW89_KCC][0][64] = 127,
+ [2][0][RTW89_ACMA][1][64] = 127,
+ [2][0][RTW89_ACMA][0][64] = 127,
+ [2][0][RTW89_CHILE][1][64] = 127,
+ [2][0][RTW89_QATAR][1][64] = 127,
+ [2][0][RTW89_QATAR][0][64] = 127,
+ [2][0][RTW89_UK][1][64] = 127,
+ [2][0][RTW89_UK][0][64] = 127,
+ [2][0][RTW89_FCC][1][66] = 8,
+ [2][0][RTW89_FCC][2][66] = 78,
+ [2][0][RTW89_ETSI][1][66] = 127,
+ [2][0][RTW89_ETSI][0][66] = 127,
+ [2][0][RTW89_MKK][1][66] = 127,
+ [2][0][RTW89_MKK][0][66] = 127,
+ [2][0][RTW89_IC][1][66] = 8,
+ [2][0][RTW89_KCC][1][66] = -2,
+ [2][0][RTW89_KCC][0][66] = 127,
+ [2][0][RTW89_ACMA][1][66] = 127,
+ [2][0][RTW89_ACMA][0][66] = 127,
+ [2][0][RTW89_CHILE][1][66] = 127,
+ [2][0][RTW89_QATAR][1][66] = 127,
+ [2][0][RTW89_QATAR][0][66] = 127,
+ [2][0][RTW89_UK][1][66] = 127,
+ [2][0][RTW89_UK][0][66] = 127,
+ [2][0][RTW89_FCC][1][68] = 8,
+ [2][0][RTW89_FCC][2][68] = 78,
+ [2][0][RTW89_ETSI][1][68] = 127,
+ [2][0][RTW89_ETSI][0][68] = 127,
+ [2][0][RTW89_MKK][1][68] = 127,
+ [2][0][RTW89_MKK][0][68] = 127,
+ [2][0][RTW89_IC][1][68] = 8,
+ [2][0][RTW89_KCC][1][68] = -2,
+ [2][0][RTW89_KCC][0][68] = 127,
+ [2][0][RTW89_ACMA][1][68] = 127,
+ [2][0][RTW89_ACMA][0][68] = 127,
+ [2][0][RTW89_CHILE][1][68] = 127,
+ [2][0][RTW89_QATAR][1][68] = 127,
+ [2][0][RTW89_QATAR][0][68] = 127,
+ [2][0][RTW89_UK][1][68] = 127,
+ [2][0][RTW89_UK][0][68] = 127,
+ [2][0][RTW89_FCC][1][70] = 8,
+ [2][0][RTW89_FCC][2][70] = 78,
+ [2][0][RTW89_ETSI][1][70] = 127,
+ [2][0][RTW89_ETSI][0][70] = 127,
+ [2][0][RTW89_MKK][1][70] = 127,
+ [2][0][RTW89_MKK][0][70] = 127,
+ [2][0][RTW89_IC][1][70] = 8,
+ [2][0][RTW89_KCC][1][70] = -2,
+ [2][0][RTW89_KCC][0][70] = 127,
+ [2][0][RTW89_ACMA][1][70] = 127,
+ [2][0][RTW89_ACMA][0][70] = 127,
+ [2][0][RTW89_CHILE][1][70] = 127,
+ [2][0][RTW89_QATAR][1][70] = 127,
+ [2][0][RTW89_QATAR][0][70] = 127,
+ [2][0][RTW89_UK][1][70] = 127,
+ [2][0][RTW89_UK][0][70] = 127,
+ [2][0][RTW89_FCC][1][72] = 8,
+ [2][0][RTW89_FCC][2][72] = 78,
+ [2][0][RTW89_ETSI][1][72] = 127,
+ [2][0][RTW89_ETSI][0][72] = 127,
+ [2][0][RTW89_MKK][1][72] = 127,
+ [2][0][RTW89_MKK][0][72] = 127,
+ [2][0][RTW89_IC][1][72] = 8,
+ [2][0][RTW89_KCC][1][72] = -2,
+ [2][0][RTW89_KCC][0][72] = 127,
+ [2][0][RTW89_ACMA][1][72] = 127,
+ [2][0][RTW89_ACMA][0][72] = 127,
+ [2][0][RTW89_CHILE][1][72] = 127,
+ [2][0][RTW89_QATAR][1][72] = 127,
+ [2][0][RTW89_QATAR][0][72] = 127,
+ [2][0][RTW89_UK][1][72] = 127,
+ [2][0][RTW89_UK][0][72] = 127,
+ [2][0][RTW89_FCC][1][74] = 8,
+ [2][0][RTW89_FCC][2][74] = 78,
+ [2][0][RTW89_ETSI][1][74] = 127,
+ [2][0][RTW89_ETSI][0][74] = 127,
+ [2][0][RTW89_MKK][1][74] = 127,
+ [2][0][RTW89_MKK][0][74] = 127,
+ [2][0][RTW89_IC][1][74] = 8,
+ [2][0][RTW89_KCC][1][74] = -2,
+ [2][0][RTW89_KCC][0][74] = 127,
+ [2][0][RTW89_ACMA][1][74] = 127,
+ [2][0][RTW89_ACMA][0][74] = 127,
+ [2][0][RTW89_CHILE][1][74] = 127,
+ [2][0][RTW89_QATAR][1][74] = 127,
+ [2][0][RTW89_QATAR][0][74] = 127,
+ [2][0][RTW89_UK][1][74] = 127,
+ [2][0][RTW89_UK][0][74] = 127,
+ [2][0][RTW89_FCC][1][75] = 8,
+ [2][0][RTW89_FCC][2][75] = 78,
+ [2][0][RTW89_ETSI][1][75] = 127,
+ [2][0][RTW89_ETSI][0][75] = 127,
+ [2][0][RTW89_MKK][1][75] = 127,
+ [2][0][RTW89_MKK][0][75] = 127,
+ [2][0][RTW89_IC][1][75] = 8,
+ [2][0][RTW89_KCC][1][75] = -2,
+ [2][0][RTW89_KCC][0][75] = 127,
+ [2][0][RTW89_ACMA][1][75] = 127,
+ [2][0][RTW89_ACMA][0][75] = 127,
+ [2][0][RTW89_CHILE][1][75] = 127,
+ [2][0][RTW89_QATAR][1][75] = 127,
+ [2][0][RTW89_QATAR][0][75] = 127,
+ [2][0][RTW89_UK][1][75] = 127,
+ [2][0][RTW89_UK][0][75] = 127,
+ [2][0][RTW89_FCC][1][77] = 8,
+ [2][0][RTW89_FCC][2][77] = 78,
+ [2][0][RTW89_ETSI][1][77] = 127,
+ [2][0][RTW89_ETSI][0][77] = 127,
+ [2][0][RTW89_MKK][1][77] = 127,
+ [2][0][RTW89_MKK][0][77] = 127,
+ [2][0][RTW89_IC][1][77] = 8,
+ [2][0][RTW89_KCC][1][77] = -2,
+ [2][0][RTW89_KCC][0][77] = 127,
+ [2][0][RTW89_ACMA][1][77] = 127,
+ [2][0][RTW89_ACMA][0][77] = 127,
+ [2][0][RTW89_CHILE][1][77] = 127,
+ [2][0][RTW89_QATAR][1][77] = 127,
+ [2][0][RTW89_QATAR][0][77] = 127,
+ [2][0][RTW89_UK][1][77] = 127,
+ [2][0][RTW89_UK][0][77] = 127,
+ [2][0][RTW89_FCC][1][79] = 8,
+ [2][0][RTW89_FCC][2][79] = 78,
+ [2][0][RTW89_ETSI][1][79] = 127,
+ [2][0][RTW89_ETSI][0][79] = 127,
+ [2][0][RTW89_MKK][1][79] = 127,
+ [2][0][RTW89_MKK][0][79] = 127,
+ [2][0][RTW89_IC][1][79] = 8,
+ [2][0][RTW89_KCC][1][79] = -2,
+ [2][0][RTW89_KCC][0][79] = 127,
+ [2][0][RTW89_ACMA][1][79] = 127,
+ [2][0][RTW89_ACMA][0][79] = 127,
+ [2][0][RTW89_CHILE][1][79] = 127,
+ [2][0][RTW89_QATAR][1][79] = 127,
+ [2][0][RTW89_QATAR][0][79] = 127,
+ [2][0][RTW89_UK][1][79] = 127,
+ [2][0][RTW89_UK][0][79] = 127,
+ [2][0][RTW89_FCC][1][81] = 8,
+ [2][0][RTW89_FCC][2][81] = 78,
+ [2][0][RTW89_ETSI][1][81] = 127,
+ [2][0][RTW89_ETSI][0][81] = 127,
+ [2][0][RTW89_MKK][1][81] = 127,
+ [2][0][RTW89_MKK][0][81] = 127,
+ [2][0][RTW89_IC][1][81] = 8,
+ [2][0][RTW89_KCC][1][81] = -2,
+ [2][0][RTW89_KCC][0][81] = 127,
+ [2][0][RTW89_ACMA][1][81] = 127,
+ [2][0][RTW89_ACMA][0][81] = 127,
+ [2][0][RTW89_CHILE][1][81] = 127,
+ [2][0][RTW89_QATAR][1][81] = 127,
+ [2][0][RTW89_QATAR][0][81] = 127,
+ [2][0][RTW89_UK][1][81] = 127,
+ [2][0][RTW89_UK][0][81] = 127,
+ [2][0][RTW89_FCC][1][83] = 8,
+ [2][0][RTW89_FCC][2][83] = 78,
+ [2][0][RTW89_ETSI][1][83] = 127,
+ [2][0][RTW89_ETSI][0][83] = 127,
+ [2][0][RTW89_MKK][1][83] = 127,
+ [2][0][RTW89_MKK][0][83] = 127,
+ [2][0][RTW89_IC][1][83] = 8,
+ [2][0][RTW89_KCC][1][83] = -2,
+ [2][0][RTW89_KCC][0][83] = 127,
+ [2][0][RTW89_ACMA][1][83] = 127,
+ [2][0][RTW89_ACMA][0][83] = 127,
+ [2][0][RTW89_CHILE][1][83] = 127,
+ [2][0][RTW89_QATAR][1][83] = 127,
+ [2][0][RTW89_QATAR][0][83] = 127,
+ [2][0][RTW89_UK][1][83] = 127,
+ [2][0][RTW89_UK][0][83] = 127,
+ [2][0][RTW89_FCC][1][85] = 8,
+ [2][0][RTW89_FCC][2][85] = 78,
+ [2][0][RTW89_ETSI][1][85] = 127,
+ [2][0][RTW89_ETSI][0][85] = 127,
+ [2][0][RTW89_MKK][1][85] = 127,
+ [2][0][RTW89_MKK][0][85] = 127,
+ [2][0][RTW89_IC][1][85] = 8,
+ [2][0][RTW89_KCC][1][85] = -2,
+ [2][0][RTW89_KCC][0][85] = 127,
+ [2][0][RTW89_ACMA][1][85] = 127,
+ [2][0][RTW89_ACMA][0][85] = 127,
+ [2][0][RTW89_CHILE][1][85] = 127,
+ [2][0][RTW89_QATAR][1][85] = 127,
+ [2][0][RTW89_QATAR][0][85] = 127,
+ [2][0][RTW89_UK][1][85] = 127,
+ [2][0][RTW89_UK][0][85] = 127,
+ [2][0][RTW89_FCC][1][87] = 8,
+ [2][0][RTW89_FCC][2][87] = 127,
+ [2][0][RTW89_ETSI][1][87] = 127,
+ [2][0][RTW89_ETSI][0][87] = 127,
+ [2][0][RTW89_MKK][1][87] = 127,
+ [2][0][RTW89_MKK][0][87] = 127,
+ [2][0][RTW89_IC][1][87] = 8,
+ [2][0][RTW89_KCC][1][87] = -2,
+ [2][0][RTW89_KCC][0][87] = 127,
+ [2][0][RTW89_ACMA][1][87] = 127,
+ [2][0][RTW89_ACMA][0][87] = 127,
+ [2][0][RTW89_CHILE][1][87] = 127,
+ [2][0][RTW89_QATAR][1][87] = 127,
+ [2][0][RTW89_QATAR][0][87] = 127,
+ [2][0][RTW89_UK][1][87] = 127,
+ [2][0][RTW89_UK][0][87] = 127,
+ [2][0][RTW89_FCC][1][89] = 8,
+ [2][0][RTW89_FCC][2][89] = 127,
+ [2][0][RTW89_ETSI][1][89] = 127,
+ [2][0][RTW89_ETSI][0][89] = 127,
+ [2][0][RTW89_MKK][1][89] = 127,
+ [2][0][RTW89_MKK][0][89] = 127,
+ [2][0][RTW89_IC][1][89] = 8,
+ [2][0][RTW89_KCC][1][89] = -2,
+ [2][0][RTW89_KCC][0][89] = 127,
+ [2][0][RTW89_ACMA][1][89] = 127,
+ [2][0][RTW89_ACMA][0][89] = 127,
+ [2][0][RTW89_CHILE][1][89] = 127,
+ [2][0][RTW89_QATAR][1][89] = 127,
+ [2][0][RTW89_QATAR][0][89] = 127,
+ [2][0][RTW89_UK][1][89] = 127,
+ [2][0][RTW89_UK][0][89] = 127,
+ [2][0][RTW89_FCC][1][90] = 8,
+ [2][0][RTW89_FCC][2][90] = 127,
+ [2][0][RTW89_ETSI][1][90] = 127,
+ [2][0][RTW89_ETSI][0][90] = 127,
+ [2][0][RTW89_MKK][1][90] = 127,
+ [2][0][RTW89_MKK][0][90] = 127,
+ [2][0][RTW89_IC][1][90] = 8,
+ [2][0][RTW89_KCC][1][90] = -2,
+ [2][0][RTW89_KCC][0][90] = 127,
+ [2][0][RTW89_ACMA][1][90] = 127,
+ [2][0][RTW89_ACMA][0][90] = 127,
+ [2][0][RTW89_CHILE][1][90] = 127,
+ [2][0][RTW89_QATAR][1][90] = 127,
+ [2][0][RTW89_QATAR][0][90] = 127,
+ [2][0][RTW89_UK][1][90] = 127,
+ [2][0][RTW89_UK][0][90] = 127,
+ [2][0][RTW89_FCC][1][92] = 8,
+ [2][0][RTW89_FCC][2][92] = 127,
+ [2][0][RTW89_ETSI][1][92] = 127,
+ [2][0][RTW89_ETSI][0][92] = 127,
+ [2][0][RTW89_MKK][1][92] = 127,
+ [2][0][RTW89_MKK][0][92] = 127,
+ [2][0][RTW89_IC][1][92] = 8,
+ [2][0][RTW89_KCC][1][92] = -2,
+ [2][0][RTW89_KCC][0][92] = 127,
+ [2][0][RTW89_ACMA][1][92] = 127,
+ [2][0][RTW89_ACMA][0][92] = 127,
+ [2][0][RTW89_CHILE][1][92] = 127,
+ [2][0][RTW89_QATAR][1][92] = 127,
+ [2][0][RTW89_QATAR][0][92] = 127,
+ [2][0][RTW89_UK][1][92] = 127,
+ [2][0][RTW89_UK][0][92] = 127,
+ [2][0][RTW89_FCC][1][94] = 8,
+ [2][0][RTW89_FCC][2][94] = 127,
+ [2][0][RTW89_ETSI][1][94] = 127,
+ [2][0][RTW89_ETSI][0][94] = 127,
+ [2][0][RTW89_MKK][1][94] = 127,
+ [2][0][RTW89_MKK][0][94] = 127,
+ [2][0][RTW89_IC][1][94] = 8,
+ [2][0][RTW89_KCC][1][94] = -2,
+ [2][0][RTW89_KCC][0][94] = 127,
+ [2][0][RTW89_ACMA][1][94] = 127,
+ [2][0][RTW89_ACMA][0][94] = 127,
+ [2][0][RTW89_CHILE][1][94] = 127,
+ [2][0][RTW89_QATAR][1][94] = 127,
+ [2][0][RTW89_QATAR][0][94] = 127,
+ [2][0][RTW89_UK][1][94] = 127,
+ [2][0][RTW89_UK][0][94] = 127,
+ [2][0][RTW89_FCC][1][96] = 8,
+ [2][0][RTW89_FCC][2][96] = 127,
+ [2][0][RTW89_ETSI][1][96] = 127,
+ [2][0][RTW89_ETSI][0][96] = 127,
+ [2][0][RTW89_MKK][1][96] = 127,
+ [2][0][RTW89_MKK][0][96] = 127,
+ [2][0][RTW89_IC][1][96] = 8,
+ [2][0][RTW89_KCC][1][96] = -2,
+ [2][0][RTW89_KCC][0][96] = 127,
+ [2][0][RTW89_ACMA][1][96] = 127,
+ [2][0][RTW89_ACMA][0][96] = 127,
+ [2][0][RTW89_CHILE][1][96] = 127,
+ [2][0][RTW89_QATAR][1][96] = 127,
+ [2][0][RTW89_QATAR][0][96] = 127,
+ [2][0][RTW89_UK][1][96] = 127,
+ [2][0][RTW89_UK][0][96] = 127,
+ [2][0][RTW89_FCC][1][98] = 8,
+ [2][0][RTW89_FCC][2][98] = 127,
+ [2][0][RTW89_ETSI][1][98] = 127,
+ [2][0][RTW89_ETSI][0][98] = 127,
+ [2][0][RTW89_MKK][1][98] = 127,
+ [2][0][RTW89_MKK][0][98] = 127,
+ [2][0][RTW89_IC][1][98] = 8,
+ [2][0][RTW89_KCC][1][98] = -2,
+ [2][0][RTW89_KCC][0][98] = 127,
+ [2][0][RTW89_ACMA][1][98] = 127,
+ [2][0][RTW89_ACMA][0][98] = 127,
+ [2][0][RTW89_CHILE][1][98] = 127,
+ [2][0][RTW89_QATAR][1][98] = 127,
+ [2][0][RTW89_QATAR][0][98] = 127,
+ [2][0][RTW89_UK][1][98] = 127,
+ [2][0][RTW89_UK][0][98] = 127,
+ [2][0][RTW89_FCC][1][100] = 8,
+ [2][0][RTW89_FCC][2][100] = 127,
+ [2][0][RTW89_ETSI][1][100] = 127,
+ [2][0][RTW89_ETSI][0][100] = 127,
+ [2][0][RTW89_MKK][1][100] = 127,
+ [2][0][RTW89_MKK][0][100] = 127,
+ [2][0][RTW89_IC][1][100] = 8,
+ [2][0][RTW89_KCC][1][100] = -2,
+ [2][0][RTW89_KCC][0][100] = 127,
+ [2][0][RTW89_ACMA][1][100] = 127,
+ [2][0][RTW89_ACMA][0][100] = 127,
+ [2][0][RTW89_CHILE][1][100] = 127,
+ [2][0][RTW89_QATAR][1][100] = 127,
+ [2][0][RTW89_QATAR][0][100] = 127,
+ [2][0][RTW89_UK][1][100] = 127,
+ [2][0][RTW89_UK][0][100] = 127,
+ [2][0][RTW89_FCC][1][102] = 8,
+ [2][0][RTW89_FCC][2][102] = 127,
+ [2][0][RTW89_ETSI][1][102] = 127,
+ [2][0][RTW89_ETSI][0][102] = 127,
+ [2][0][RTW89_MKK][1][102] = 127,
+ [2][0][RTW89_MKK][0][102] = 127,
+ [2][0][RTW89_IC][1][102] = 8,
+ [2][0][RTW89_KCC][1][102] = -2,
+ [2][0][RTW89_KCC][0][102] = 127,
+ [2][0][RTW89_ACMA][1][102] = 127,
+ [2][0][RTW89_ACMA][0][102] = 127,
+ [2][0][RTW89_CHILE][1][102] = 127,
+ [2][0][RTW89_QATAR][1][102] = 127,
+ [2][0][RTW89_QATAR][0][102] = 127,
+ [2][0][RTW89_UK][1][102] = 127,
+ [2][0][RTW89_UK][0][102] = 127,
+ [2][0][RTW89_FCC][1][104] = 8,
+ [2][0][RTW89_FCC][2][104] = 127,
+ [2][0][RTW89_ETSI][1][104] = 127,
+ [2][0][RTW89_ETSI][0][104] = 127,
+ [2][0][RTW89_MKK][1][104] = 127,
+ [2][0][RTW89_MKK][0][104] = 127,
+ [2][0][RTW89_IC][1][104] = 8,
+ [2][0][RTW89_KCC][1][104] = -2,
+ [2][0][RTW89_KCC][0][104] = 127,
+ [2][0][RTW89_ACMA][1][104] = 127,
+ [2][0][RTW89_ACMA][0][104] = 127,
+ [2][0][RTW89_CHILE][1][104] = 127,
+ [2][0][RTW89_QATAR][1][104] = 127,
+ [2][0][RTW89_QATAR][0][104] = 127,
+ [2][0][RTW89_UK][1][104] = 127,
+ [2][0][RTW89_UK][0][104] = 127,
+ [2][0][RTW89_FCC][1][105] = 8,
+ [2][0][RTW89_FCC][2][105] = 127,
+ [2][0][RTW89_ETSI][1][105] = 127,
+ [2][0][RTW89_ETSI][0][105] = 127,
+ [2][0][RTW89_MKK][1][105] = 127,
+ [2][0][RTW89_MKK][0][105] = 127,
+ [2][0][RTW89_IC][1][105] = 8,
+ [2][0][RTW89_KCC][1][105] = -2,
+ [2][0][RTW89_KCC][0][105] = 127,
+ [2][0][RTW89_ACMA][1][105] = 127,
+ [2][0][RTW89_ACMA][0][105] = 127,
+ [2][0][RTW89_CHILE][1][105] = 127,
+ [2][0][RTW89_QATAR][1][105] = 127,
+ [2][0][RTW89_QATAR][0][105] = 127,
+ [2][0][RTW89_UK][1][105] = 127,
+ [2][0][RTW89_UK][0][105] = 127,
+ [2][0][RTW89_FCC][1][107] = 10,
+ [2][0][RTW89_FCC][2][107] = 127,
+ [2][0][RTW89_ETSI][1][107] = 127,
+ [2][0][RTW89_ETSI][0][107] = 127,
+ [2][0][RTW89_MKK][1][107] = 127,
+ [2][0][RTW89_MKK][0][107] = 127,
+ [2][0][RTW89_IC][1][107] = 10,
+ [2][0][RTW89_KCC][1][107] = -2,
+ [2][0][RTW89_KCC][0][107] = 127,
+ [2][0][RTW89_ACMA][1][107] = 127,
+ [2][0][RTW89_ACMA][0][107] = 127,
+ [2][0][RTW89_CHILE][1][107] = 127,
+ [2][0][RTW89_QATAR][1][107] = 127,
+ [2][0][RTW89_QATAR][0][107] = 127,
+ [2][0][RTW89_UK][1][107] = 127,
+ [2][0][RTW89_UK][0][107] = 127,
+ [2][0][RTW89_FCC][1][109] = 12,
+ [2][0][RTW89_FCC][2][109] = 127,
+ [2][0][RTW89_ETSI][1][109] = 127,
+ [2][0][RTW89_ETSI][0][109] = 127,
+ [2][0][RTW89_MKK][1][109] = 127,
+ [2][0][RTW89_MKK][0][109] = 127,
+ [2][0][RTW89_IC][1][109] = 12,
+ [2][0][RTW89_KCC][1][109] = 127,
+ [2][0][RTW89_KCC][0][109] = 127,
+ [2][0][RTW89_ACMA][1][109] = 127,
+ [2][0][RTW89_ACMA][0][109] = 127,
+ [2][0][RTW89_CHILE][1][109] = 127,
+ [2][0][RTW89_QATAR][1][109] = 127,
+ [2][0][RTW89_QATAR][0][109] = 127,
+ [2][0][RTW89_UK][1][109] = 127,
+ [2][0][RTW89_UK][0][109] = 127,
+ [2][0][RTW89_FCC][1][111] = 127,
+ [2][0][RTW89_FCC][2][111] = 127,
+ [2][0][RTW89_ETSI][1][111] = 127,
+ [2][0][RTW89_ETSI][0][111] = 127,
+ [2][0][RTW89_MKK][1][111] = 127,
+ [2][0][RTW89_MKK][0][111] = 127,
+ [2][0][RTW89_IC][1][111] = 127,
+ [2][0][RTW89_KCC][1][111] = 127,
+ [2][0][RTW89_KCC][0][111] = 127,
+ [2][0][RTW89_ACMA][1][111] = 127,
+ [2][0][RTW89_ACMA][0][111] = 127,
+ [2][0][RTW89_CHILE][1][111] = 127,
+ [2][0][RTW89_QATAR][1][111] = 127,
+ [2][0][RTW89_QATAR][0][111] = 127,
+ [2][0][RTW89_UK][1][111] = 127,
+ [2][0][RTW89_UK][0][111] = 127,
+ [2][0][RTW89_FCC][1][113] = 127,
+ [2][0][RTW89_FCC][2][113] = 127,
+ [2][0][RTW89_ETSI][1][113] = 127,
+ [2][0][RTW89_ETSI][0][113] = 127,
+ [2][0][RTW89_MKK][1][113] = 127,
+ [2][0][RTW89_MKK][0][113] = 127,
+ [2][0][RTW89_IC][1][113] = 127,
+ [2][0][RTW89_KCC][1][113] = 127,
+ [2][0][RTW89_KCC][0][113] = 127,
+ [2][0][RTW89_ACMA][1][113] = 127,
+ [2][0][RTW89_ACMA][0][113] = 127,
+ [2][0][RTW89_CHILE][1][113] = 127,
+ [2][0][RTW89_QATAR][1][113] = 127,
+ [2][0][RTW89_QATAR][0][113] = 127,
+ [2][0][RTW89_UK][1][113] = 127,
+ [2][0][RTW89_UK][0][113] = 127,
+ [2][0][RTW89_FCC][1][115] = 127,
+ [2][0][RTW89_FCC][2][115] = 127,
+ [2][0][RTW89_ETSI][1][115] = 127,
+ [2][0][RTW89_ETSI][0][115] = 127,
+ [2][0][RTW89_MKK][1][115] = 127,
+ [2][0][RTW89_MKK][0][115] = 127,
+ [2][0][RTW89_IC][1][115] = 127,
+ [2][0][RTW89_KCC][1][115] = 127,
+ [2][0][RTW89_KCC][0][115] = 127,
+ [2][0][RTW89_ACMA][1][115] = 127,
+ [2][0][RTW89_ACMA][0][115] = 127,
+ [2][0][RTW89_CHILE][1][115] = 127,
+ [2][0][RTW89_QATAR][1][115] = 127,
+ [2][0][RTW89_QATAR][0][115] = 127,
+ [2][0][RTW89_UK][1][115] = 127,
+ [2][0][RTW89_UK][0][115] = 127,
+ [2][0][RTW89_FCC][1][117] = 127,
+ [2][0][RTW89_FCC][2][117] = 127,
+ [2][0][RTW89_ETSI][1][117] = 127,
+ [2][0][RTW89_ETSI][0][117] = 127,
+ [2][0][RTW89_MKK][1][117] = 127,
+ [2][0][RTW89_MKK][0][117] = 127,
+ [2][0][RTW89_IC][1][117] = 127,
+ [2][0][RTW89_KCC][1][117] = 127,
+ [2][0][RTW89_KCC][0][117] = 127,
+ [2][0][RTW89_ACMA][1][117] = 127,
+ [2][0][RTW89_ACMA][0][117] = 127,
+ [2][0][RTW89_CHILE][1][117] = 127,
+ [2][0][RTW89_QATAR][1][117] = 127,
+ [2][0][RTW89_QATAR][0][117] = 127,
+ [2][0][RTW89_UK][1][117] = 127,
+ [2][0][RTW89_UK][0][117] = 127,
+ [2][0][RTW89_FCC][1][119] = 127,
+ [2][0][RTW89_FCC][2][119] = 127,
+ [2][0][RTW89_ETSI][1][119] = 127,
+ [2][0][RTW89_ETSI][0][119] = 127,
+ [2][0][RTW89_MKK][1][119] = 127,
+ [2][0][RTW89_MKK][0][119] = 127,
+ [2][0][RTW89_IC][1][119] = 127,
+ [2][0][RTW89_KCC][1][119] = 127,
+ [2][0][RTW89_KCC][0][119] = 127,
+ [2][0][RTW89_ACMA][1][119] = 127,
+ [2][0][RTW89_ACMA][0][119] = 127,
+ [2][0][RTW89_CHILE][1][119] = 127,
+ [2][0][RTW89_QATAR][1][119] = 127,
+ [2][0][RTW89_QATAR][0][119] = 127,
+ [2][0][RTW89_UK][1][119] = 127,
+ [2][0][RTW89_UK][0][119] = 127,
+ [2][1][RTW89_FCC][1][0] = -16,
+ [2][1][RTW89_FCC][2][0] = 54,
+ [2][1][RTW89_ETSI][1][0] = 44,
+ [2][1][RTW89_ETSI][0][0] = 6,
+ [2][1][RTW89_MKK][1][0] = 42,
+ [2][1][RTW89_MKK][0][0] = 2,
+ [2][1][RTW89_IC][1][0] = -16,
+ [2][1][RTW89_KCC][1][0] = -14,
+ [2][1][RTW89_KCC][0][0] = -14,
+ [2][1][RTW89_ACMA][1][0] = 44,
+ [2][1][RTW89_ACMA][0][0] = 6,
+ [2][1][RTW89_CHILE][1][0] = -16,
+ [2][1][RTW89_QATAR][1][0] = 44,
+ [2][1][RTW89_QATAR][0][0] = 6,
+ [2][1][RTW89_UK][1][0] = 44,
+ [2][1][RTW89_UK][0][0] = 6,
+ [2][1][RTW89_FCC][1][2] = -16,
+ [2][1][RTW89_FCC][2][2] = 54,
+ [2][1][RTW89_ETSI][1][2] = 44,
+ [2][1][RTW89_ETSI][0][2] = 6,
+ [2][1][RTW89_MKK][1][2] = 40,
+ [2][1][RTW89_MKK][0][2] = 2,
+ [2][1][RTW89_IC][1][2] = -16,
+ [2][1][RTW89_KCC][1][2] = -14,
+ [2][1][RTW89_KCC][0][2] = -14,
+ [2][1][RTW89_ACMA][1][2] = 44,
+ [2][1][RTW89_ACMA][0][2] = 6,
+ [2][1][RTW89_CHILE][1][2] = -16,
+ [2][1][RTW89_QATAR][1][2] = 44,
+ [2][1][RTW89_QATAR][0][2] = 6,
+ [2][1][RTW89_UK][1][2] = 44,
+ [2][1][RTW89_UK][0][2] = 6,
+ [2][1][RTW89_FCC][1][4] = -16,
+ [2][1][RTW89_FCC][2][4] = 54,
+ [2][1][RTW89_ETSI][1][4] = 44,
+ [2][1][RTW89_ETSI][0][4] = 6,
+ [2][1][RTW89_MKK][1][4] = 40,
+ [2][1][RTW89_MKK][0][4] = 2,
+ [2][1][RTW89_IC][1][4] = -16,
+ [2][1][RTW89_KCC][1][4] = -14,
+ [2][1][RTW89_KCC][0][4] = -14,
+ [2][1][RTW89_ACMA][1][4] = 44,
+ [2][1][RTW89_ACMA][0][4] = 6,
+ [2][1][RTW89_CHILE][1][4] = -16,
+ [2][1][RTW89_QATAR][1][4] = 44,
+ [2][1][RTW89_QATAR][0][4] = 6,
+ [2][1][RTW89_UK][1][4] = 44,
+ [2][1][RTW89_UK][0][4] = 6,
+ [2][1][RTW89_FCC][1][6] = -16,
+ [2][1][RTW89_FCC][2][6] = 54,
+ [2][1][RTW89_ETSI][1][6] = 44,
+ [2][1][RTW89_ETSI][0][6] = 6,
+ [2][1][RTW89_MKK][1][6] = 40,
+ [2][1][RTW89_MKK][0][6] = 2,
+ [2][1][RTW89_IC][1][6] = -16,
+ [2][1][RTW89_KCC][1][6] = -14,
+ [2][1][RTW89_KCC][0][6] = -14,
+ [2][1][RTW89_ACMA][1][6] = 44,
+ [2][1][RTW89_ACMA][0][6] = 6,
+ [2][1][RTW89_CHILE][1][6] = -16,
+ [2][1][RTW89_QATAR][1][6] = 44,
+ [2][1][RTW89_QATAR][0][6] = 6,
+ [2][1][RTW89_UK][1][6] = 44,
+ [2][1][RTW89_UK][0][6] = 6,
+ [2][1][RTW89_FCC][1][8] = -16,
+ [2][1][RTW89_FCC][2][8] = 54,
+ [2][1][RTW89_ETSI][1][8] = 44,
+ [2][1][RTW89_ETSI][0][8] = 6,
+ [2][1][RTW89_MKK][1][8] = 40,
+ [2][1][RTW89_MKK][0][8] = 2,
+ [2][1][RTW89_IC][1][8] = -16,
+ [2][1][RTW89_KCC][1][8] = -14,
+ [2][1][RTW89_KCC][0][8] = -14,
+ [2][1][RTW89_ACMA][1][8] = 44,
+ [2][1][RTW89_ACMA][0][8] = 6,
+ [2][1][RTW89_CHILE][1][8] = -16,
+ [2][1][RTW89_QATAR][1][8] = 44,
+ [2][1][RTW89_QATAR][0][8] = 6,
+ [2][1][RTW89_UK][1][8] = 44,
+ [2][1][RTW89_UK][0][8] = 6,
+ [2][1][RTW89_FCC][1][10] = -16,
+ [2][1][RTW89_FCC][2][10] = 54,
+ [2][1][RTW89_ETSI][1][10] = 44,
+ [2][1][RTW89_ETSI][0][10] = 6,
+ [2][1][RTW89_MKK][1][10] = 40,
+ [2][1][RTW89_MKK][0][10] = 2,
+ [2][1][RTW89_IC][1][10] = -16,
+ [2][1][RTW89_KCC][1][10] = -14,
+ [2][1][RTW89_KCC][0][10] = -14,
+ [2][1][RTW89_ACMA][1][10] = 44,
+ [2][1][RTW89_ACMA][0][10] = 6,
+ [2][1][RTW89_CHILE][1][10] = -16,
+ [2][1][RTW89_QATAR][1][10] = 44,
+ [2][1][RTW89_QATAR][0][10] = 6,
+ [2][1][RTW89_UK][1][10] = 44,
+ [2][1][RTW89_UK][0][10] = 6,
+ [2][1][RTW89_FCC][1][12] = -16,
+ [2][1][RTW89_FCC][2][12] = 54,
+ [2][1][RTW89_ETSI][1][12] = 44,
+ [2][1][RTW89_ETSI][0][12] = 6,
+ [2][1][RTW89_MKK][1][12] = 40,
+ [2][1][RTW89_MKK][0][12] = 2,
+ [2][1][RTW89_IC][1][12] = -16,
+ [2][1][RTW89_KCC][1][12] = -14,
+ [2][1][RTW89_KCC][0][12] = -14,
+ [2][1][RTW89_ACMA][1][12] = 44,
+ [2][1][RTW89_ACMA][0][12] = 6,
+ [2][1][RTW89_CHILE][1][12] = -16,
+ [2][1][RTW89_QATAR][1][12] = 44,
+ [2][1][RTW89_QATAR][0][12] = 6,
+ [2][1][RTW89_UK][1][12] = 44,
+ [2][1][RTW89_UK][0][12] = 6,
+ [2][1][RTW89_FCC][1][14] = -16,
+ [2][1][RTW89_FCC][2][14] = 54,
+ [2][1][RTW89_ETSI][1][14] = 44,
+ [2][1][RTW89_ETSI][0][14] = 6,
+ [2][1][RTW89_MKK][1][14] = 40,
+ [2][1][RTW89_MKK][0][14] = 2,
+ [2][1][RTW89_IC][1][14] = -16,
+ [2][1][RTW89_KCC][1][14] = -14,
+ [2][1][RTW89_KCC][0][14] = -14,
+ [2][1][RTW89_ACMA][1][14] = 44,
+ [2][1][RTW89_ACMA][0][14] = 6,
+ [2][1][RTW89_CHILE][1][14] = -16,
+ [2][1][RTW89_QATAR][1][14] = 44,
+ [2][1][RTW89_QATAR][0][14] = 6,
+ [2][1][RTW89_UK][1][14] = 44,
+ [2][1][RTW89_UK][0][14] = 6,
+ [2][1][RTW89_FCC][1][15] = -16,
+ [2][1][RTW89_FCC][2][15] = 54,
+ [2][1][RTW89_ETSI][1][15] = 44,
+ [2][1][RTW89_ETSI][0][15] = 6,
+ [2][1][RTW89_MKK][1][15] = 40,
+ [2][1][RTW89_MKK][0][15] = 2,
+ [2][1][RTW89_IC][1][15] = -16,
+ [2][1][RTW89_KCC][1][15] = -14,
+ [2][1][RTW89_KCC][0][15] = -14,
+ [2][1][RTW89_ACMA][1][15] = 44,
+ [2][1][RTW89_ACMA][0][15] = 6,
+ [2][1][RTW89_CHILE][1][15] = -16,
+ [2][1][RTW89_QATAR][1][15] = 44,
+ [2][1][RTW89_QATAR][0][15] = 6,
+ [2][1][RTW89_UK][1][15] = 44,
+ [2][1][RTW89_UK][0][15] = 6,
+ [2][1][RTW89_FCC][1][17] = -16,
+ [2][1][RTW89_FCC][2][17] = 54,
+ [2][1][RTW89_ETSI][1][17] = 44,
+ [2][1][RTW89_ETSI][0][17] = 6,
+ [2][1][RTW89_MKK][1][17] = 40,
+ [2][1][RTW89_MKK][0][17] = 2,
+ [2][1][RTW89_IC][1][17] = -16,
+ [2][1][RTW89_KCC][1][17] = -14,
+ [2][1][RTW89_KCC][0][17] = -14,
+ [2][1][RTW89_ACMA][1][17] = 44,
+ [2][1][RTW89_ACMA][0][17] = 6,
+ [2][1][RTW89_CHILE][1][17] = -16,
+ [2][1][RTW89_QATAR][1][17] = 44,
+ [2][1][RTW89_QATAR][0][17] = 6,
+ [2][1][RTW89_UK][1][17] = 44,
+ [2][1][RTW89_UK][0][17] = 6,
+ [2][1][RTW89_FCC][1][19] = -16,
+ [2][1][RTW89_FCC][2][19] = 54,
+ [2][1][RTW89_ETSI][1][19] = 44,
+ [2][1][RTW89_ETSI][0][19] = 6,
+ [2][1][RTW89_MKK][1][19] = 40,
+ [2][1][RTW89_MKK][0][19] = 2,
+ [2][1][RTW89_IC][1][19] = -16,
+ [2][1][RTW89_KCC][1][19] = -14,
+ [2][1][RTW89_KCC][0][19] = -14,
+ [2][1][RTW89_ACMA][1][19] = 44,
+ [2][1][RTW89_ACMA][0][19] = 6,
+ [2][1][RTW89_CHILE][1][19] = -16,
+ [2][1][RTW89_QATAR][1][19] = 44,
+ [2][1][RTW89_QATAR][0][19] = 6,
+ [2][1][RTW89_UK][1][19] = 44,
+ [2][1][RTW89_UK][0][19] = 6,
+ [2][1][RTW89_FCC][1][21] = -16,
+ [2][1][RTW89_FCC][2][21] = 54,
+ [2][1][RTW89_ETSI][1][21] = 44,
+ [2][1][RTW89_ETSI][0][21] = 6,
+ [2][1][RTW89_MKK][1][21] = 40,
+ [2][1][RTW89_MKK][0][21] = 2,
+ [2][1][RTW89_IC][1][21] = -16,
+ [2][1][RTW89_KCC][1][21] = -14,
+ [2][1][RTW89_KCC][0][21] = -14,
+ [2][1][RTW89_ACMA][1][21] = 44,
+ [2][1][RTW89_ACMA][0][21] = 6,
+ [2][1][RTW89_CHILE][1][21] = -16,
+ [2][1][RTW89_QATAR][1][21] = 44,
+ [2][1][RTW89_QATAR][0][21] = 6,
+ [2][1][RTW89_UK][1][21] = 44,
+ [2][1][RTW89_UK][0][21] = 6,
+ [2][1][RTW89_FCC][1][23] = -16,
+ [2][1][RTW89_FCC][2][23] = 54,
+ [2][1][RTW89_ETSI][1][23] = 44,
+ [2][1][RTW89_ETSI][0][23] = 6,
+ [2][1][RTW89_MKK][1][23] = 40,
+ [2][1][RTW89_MKK][0][23] = 2,
+ [2][1][RTW89_IC][1][23] = -16,
+ [2][1][RTW89_KCC][1][23] = -14,
+ [2][1][RTW89_KCC][0][23] = -14,
+ [2][1][RTW89_ACMA][1][23] = 44,
+ [2][1][RTW89_ACMA][0][23] = 6,
+ [2][1][RTW89_CHILE][1][23] = -16,
+ [2][1][RTW89_QATAR][1][23] = 44,
+ [2][1][RTW89_QATAR][0][23] = 6,
+ [2][1][RTW89_UK][1][23] = 44,
+ [2][1][RTW89_UK][0][23] = 6,
+ [2][1][RTW89_FCC][1][25] = -16,
+ [2][1][RTW89_FCC][2][25] = 54,
+ [2][1][RTW89_ETSI][1][25] = 44,
+ [2][1][RTW89_ETSI][0][25] = 6,
+ [2][1][RTW89_MKK][1][25] = 40,
+ [2][1][RTW89_MKK][0][25] = 2,
+ [2][1][RTW89_IC][1][25] = -16,
+ [2][1][RTW89_KCC][1][25] = -14,
+ [2][1][RTW89_KCC][0][25] = -14,
+ [2][1][RTW89_ACMA][1][25] = 44,
+ [2][1][RTW89_ACMA][0][25] = 6,
+ [2][1][RTW89_CHILE][1][25] = -16,
+ [2][1][RTW89_QATAR][1][25] = 44,
+ [2][1][RTW89_QATAR][0][25] = 6,
+ [2][1][RTW89_UK][1][25] = 44,
+ [2][1][RTW89_UK][0][25] = 6,
+ [2][1][RTW89_FCC][1][27] = -16,
+ [2][1][RTW89_FCC][2][27] = 54,
+ [2][1][RTW89_ETSI][1][27] = 44,
+ [2][1][RTW89_ETSI][0][27] = 6,
+ [2][1][RTW89_MKK][1][27] = 40,
+ [2][1][RTW89_MKK][0][27] = 2,
+ [2][1][RTW89_IC][1][27] = -16,
+ [2][1][RTW89_KCC][1][27] = -14,
+ [2][1][RTW89_KCC][0][27] = -14,
+ [2][1][RTW89_ACMA][1][27] = 44,
+ [2][1][RTW89_ACMA][0][27] = 6,
+ [2][1][RTW89_CHILE][1][27] = -16,
+ [2][1][RTW89_QATAR][1][27] = 44,
+ [2][1][RTW89_QATAR][0][27] = 6,
+ [2][1][RTW89_UK][1][27] = 44,
+ [2][1][RTW89_UK][0][27] = 6,
+ [2][1][RTW89_FCC][1][29] = -16,
+ [2][1][RTW89_FCC][2][29] = 54,
+ [2][1][RTW89_ETSI][1][29] = 44,
+ [2][1][RTW89_ETSI][0][29] = 6,
+ [2][1][RTW89_MKK][1][29] = 40,
+ [2][1][RTW89_MKK][0][29] = 2,
+ [2][1][RTW89_IC][1][29] = -16,
+ [2][1][RTW89_KCC][1][29] = -14,
+ [2][1][RTW89_KCC][0][29] = -14,
+ [2][1][RTW89_ACMA][1][29] = 44,
+ [2][1][RTW89_ACMA][0][29] = 6,
+ [2][1][RTW89_CHILE][1][29] = -16,
+ [2][1][RTW89_QATAR][1][29] = 44,
+ [2][1][RTW89_QATAR][0][29] = 6,
+ [2][1][RTW89_UK][1][29] = 44,
+ [2][1][RTW89_UK][0][29] = 6,
+ [2][1][RTW89_FCC][1][30] = -16,
+ [2][1][RTW89_FCC][2][30] = 54,
+ [2][1][RTW89_ETSI][1][30] = 44,
+ [2][1][RTW89_ETSI][0][30] = 6,
+ [2][1][RTW89_MKK][1][30] = 40,
+ [2][1][RTW89_MKK][0][30] = 2,
+ [2][1][RTW89_IC][1][30] = -16,
+ [2][1][RTW89_KCC][1][30] = -14,
+ [2][1][RTW89_KCC][0][30] = -14,
+ [2][1][RTW89_ACMA][1][30] = 44,
+ [2][1][RTW89_ACMA][0][30] = 6,
+ [2][1][RTW89_CHILE][1][30] = -16,
+ [2][1][RTW89_QATAR][1][30] = 44,
+ [2][1][RTW89_QATAR][0][30] = 6,
+ [2][1][RTW89_UK][1][30] = 44,
+ [2][1][RTW89_UK][0][30] = 6,
+ [2][1][RTW89_FCC][1][32] = -16,
+ [2][1][RTW89_FCC][2][32] = 54,
+ [2][1][RTW89_ETSI][1][32] = 44,
+ [2][1][RTW89_ETSI][0][32] = 6,
+ [2][1][RTW89_MKK][1][32] = 40,
+ [2][1][RTW89_MKK][0][32] = 2,
+ [2][1][RTW89_IC][1][32] = -16,
+ [2][1][RTW89_KCC][1][32] = -14,
+ [2][1][RTW89_KCC][0][32] = -14,
+ [2][1][RTW89_ACMA][1][32] = 44,
+ [2][1][RTW89_ACMA][0][32] = 6,
+ [2][1][RTW89_CHILE][1][32] = -16,
+ [2][1][RTW89_QATAR][1][32] = 44,
+ [2][1][RTW89_QATAR][0][32] = 6,
+ [2][1][RTW89_UK][1][32] = 44,
+ [2][1][RTW89_UK][0][32] = 6,
+ [2][1][RTW89_FCC][1][34] = -16,
+ [2][1][RTW89_FCC][2][34] = 54,
+ [2][1][RTW89_ETSI][1][34] = 44,
+ [2][1][RTW89_ETSI][0][34] = 6,
+ [2][1][RTW89_MKK][1][34] = 40,
+ [2][1][RTW89_MKK][0][34] = 2,
+ [2][1][RTW89_IC][1][34] = -16,
+ [2][1][RTW89_KCC][1][34] = -14,
+ [2][1][RTW89_KCC][0][34] = -14,
+ [2][1][RTW89_ACMA][1][34] = 44,
+ [2][1][RTW89_ACMA][0][34] = 6,
+ [2][1][RTW89_CHILE][1][34] = -16,
+ [2][1][RTW89_QATAR][1][34] = 44,
+ [2][1][RTW89_QATAR][0][34] = 6,
+ [2][1][RTW89_UK][1][34] = 44,
+ [2][1][RTW89_UK][0][34] = 6,
+ [2][1][RTW89_FCC][1][36] = -16,
+ [2][1][RTW89_FCC][2][36] = 54,
+ [2][1][RTW89_ETSI][1][36] = 44,
+ [2][1][RTW89_ETSI][0][36] = 6,
+ [2][1][RTW89_MKK][1][36] = 40,
+ [2][1][RTW89_MKK][0][36] = 2,
+ [2][1][RTW89_IC][1][36] = -16,
+ [2][1][RTW89_KCC][1][36] = -14,
+ [2][1][RTW89_KCC][0][36] = -14,
+ [2][1][RTW89_ACMA][1][36] = 44,
+ [2][1][RTW89_ACMA][0][36] = 6,
+ [2][1][RTW89_CHILE][1][36] = -16,
+ [2][1][RTW89_QATAR][1][36] = 44,
+ [2][1][RTW89_QATAR][0][36] = 6,
+ [2][1][RTW89_UK][1][36] = 44,
+ [2][1][RTW89_UK][0][36] = 6,
+ [2][1][RTW89_FCC][1][38] = -16,
+ [2][1][RTW89_FCC][2][38] = 54,
+ [2][1][RTW89_ETSI][1][38] = 44,
+ [2][1][RTW89_ETSI][0][38] = 6,
+ [2][1][RTW89_MKK][1][38] = 40,
+ [2][1][RTW89_MKK][0][38] = 2,
+ [2][1][RTW89_IC][1][38] = -16,
+ [2][1][RTW89_KCC][1][38] = -14,
+ [2][1][RTW89_KCC][0][38] = -14,
+ [2][1][RTW89_ACMA][1][38] = 44,
+ [2][1][RTW89_ACMA][0][38] = 6,
+ [2][1][RTW89_CHILE][1][38] = -16,
+ [2][1][RTW89_QATAR][1][38] = 44,
+ [2][1][RTW89_QATAR][0][38] = 6,
+ [2][1][RTW89_UK][1][38] = 44,
+ [2][1][RTW89_UK][0][38] = 6,
+ [2][1][RTW89_FCC][1][40] = -16,
+ [2][1][RTW89_FCC][2][40] = 54,
+ [2][1][RTW89_ETSI][1][40] = 44,
+ [2][1][RTW89_ETSI][0][40] = 6,
+ [2][1][RTW89_MKK][1][40] = 40,
+ [2][1][RTW89_MKK][0][40] = 2,
+ [2][1][RTW89_IC][1][40] = -16,
+ [2][1][RTW89_KCC][1][40] = -14,
+ [2][1][RTW89_KCC][0][40] = -14,
+ [2][1][RTW89_ACMA][1][40] = 44,
+ [2][1][RTW89_ACMA][0][40] = 6,
+ [2][1][RTW89_CHILE][1][40] = -16,
+ [2][1][RTW89_QATAR][1][40] = 44,
+ [2][1][RTW89_QATAR][0][40] = 6,
+ [2][1][RTW89_UK][1][40] = 44,
+ [2][1][RTW89_UK][0][40] = 6,
+ [2][1][RTW89_FCC][1][42] = -16,
+ [2][1][RTW89_FCC][2][42] = 54,
+ [2][1][RTW89_ETSI][1][42] = 44,
+ [2][1][RTW89_ETSI][0][42] = 6,
+ [2][1][RTW89_MKK][1][42] = 40,
+ [2][1][RTW89_MKK][0][42] = 2,
+ [2][1][RTW89_IC][1][42] = -16,
+ [2][1][RTW89_KCC][1][42] = -14,
+ [2][1][RTW89_KCC][0][42] = -14,
+ [2][1][RTW89_ACMA][1][42] = 44,
+ [2][1][RTW89_ACMA][0][42] = 6,
+ [2][1][RTW89_CHILE][1][42] = -16,
+ [2][1][RTW89_QATAR][1][42] = 44,
+ [2][1][RTW89_QATAR][0][42] = 6,
+ [2][1][RTW89_UK][1][42] = 44,
+ [2][1][RTW89_UK][0][42] = 6,
+ [2][1][RTW89_FCC][1][44] = -16,
+ [2][1][RTW89_FCC][2][44] = 54,
+ [2][1][RTW89_ETSI][1][44] = 44,
+ [2][1][RTW89_ETSI][0][44] = 6,
+ [2][1][RTW89_MKK][1][44] = 16,
+ [2][1][RTW89_MKK][0][44] = 2,
+ [2][1][RTW89_IC][1][44] = -16,
+ [2][1][RTW89_KCC][1][44] = -14,
+ [2][1][RTW89_KCC][0][44] = -14,
+ [2][1][RTW89_ACMA][1][44] = 44,
+ [2][1][RTW89_ACMA][0][44] = 6,
+ [2][1][RTW89_CHILE][1][44] = -16,
+ [2][1][RTW89_QATAR][1][44] = 44,
+ [2][1][RTW89_QATAR][0][44] = 6,
+ [2][1][RTW89_UK][1][44] = 44,
+ [2][1][RTW89_UK][0][44] = 6,
+ [2][1][RTW89_FCC][1][45] = -16,
+ [2][1][RTW89_FCC][2][45] = 127,
+ [2][1][RTW89_ETSI][1][45] = 127,
+ [2][1][RTW89_ETSI][0][45] = 127,
+ [2][1][RTW89_MKK][1][45] = 127,
+ [2][1][RTW89_MKK][0][45] = 127,
+ [2][1][RTW89_IC][1][45] = -16,
+ [2][1][RTW89_KCC][1][45] = -14,
+ [2][1][RTW89_KCC][0][45] = 127,
+ [2][1][RTW89_ACMA][1][45] = 127,
+ [2][1][RTW89_ACMA][0][45] = 127,
+ [2][1][RTW89_CHILE][1][45] = 127,
+ [2][1][RTW89_QATAR][1][45] = 127,
+ [2][1][RTW89_QATAR][0][45] = 127,
+ [2][1][RTW89_UK][1][45] = 127,
+ [2][1][RTW89_UK][0][45] = 127,
+ [2][1][RTW89_FCC][1][47] = -16,
+ [2][1][RTW89_FCC][2][47] = 127,
+ [2][1][RTW89_ETSI][1][47] = 127,
+ [2][1][RTW89_ETSI][0][47] = 127,
+ [2][1][RTW89_MKK][1][47] = 127,
+ [2][1][RTW89_MKK][0][47] = 127,
+ [2][1][RTW89_IC][1][47] = -16,
+ [2][1][RTW89_KCC][1][47] = -14,
+ [2][1][RTW89_KCC][0][47] = 127,
+ [2][1][RTW89_ACMA][1][47] = 127,
+ [2][1][RTW89_ACMA][0][47] = 127,
+ [2][1][RTW89_CHILE][1][47] = 127,
+ [2][1][RTW89_QATAR][1][47] = 127,
+ [2][1][RTW89_QATAR][0][47] = 127,
+ [2][1][RTW89_UK][1][47] = 127,
+ [2][1][RTW89_UK][0][47] = 127,
+ [2][1][RTW89_FCC][1][49] = -16,
+ [2][1][RTW89_FCC][2][49] = 127,
+ [2][1][RTW89_ETSI][1][49] = 127,
+ [2][1][RTW89_ETSI][0][49] = 127,
+ [2][1][RTW89_MKK][1][49] = 127,
+ [2][1][RTW89_MKK][0][49] = 127,
+ [2][1][RTW89_IC][1][49] = -16,
+ [2][1][RTW89_KCC][1][49] = -14,
+ [2][1][RTW89_KCC][0][49] = 127,
+ [2][1][RTW89_ACMA][1][49] = 127,
+ [2][1][RTW89_ACMA][0][49] = 127,
+ [2][1][RTW89_CHILE][1][49] = 127,
+ [2][1][RTW89_QATAR][1][49] = 127,
+ [2][1][RTW89_QATAR][0][49] = 127,
+ [2][1][RTW89_UK][1][49] = 127,
+ [2][1][RTW89_UK][0][49] = 127,
+ [2][1][RTW89_FCC][1][51] = -16,
+ [2][1][RTW89_FCC][2][51] = 127,
+ [2][1][RTW89_ETSI][1][51] = 127,
+ [2][1][RTW89_ETSI][0][51] = 127,
+ [2][1][RTW89_MKK][1][51] = 127,
+ [2][1][RTW89_MKK][0][51] = 127,
+ [2][1][RTW89_IC][1][51] = -16,
+ [2][1][RTW89_KCC][1][51] = -14,
+ [2][1][RTW89_KCC][0][51] = 127,
+ [2][1][RTW89_ACMA][1][51] = 127,
+ [2][1][RTW89_ACMA][0][51] = 127,
+ [2][1][RTW89_CHILE][1][51] = 127,
+ [2][1][RTW89_QATAR][1][51] = 127,
+ [2][1][RTW89_QATAR][0][51] = 127,
+ [2][1][RTW89_UK][1][51] = 127,
+ [2][1][RTW89_UK][0][51] = 127,
+ [2][1][RTW89_FCC][1][53] = -16,
+ [2][1][RTW89_FCC][2][53] = 127,
+ [2][1][RTW89_ETSI][1][53] = 127,
+ [2][1][RTW89_ETSI][0][53] = 127,
+ [2][1][RTW89_MKK][1][53] = 127,
+ [2][1][RTW89_MKK][0][53] = 127,
+ [2][1][RTW89_IC][1][53] = -16,
+ [2][1][RTW89_KCC][1][53] = -14,
+ [2][1][RTW89_KCC][0][53] = 127,
+ [2][1][RTW89_ACMA][1][53] = 127,
+ [2][1][RTW89_ACMA][0][53] = 127,
+ [2][1][RTW89_CHILE][1][53] = 127,
+ [2][1][RTW89_QATAR][1][53] = 127,
+ [2][1][RTW89_QATAR][0][53] = 127,
+ [2][1][RTW89_UK][1][53] = 127,
+ [2][1][RTW89_UK][0][53] = 127,
+ [2][1][RTW89_FCC][1][55] = -16,
+ [2][1][RTW89_FCC][2][55] = 54,
+ [2][1][RTW89_ETSI][1][55] = 127,
+ [2][1][RTW89_ETSI][0][55] = 127,
+ [2][1][RTW89_MKK][1][55] = 127,
+ [2][1][RTW89_MKK][0][55] = 127,
+ [2][1][RTW89_IC][1][55] = -16,
+ [2][1][RTW89_KCC][1][55] = -14,
+ [2][1][RTW89_KCC][0][55] = 127,
+ [2][1][RTW89_ACMA][1][55] = 127,
+ [2][1][RTW89_ACMA][0][55] = 127,
+ [2][1][RTW89_CHILE][1][55] = 127,
+ [2][1][RTW89_QATAR][1][55] = 127,
+ [2][1][RTW89_QATAR][0][55] = 127,
+ [2][1][RTW89_UK][1][55] = 127,
+ [2][1][RTW89_UK][0][55] = 127,
+ [2][1][RTW89_FCC][1][57] = -16,
+ [2][1][RTW89_FCC][2][57] = 54,
+ [2][1][RTW89_ETSI][1][57] = 127,
+ [2][1][RTW89_ETSI][0][57] = 127,
+ [2][1][RTW89_MKK][1][57] = 127,
+ [2][1][RTW89_MKK][0][57] = 127,
+ [2][1][RTW89_IC][1][57] = -16,
+ [2][1][RTW89_KCC][1][57] = -14,
+ [2][1][RTW89_KCC][0][57] = 127,
+ [2][1][RTW89_ACMA][1][57] = 127,
+ [2][1][RTW89_ACMA][0][57] = 127,
+ [2][1][RTW89_CHILE][1][57] = 127,
+ [2][1][RTW89_QATAR][1][57] = 127,
+ [2][1][RTW89_QATAR][0][57] = 127,
+ [2][1][RTW89_UK][1][57] = 127,
+ [2][1][RTW89_UK][0][57] = 127,
+ [2][1][RTW89_FCC][1][59] = -16,
+ [2][1][RTW89_FCC][2][59] = 54,
+ [2][1][RTW89_ETSI][1][59] = 127,
+ [2][1][RTW89_ETSI][0][59] = 127,
+ [2][1][RTW89_MKK][1][59] = 127,
+ [2][1][RTW89_MKK][0][59] = 127,
+ [2][1][RTW89_IC][1][59] = -16,
+ [2][1][RTW89_KCC][1][59] = -14,
+ [2][1][RTW89_KCC][0][59] = 127,
+ [2][1][RTW89_ACMA][1][59] = 127,
+ [2][1][RTW89_ACMA][0][59] = 127,
+ [2][1][RTW89_CHILE][1][59] = 127,
+ [2][1][RTW89_QATAR][1][59] = 127,
+ [2][1][RTW89_QATAR][0][59] = 127,
+ [2][1][RTW89_UK][1][59] = 127,
+ [2][1][RTW89_UK][0][59] = 127,
+ [2][1][RTW89_FCC][1][60] = -16,
+ [2][1][RTW89_FCC][2][60] = 54,
+ [2][1][RTW89_ETSI][1][60] = 127,
+ [2][1][RTW89_ETSI][0][60] = 127,
+ [2][1][RTW89_MKK][1][60] = 127,
+ [2][1][RTW89_MKK][0][60] = 127,
+ [2][1][RTW89_IC][1][60] = -16,
+ [2][1][RTW89_KCC][1][60] = -14,
+ [2][1][RTW89_KCC][0][60] = 127,
+ [2][1][RTW89_ACMA][1][60] = 127,
+ [2][1][RTW89_ACMA][0][60] = 127,
+ [2][1][RTW89_CHILE][1][60] = 127,
+ [2][1][RTW89_QATAR][1][60] = 127,
+ [2][1][RTW89_QATAR][0][60] = 127,
+ [2][1][RTW89_UK][1][60] = 127,
+ [2][1][RTW89_UK][0][60] = 127,
+ [2][1][RTW89_FCC][1][62] = -16,
+ [2][1][RTW89_FCC][2][62] = 54,
+ [2][1][RTW89_ETSI][1][62] = 127,
+ [2][1][RTW89_ETSI][0][62] = 127,
+ [2][1][RTW89_MKK][1][62] = 127,
+ [2][1][RTW89_MKK][0][62] = 127,
+ [2][1][RTW89_IC][1][62] = -16,
+ [2][1][RTW89_KCC][1][62] = -14,
+ [2][1][RTW89_KCC][0][62] = 127,
+ [2][1][RTW89_ACMA][1][62] = 127,
+ [2][1][RTW89_ACMA][0][62] = 127,
+ [2][1][RTW89_CHILE][1][62] = 127,
+ [2][1][RTW89_QATAR][1][62] = 127,
+ [2][1][RTW89_QATAR][0][62] = 127,
+ [2][1][RTW89_UK][1][62] = 127,
+ [2][1][RTW89_UK][0][62] = 127,
+ [2][1][RTW89_FCC][1][64] = -16,
+ [2][1][RTW89_FCC][2][64] = 54,
+ [2][1][RTW89_ETSI][1][64] = 127,
+ [2][1][RTW89_ETSI][0][64] = 127,
+ [2][1][RTW89_MKK][1][64] = 127,
+ [2][1][RTW89_MKK][0][64] = 127,
+ [2][1][RTW89_IC][1][64] = -16,
+ [2][1][RTW89_KCC][1][64] = -14,
+ [2][1][RTW89_KCC][0][64] = 127,
+ [2][1][RTW89_ACMA][1][64] = 127,
+ [2][1][RTW89_ACMA][0][64] = 127,
+ [2][1][RTW89_CHILE][1][64] = 127,
+ [2][1][RTW89_QATAR][1][64] = 127,
+ [2][1][RTW89_QATAR][0][64] = 127,
+ [2][1][RTW89_UK][1][64] = 127,
+ [2][1][RTW89_UK][0][64] = 127,
+ [2][1][RTW89_FCC][1][66] = -16,
+ [2][1][RTW89_FCC][2][66] = 54,
+ [2][1][RTW89_ETSI][1][66] = 127,
+ [2][1][RTW89_ETSI][0][66] = 127,
+ [2][1][RTW89_MKK][1][66] = 127,
+ [2][1][RTW89_MKK][0][66] = 127,
+ [2][1][RTW89_IC][1][66] = -16,
+ [2][1][RTW89_KCC][1][66] = -14,
+ [2][1][RTW89_KCC][0][66] = 127,
+ [2][1][RTW89_ACMA][1][66] = 127,
+ [2][1][RTW89_ACMA][0][66] = 127,
+ [2][1][RTW89_CHILE][1][66] = 127,
+ [2][1][RTW89_QATAR][1][66] = 127,
+ [2][1][RTW89_QATAR][0][66] = 127,
+ [2][1][RTW89_UK][1][66] = 127,
+ [2][1][RTW89_UK][0][66] = 127,
+ [2][1][RTW89_FCC][1][68] = -16,
+ [2][1][RTW89_FCC][2][68] = 54,
+ [2][1][RTW89_ETSI][1][68] = 127,
+ [2][1][RTW89_ETSI][0][68] = 127,
+ [2][1][RTW89_MKK][1][68] = 127,
+ [2][1][RTW89_MKK][0][68] = 127,
+ [2][1][RTW89_IC][1][68] = -16,
+ [2][1][RTW89_KCC][1][68] = -14,
+ [2][1][RTW89_KCC][0][68] = 127,
+ [2][1][RTW89_ACMA][1][68] = 127,
+ [2][1][RTW89_ACMA][0][68] = 127,
+ [2][1][RTW89_CHILE][1][68] = 127,
+ [2][1][RTW89_QATAR][1][68] = 127,
+ [2][1][RTW89_QATAR][0][68] = 127,
+ [2][1][RTW89_UK][1][68] = 127,
+ [2][1][RTW89_UK][0][68] = 127,
+ [2][1][RTW89_FCC][1][70] = -16,
+ [2][1][RTW89_FCC][2][70] = 56,
+ [2][1][RTW89_ETSI][1][70] = 127,
+ [2][1][RTW89_ETSI][0][70] = 127,
+ [2][1][RTW89_MKK][1][70] = 127,
+ [2][1][RTW89_MKK][0][70] = 127,
+ [2][1][RTW89_IC][1][70] = -16,
+ [2][1][RTW89_KCC][1][70] = -14,
+ [2][1][RTW89_KCC][0][70] = 127,
+ [2][1][RTW89_ACMA][1][70] = 127,
+ [2][1][RTW89_ACMA][0][70] = 127,
+ [2][1][RTW89_CHILE][1][70] = 127,
+ [2][1][RTW89_QATAR][1][70] = 127,
+ [2][1][RTW89_QATAR][0][70] = 127,
+ [2][1][RTW89_UK][1][70] = 127,
+ [2][1][RTW89_UK][0][70] = 127,
+ [2][1][RTW89_FCC][1][72] = -16,
+ [2][1][RTW89_FCC][2][72] = 56,
+ [2][1][RTW89_ETSI][1][72] = 127,
+ [2][1][RTW89_ETSI][0][72] = 127,
+ [2][1][RTW89_MKK][1][72] = 127,
+ [2][1][RTW89_MKK][0][72] = 127,
+ [2][1][RTW89_IC][1][72] = -16,
+ [2][1][RTW89_KCC][1][72] = -14,
+ [2][1][RTW89_KCC][0][72] = 127,
+ [2][1][RTW89_ACMA][1][72] = 127,
+ [2][1][RTW89_ACMA][0][72] = 127,
+ [2][1][RTW89_CHILE][1][72] = 127,
+ [2][1][RTW89_QATAR][1][72] = 127,
+ [2][1][RTW89_QATAR][0][72] = 127,
+ [2][1][RTW89_UK][1][72] = 127,
+ [2][1][RTW89_UK][0][72] = 127,
+ [2][1][RTW89_FCC][1][74] = -16,
+ [2][1][RTW89_FCC][2][74] = 56,
+ [2][1][RTW89_ETSI][1][74] = 127,
+ [2][1][RTW89_ETSI][0][74] = 127,
+ [2][1][RTW89_MKK][1][74] = 127,
+ [2][1][RTW89_MKK][0][74] = 127,
+ [2][1][RTW89_IC][1][74] = -16,
+ [2][1][RTW89_KCC][1][74] = -14,
+ [2][1][RTW89_KCC][0][74] = 127,
+ [2][1][RTW89_ACMA][1][74] = 127,
+ [2][1][RTW89_ACMA][0][74] = 127,
+ [2][1][RTW89_CHILE][1][74] = 127,
+ [2][1][RTW89_QATAR][1][74] = 127,
+ [2][1][RTW89_QATAR][0][74] = 127,
+ [2][1][RTW89_UK][1][74] = 127,
+ [2][1][RTW89_UK][0][74] = 127,
+ [2][1][RTW89_FCC][1][75] = -16,
+ [2][1][RTW89_FCC][2][75] = 56,
+ [2][1][RTW89_ETSI][1][75] = 127,
+ [2][1][RTW89_ETSI][0][75] = 127,
+ [2][1][RTW89_MKK][1][75] = 127,
+ [2][1][RTW89_MKK][0][75] = 127,
+ [2][1][RTW89_IC][1][75] = -16,
+ [2][1][RTW89_KCC][1][75] = -14,
+ [2][1][RTW89_KCC][0][75] = 127,
+ [2][1][RTW89_ACMA][1][75] = 127,
+ [2][1][RTW89_ACMA][0][75] = 127,
+ [2][1][RTW89_CHILE][1][75] = 127,
+ [2][1][RTW89_QATAR][1][75] = 127,
+ [2][1][RTW89_QATAR][0][75] = 127,
+ [2][1][RTW89_UK][1][75] = 127,
+ [2][1][RTW89_UK][0][75] = 127,
+ [2][1][RTW89_FCC][1][77] = -16,
+ [2][1][RTW89_FCC][2][77] = 56,
+ [2][1][RTW89_ETSI][1][77] = 127,
+ [2][1][RTW89_ETSI][0][77] = 127,
+ [2][1][RTW89_MKK][1][77] = 127,
+ [2][1][RTW89_MKK][0][77] = 127,
+ [2][1][RTW89_IC][1][77] = -16,
+ [2][1][RTW89_KCC][1][77] = -14,
+ [2][1][RTW89_KCC][0][77] = 127,
+ [2][1][RTW89_ACMA][1][77] = 127,
+ [2][1][RTW89_ACMA][0][77] = 127,
+ [2][1][RTW89_CHILE][1][77] = 127,
+ [2][1][RTW89_QATAR][1][77] = 127,
+ [2][1][RTW89_QATAR][0][77] = 127,
+ [2][1][RTW89_UK][1][77] = 127,
+ [2][1][RTW89_UK][0][77] = 127,
+ [2][1][RTW89_FCC][1][79] = -16,
+ [2][1][RTW89_FCC][2][79] = 56,
+ [2][1][RTW89_ETSI][1][79] = 127,
+ [2][1][RTW89_ETSI][0][79] = 127,
+ [2][1][RTW89_MKK][1][79] = 127,
+ [2][1][RTW89_MKK][0][79] = 127,
+ [2][1][RTW89_IC][1][79] = -16,
+ [2][1][RTW89_KCC][1][79] = -14,
+ [2][1][RTW89_KCC][0][79] = 127,
+ [2][1][RTW89_ACMA][1][79] = 127,
+ [2][1][RTW89_ACMA][0][79] = 127,
+ [2][1][RTW89_CHILE][1][79] = 127,
+ [2][1][RTW89_QATAR][1][79] = 127,
+ [2][1][RTW89_QATAR][0][79] = 127,
+ [2][1][RTW89_UK][1][79] = 127,
+ [2][1][RTW89_UK][0][79] = 127,
+ [2][1][RTW89_FCC][1][81] = -16,
+ [2][1][RTW89_FCC][2][81] = 56,
+ [2][1][RTW89_ETSI][1][81] = 127,
+ [2][1][RTW89_ETSI][0][81] = 127,
+ [2][1][RTW89_MKK][1][81] = 127,
+ [2][1][RTW89_MKK][0][81] = 127,
+ [2][1][RTW89_IC][1][81] = -16,
+ [2][1][RTW89_KCC][1][81] = -14,
+ [2][1][RTW89_KCC][0][81] = 127,
+ [2][1][RTW89_ACMA][1][81] = 127,
+ [2][1][RTW89_ACMA][0][81] = 127,
+ [2][1][RTW89_CHILE][1][81] = 127,
+ [2][1][RTW89_QATAR][1][81] = 127,
+ [2][1][RTW89_QATAR][0][81] = 127,
+ [2][1][RTW89_UK][1][81] = 127,
+ [2][1][RTW89_UK][0][81] = 127,
+ [2][1][RTW89_FCC][1][83] = -16,
+ [2][1][RTW89_FCC][2][83] = 56,
+ [2][1][RTW89_ETSI][1][83] = 127,
+ [2][1][RTW89_ETSI][0][83] = 127,
+ [2][1][RTW89_MKK][1][83] = 127,
+ [2][1][RTW89_MKK][0][83] = 127,
+ [2][1][RTW89_IC][1][83] = -16,
+ [2][1][RTW89_KCC][1][83] = -14,
+ [2][1][RTW89_KCC][0][83] = 127,
+ [2][1][RTW89_ACMA][1][83] = 127,
+ [2][1][RTW89_ACMA][0][83] = 127,
+ [2][1][RTW89_CHILE][1][83] = 127,
+ [2][1][RTW89_QATAR][1][83] = 127,
+ [2][1][RTW89_QATAR][0][83] = 127,
+ [2][1][RTW89_UK][1][83] = 127,
+ [2][1][RTW89_UK][0][83] = 127,
+ [2][1][RTW89_FCC][1][85] = -18,
+ [2][1][RTW89_FCC][2][85] = 56,
+ [2][1][RTW89_ETSI][1][85] = 127,
+ [2][1][RTW89_ETSI][0][85] = 127,
+ [2][1][RTW89_MKK][1][85] = 127,
+ [2][1][RTW89_MKK][0][85] = 127,
+ [2][1][RTW89_IC][1][85] = -18,
+ [2][1][RTW89_KCC][1][85] = -14,
+ [2][1][RTW89_KCC][0][85] = 127,
+ [2][1][RTW89_ACMA][1][85] = 127,
+ [2][1][RTW89_ACMA][0][85] = 127,
+ [2][1][RTW89_CHILE][1][85] = 127,
+ [2][1][RTW89_QATAR][1][85] = 127,
+ [2][1][RTW89_QATAR][0][85] = 127,
+ [2][1][RTW89_UK][1][85] = 127,
+ [2][1][RTW89_UK][0][85] = 127,
+ [2][1][RTW89_FCC][1][87] = -16,
+ [2][1][RTW89_FCC][2][87] = 127,
+ [2][1][RTW89_ETSI][1][87] = 127,
+ [2][1][RTW89_ETSI][0][87] = 127,
+ [2][1][RTW89_MKK][1][87] = 127,
+ [2][1][RTW89_MKK][0][87] = 127,
+ [2][1][RTW89_IC][1][87] = -16,
+ [2][1][RTW89_KCC][1][87] = -14,
+ [2][1][RTW89_KCC][0][87] = 127,
+ [2][1][RTW89_ACMA][1][87] = 127,
+ [2][1][RTW89_ACMA][0][87] = 127,
+ [2][1][RTW89_CHILE][1][87] = 127,
+ [2][1][RTW89_QATAR][1][87] = 127,
+ [2][1][RTW89_QATAR][0][87] = 127,
+ [2][1][RTW89_UK][1][87] = 127,
+ [2][1][RTW89_UK][0][87] = 127,
+ [2][1][RTW89_FCC][1][89] = -16,
+ [2][1][RTW89_FCC][2][89] = 127,
+ [2][1][RTW89_ETSI][1][89] = 127,
+ [2][1][RTW89_ETSI][0][89] = 127,
+ [2][1][RTW89_MKK][1][89] = 127,
+ [2][1][RTW89_MKK][0][89] = 127,
+ [2][1][RTW89_IC][1][89] = -16,
+ [2][1][RTW89_KCC][1][89] = -14,
+ [2][1][RTW89_KCC][0][89] = 127,
+ [2][1][RTW89_ACMA][1][89] = 127,
+ [2][1][RTW89_ACMA][0][89] = 127,
+ [2][1][RTW89_CHILE][1][89] = 127,
+ [2][1][RTW89_QATAR][1][89] = 127,
+ [2][1][RTW89_QATAR][0][89] = 127,
+ [2][1][RTW89_UK][1][89] = 127,
+ [2][1][RTW89_UK][0][89] = 127,
+ [2][1][RTW89_FCC][1][90] = -16,
+ [2][1][RTW89_FCC][2][90] = 127,
+ [2][1][RTW89_ETSI][1][90] = 127,
+ [2][1][RTW89_ETSI][0][90] = 127,
+ [2][1][RTW89_MKK][1][90] = 127,
+ [2][1][RTW89_MKK][0][90] = 127,
+ [2][1][RTW89_IC][1][90] = -16,
+ [2][1][RTW89_KCC][1][90] = -14,
+ [2][1][RTW89_KCC][0][90] = 127,
+ [2][1][RTW89_ACMA][1][90] = 127,
+ [2][1][RTW89_ACMA][0][90] = 127,
+ [2][1][RTW89_CHILE][1][90] = 127,
+ [2][1][RTW89_QATAR][1][90] = 127,
+ [2][1][RTW89_QATAR][0][90] = 127,
+ [2][1][RTW89_UK][1][90] = 127,
+ [2][1][RTW89_UK][0][90] = 127,
+ [2][1][RTW89_FCC][1][92] = -16,
+ [2][1][RTW89_FCC][2][92] = 127,
+ [2][1][RTW89_ETSI][1][92] = 127,
+ [2][1][RTW89_ETSI][0][92] = 127,
+ [2][1][RTW89_MKK][1][92] = 127,
+ [2][1][RTW89_MKK][0][92] = 127,
+ [2][1][RTW89_IC][1][92] = -16,
+ [2][1][RTW89_KCC][1][92] = -14,
+ [2][1][RTW89_KCC][0][92] = 127,
+ [2][1][RTW89_ACMA][1][92] = 127,
+ [2][1][RTW89_ACMA][0][92] = 127,
+ [2][1][RTW89_CHILE][1][92] = 127,
+ [2][1][RTW89_QATAR][1][92] = 127,
+ [2][1][RTW89_QATAR][0][92] = 127,
+ [2][1][RTW89_UK][1][92] = 127,
+ [2][1][RTW89_UK][0][92] = 127,
+ [2][1][RTW89_FCC][1][94] = -16,
+ [2][1][RTW89_FCC][2][94] = 127,
+ [2][1][RTW89_ETSI][1][94] = 127,
+ [2][1][RTW89_ETSI][0][94] = 127,
+ [2][1][RTW89_MKK][1][94] = 127,
+ [2][1][RTW89_MKK][0][94] = 127,
+ [2][1][RTW89_IC][1][94] = -16,
+ [2][1][RTW89_KCC][1][94] = -14,
+ [2][1][RTW89_KCC][0][94] = 127,
+ [2][1][RTW89_ACMA][1][94] = 127,
+ [2][1][RTW89_ACMA][0][94] = 127,
+ [2][1][RTW89_CHILE][1][94] = 127,
+ [2][1][RTW89_QATAR][1][94] = 127,
+ [2][1][RTW89_QATAR][0][94] = 127,
+ [2][1][RTW89_UK][1][94] = 127,
+ [2][1][RTW89_UK][0][94] = 127,
+ [2][1][RTW89_FCC][1][96] = -16,
+ [2][1][RTW89_FCC][2][96] = 127,
+ [2][1][RTW89_ETSI][1][96] = 127,
+ [2][1][RTW89_ETSI][0][96] = 127,
+ [2][1][RTW89_MKK][1][96] = 127,
+ [2][1][RTW89_MKK][0][96] = 127,
+ [2][1][RTW89_IC][1][96] = -16,
+ [2][1][RTW89_KCC][1][96] = -14,
+ [2][1][RTW89_KCC][0][96] = 127,
+ [2][1][RTW89_ACMA][1][96] = 127,
+ [2][1][RTW89_ACMA][0][96] = 127,
+ [2][1][RTW89_CHILE][1][96] = 127,
+ [2][1][RTW89_QATAR][1][96] = 127,
+ [2][1][RTW89_QATAR][0][96] = 127,
+ [2][1][RTW89_UK][1][96] = 127,
+ [2][1][RTW89_UK][0][96] = 127,
+ [2][1][RTW89_FCC][1][98] = -16,
+ [2][1][RTW89_FCC][2][98] = 127,
+ [2][1][RTW89_ETSI][1][98] = 127,
+ [2][1][RTW89_ETSI][0][98] = 127,
+ [2][1][RTW89_MKK][1][98] = 127,
+ [2][1][RTW89_MKK][0][98] = 127,
+ [2][1][RTW89_IC][1][98] = -16,
+ [2][1][RTW89_KCC][1][98] = -14,
+ [2][1][RTW89_KCC][0][98] = 127,
+ [2][1][RTW89_ACMA][1][98] = 127,
+ [2][1][RTW89_ACMA][0][98] = 127,
+ [2][1][RTW89_CHILE][1][98] = 127,
+ [2][1][RTW89_QATAR][1][98] = 127,
+ [2][1][RTW89_QATAR][0][98] = 127,
+ [2][1][RTW89_UK][1][98] = 127,
+ [2][1][RTW89_UK][0][98] = 127,
+ [2][1][RTW89_FCC][1][100] = -16,
+ [2][1][RTW89_FCC][2][100] = 127,
+ [2][1][RTW89_ETSI][1][100] = 127,
+ [2][1][RTW89_ETSI][0][100] = 127,
+ [2][1][RTW89_MKK][1][100] = 127,
+ [2][1][RTW89_MKK][0][100] = 127,
+ [2][1][RTW89_IC][1][100] = -16,
+ [2][1][RTW89_KCC][1][100] = -14,
+ [2][1][RTW89_KCC][0][100] = 127,
+ [2][1][RTW89_ACMA][1][100] = 127,
+ [2][1][RTW89_ACMA][0][100] = 127,
+ [2][1][RTW89_CHILE][1][100] = 127,
+ [2][1][RTW89_QATAR][1][100] = 127,
+ [2][1][RTW89_QATAR][0][100] = 127,
+ [2][1][RTW89_UK][1][100] = 127,
+ [2][1][RTW89_UK][0][100] = 127,
+ [2][1][RTW89_FCC][1][102] = -16,
+ [2][1][RTW89_FCC][2][102] = 127,
+ [2][1][RTW89_ETSI][1][102] = 127,
+ [2][1][RTW89_ETSI][0][102] = 127,
+ [2][1][RTW89_MKK][1][102] = 127,
+ [2][1][RTW89_MKK][0][102] = 127,
+ [2][1][RTW89_IC][1][102] = -16,
+ [2][1][RTW89_KCC][1][102] = -14,
+ [2][1][RTW89_KCC][0][102] = 127,
+ [2][1][RTW89_ACMA][1][102] = 127,
+ [2][1][RTW89_ACMA][0][102] = 127,
+ [2][1][RTW89_CHILE][1][102] = 127,
+ [2][1][RTW89_QATAR][1][102] = 127,
+ [2][1][RTW89_QATAR][0][102] = 127,
+ [2][1][RTW89_UK][1][102] = 127,
+ [2][1][RTW89_UK][0][102] = 127,
+ [2][1][RTW89_FCC][1][104] = -16,
+ [2][1][RTW89_FCC][2][104] = 127,
+ [2][1][RTW89_ETSI][1][104] = 127,
+ [2][1][RTW89_ETSI][0][104] = 127,
+ [2][1][RTW89_MKK][1][104] = 127,
+ [2][1][RTW89_MKK][0][104] = 127,
+ [2][1][RTW89_IC][1][104] = -16,
+ [2][1][RTW89_KCC][1][104] = -14,
+ [2][1][RTW89_KCC][0][104] = 127,
+ [2][1][RTW89_ACMA][1][104] = 127,
+ [2][1][RTW89_ACMA][0][104] = 127,
+ [2][1][RTW89_CHILE][1][104] = 127,
+ [2][1][RTW89_QATAR][1][104] = 127,
+ [2][1][RTW89_QATAR][0][104] = 127,
+ [2][1][RTW89_UK][1][104] = 127,
+ [2][1][RTW89_UK][0][104] = 127,
+ [2][1][RTW89_FCC][1][105] = -16,
+ [2][1][RTW89_FCC][2][105] = 127,
+ [2][1][RTW89_ETSI][1][105] = 127,
+ [2][1][RTW89_ETSI][0][105] = 127,
+ [2][1][RTW89_MKK][1][105] = 127,
+ [2][1][RTW89_MKK][0][105] = 127,
+ [2][1][RTW89_IC][1][105] = -16,
+ [2][1][RTW89_KCC][1][105] = -14,
+ [2][1][RTW89_KCC][0][105] = 127,
+ [2][1][RTW89_ACMA][1][105] = 127,
+ [2][1][RTW89_ACMA][0][105] = 127,
+ [2][1][RTW89_CHILE][1][105] = 127,
+ [2][1][RTW89_QATAR][1][105] = 127,
+ [2][1][RTW89_QATAR][0][105] = 127,
+ [2][1][RTW89_UK][1][105] = 127,
+ [2][1][RTW89_UK][0][105] = 127,
+ [2][1][RTW89_FCC][1][107] = -12,
+ [2][1][RTW89_FCC][2][107] = 127,
+ [2][1][RTW89_ETSI][1][107] = 127,
+ [2][1][RTW89_ETSI][0][107] = 127,
+ [2][1][RTW89_MKK][1][107] = 127,
+ [2][1][RTW89_MKK][0][107] = 127,
+ [2][1][RTW89_IC][1][107] = -12,
+ [2][1][RTW89_KCC][1][107] = -14,
+ [2][1][RTW89_KCC][0][107] = 127,
+ [2][1][RTW89_ACMA][1][107] = 127,
+ [2][1][RTW89_ACMA][0][107] = 127,
+ [2][1][RTW89_CHILE][1][107] = 127,
+ [2][1][RTW89_QATAR][1][107] = 127,
+ [2][1][RTW89_QATAR][0][107] = 127,
+ [2][1][RTW89_UK][1][107] = 127,
+ [2][1][RTW89_UK][0][107] = 127,
+ [2][1][RTW89_FCC][1][109] = -10,
+ [2][1][RTW89_FCC][2][109] = 127,
+ [2][1][RTW89_ETSI][1][109] = 127,
+ [2][1][RTW89_ETSI][0][109] = 127,
+ [2][1][RTW89_MKK][1][109] = 127,
+ [2][1][RTW89_MKK][0][109] = 127,
+ [2][1][RTW89_IC][1][109] = -10,
+ [2][1][RTW89_KCC][1][109] = 127,
+ [2][1][RTW89_KCC][0][109] = 127,
+ [2][1][RTW89_ACMA][1][109] = 127,
+ [2][1][RTW89_ACMA][0][109] = 127,
+ [2][1][RTW89_CHILE][1][109] = 127,
+ [2][1][RTW89_QATAR][1][109] = 127,
+ [2][1][RTW89_QATAR][0][109] = 127,
+ [2][1][RTW89_UK][1][109] = 127,
+ [2][1][RTW89_UK][0][109] = 127,
+ [2][1][RTW89_FCC][1][111] = 127,
+ [2][1][RTW89_FCC][2][111] = 127,
+ [2][1][RTW89_ETSI][1][111] = 127,
+ [2][1][RTW89_ETSI][0][111] = 127,
+ [2][1][RTW89_MKK][1][111] = 127,
+ [2][1][RTW89_MKK][0][111] = 127,
+ [2][1][RTW89_IC][1][111] = 127,
+ [2][1][RTW89_KCC][1][111] = 127,
+ [2][1][RTW89_KCC][0][111] = 127,
+ [2][1][RTW89_ACMA][1][111] = 127,
+ [2][1][RTW89_ACMA][0][111] = 127,
+ [2][1][RTW89_CHILE][1][111] = 127,
+ [2][1][RTW89_QATAR][1][111] = 127,
+ [2][1][RTW89_QATAR][0][111] = 127,
+ [2][1][RTW89_UK][1][111] = 127,
+ [2][1][RTW89_UK][0][111] = 127,
+ [2][1][RTW89_FCC][1][113] = 127,
+ [2][1][RTW89_FCC][2][113] = 127,
+ [2][1][RTW89_ETSI][1][113] = 127,
+ [2][1][RTW89_ETSI][0][113] = 127,
+ [2][1][RTW89_MKK][1][113] = 127,
+ [2][1][RTW89_MKK][0][113] = 127,
+ [2][1][RTW89_IC][1][113] = 127,
+ [2][1][RTW89_KCC][1][113] = 127,
+ [2][1][RTW89_KCC][0][113] = 127,
+ [2][1][RTW89_ACMA][1][113] = 127,
+ [2][1][RTW89_ACMA][0][113] = 127,
+ [2][1][RTW89_CHILE][1][113] = 127,
+ [2][1][RTW89_QATAR][1][113] = 127,
+ [2][1][RTW89_QATAR][0][113] = 127,
+ [2][1][RTW89_UK][1][113] = 127,
+ [2][1][RTW89_UK][0][113] = 127,
+ [2][1][RTW89_FCC][1][115] = 127,
+ [2][1][RTW89_FCC][2][115] = 127,
+ [2][1][RTW89_ETSI][1][115] = 127,
+ [2][1][RTW89_ETSI][0][115] = 127,
+ [2][1][RTW89_MKK][1][115] = 127,
+ [2][1][RTW89_MKK][0][115] = 127,
+ [2][1][RTW89_IC][1][115] = 127,
+ [2][1][RTW89_KCC][1][115] = 127,
+ [2][1][RTW89_KCC][0][115] = 127,
+ [2][1][RTW89_ACMA][1][115] = 127,
+ [2][1][RTW89_ACMA][0][115] = 127,
+ [2][1][RTW89_CHILE][1][115] = 127,
+ [2][1][RTW89_QATAR][1][115] = 127,
+ [2][1][RTW89_QATAR][0][115] = 127,
+ [2][1][RTW89_UK][1][115] = 127,
+ [2][1][RTW89_UK][0][115] = 127,
+ [2][1][RTW89_FCC][1][117] = 127,
+ [2][1][RTW89_FCC][2][117] = 127,
+ [2][1][RTW89_ETSI][1][117] = 127,
+ [2][1][RTW89_ETSI][0][117] = 127,
+ [2][1][RTW89_MKK][1][117] = 127,
+ [2][1][RTW89_MKK][0][117] = 127,
+ [2][1][RTW89_IC][1][117] = 127,
+ [2][1][RTW89_KCC][1][117] = 127,
+ [2][1][RTW89_KCC][0][117] = 127,
+ [2][1][RTW89_ACMA][1][117] = 127,
+ [2][1][RTW89_ACMA][0][117] = 127,
+ [2][1][RTW89_CHILE][1][117] = 127,
+ [2][1][RTW89_QATAR][1][117] = 127,
+ [2][1][RTW89_QATAR][0][117] = 127,
+ [2][1][RTW89_UK][1][117] = 127,
+ [2][1][RTW89_UK][0][117] = 127,
+ [2][1][RTW89_FCC][1][119] = 127,
+ [2][1][RTW89_FCC][2][119] = 127,
+ [2][1][RTW89_ETSI][1][119] = 127,
+ [2][1][RTW89_ETSI][0][119] = 127,
+ [2][1][RTW89_MKK][1][119] = 127,
+ [2][1][RTW89_MKK][0][119] = 127,
+ [2][1][RTW89_IC][1][119] = 127,
+ [2][1][RTW89_KCC][1][119] = 127,
+ [2][1][RTW89_KCC][0][119] = 127,
+ [2][1][RTW89_ACMA][1][119] = 127,
+ [2][1][RTW89_ACMA][0][119] = 127,
+ [2][1][RTW89_CHILE][1][119] = 127,
+ [2][1][RTW89_QATAR][1][119] = 127,
+ [2][1][RTW89_QATAR][0][119] = 127,
+ [2][1][RTW89_UK][1][119] = 127,
+ [2][1][RTW89_UK][0][119] = 127,
};
const struct rtw89_phy_table rtw89_8852c_phy_bb_table = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
index 6da1849fb1fa..3eb0c4995174 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
@@ -15,7 +15,7 @@ extern const struct rtw89_phy_table rtw89_8852c_phy_nctl_table;
extern const struct rtw89_txpwr_table rtw89_8852c_byr_table;
extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table;
extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg;
-extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM]
+extern const u8 rtw89_8852c_tx_shape[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM]
[RTW89_REGD_NUM];
extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms;
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 9e9f6947e7f1..0462ba693f6f 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -20,12 +20,14 @@ enum ser_evt {
SER_EV_NONE,
SER_EV_STATE_IN,
SER_EV_STATE_OUT,
+ SER_EV_L1_RESET_PREPARE, /* pre-M0 */
SER_EV_L1_RESET, /* M1 */
SER_EV_DO_RECOVERY, /* M3 */
SER_EV_MAC_RESET_DONE, /* M5 */
SER_EV_L2_RESET,
SER_EV_L2_RECFG_DONE,
SER_EV_L2_RECFG_TIMEOUT,
+ SER_EV_M1_TIMEOUT,
SER_EV_M3_TIMEOUT,
SER_EV_FW_M5_TIMEOUT,
SER_EV_L0_RESET,
@@ -34,6 +36,7 @@ enum ser_evt {
enum ser_state {
SER_IDLE_ST,
+ SER_L1_RESET_PRE_ST,
SER_RESET_TRX_ST,
SER_DO_HCI_ST,
SER_L2_RESET_ST,
@@ -300,6 +303,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
rtwvif->net_type = RTW89_NET_TYPE_NO_LINK;
rtwvif->trigger = false;
+ rtwvif->tdls_peer = 0;
}
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
@@ -338,6 +342,8 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM);
rtw89_for_each_rtwvif(rtwdev, rtwvif)
ser_reset_vif(rtwdev, rtwvif);
+
+ rtwdev->total_sta_assoc = 0;
}
/* hal function */
@@ -374,6 +380,13 @@ static int hal_stop_dma(struct rtw89_ser *ser)
return ret;
}
+static void hal_send_post_m0_event(struct rtw89_ser *ser)
+{
+ struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
+
+ rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_START_DMAC);
+}
+
static void hal_send_m2_event(struct rtw89_ser *ser)
{
struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
@@ -396,8 +409,12 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
switch (evt) {
case SER_EV_STATE_IN:
rtw89_hci_recovery_complete(rtwdev);
+ clear_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags);
clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
break;
+ case SER_EV_L1_RESET_PREPARE:
+ ser_state_goto(ser, SER_L1_RESET_PRE_ST);
+ break;
case SER_EV_L1_RESET:
ser_state_goto(ser, SER_RESET_TRX_ST);
break;
@@ -405,6 +422,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
ser_state_goto(ser, SER_L2_RESET_ST);
break;
case SER_EV_STATE_OUT:
+ set_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags);
rtw89_hci_recovery_start(rtwdev);
break;
default:
@@ -412,6 +430,28 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
}
}
+static void ser_l1_reset_pre_st_hdl(struct rtw89_ser *ser, u8 evt)
+{
+ switch (evt) {
+ case SER_EV_STATE_IN:
+ ser->prehandle_l1 = true;
+ hal_send_post_m0_event(ser);
+ ser_set_alarm(ser, 1000, SER_EV_M1_TIMEOUT);
+ break;
+ case SER_EV_L1_RESET:
+ ser_state_goto(ser, SER_RESET_TRX_ST);
+ break;
+ case SER_EV_M1_TIMEOUT:
+ ser_state_goto(ser, SER_L2_RESET_ST);
+ break;
+ case SER_EV_STATE_OUT:
+ ser_del_alarm(ser);
+ break;
+ default:
+ break;
+ }
+}
+
static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
{
struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
@@ -654,12 +694,14 @@ static const struct event_ent ser_ev_tbl[] = {
{SER_EV_NONE, "SER_EV_NONE"},
{SER_EV_STATE_IN, "SER_EV_STATE_IN"},
{SER_EV_STATE_OUT, "SER_EV_STATE_OUT"},
- {SER_EV_L1_RESET, "SER_EV_L1_RESET"},
+ {SER_EV_L1_RESET_PREPARE, "SER_EV_L1_RESET_PREPARE pre-m0"},
+ {SER_EV_L1_RESET, "SER_EV_L1_RESET m1"},
{SER_EV_DO_RECOVERY, "SER_EV_DO_RECOVERY m3"},
{SER_EV_MAC_RESET_DONE, "SER_EV_MAC_RESET_DONE m5"},
{SER_EV_L2_RESET, "SER_EV_L2_RESET"},
{SER_EV_L2_RECFG_DONE, "SER_EV_L2_RECFG_DONE"},
{SER_EV_L2_RECFG_TIMEOUT, "SER_EV_L2_RECFG_TIMEOUT"},
+ {SER_EV_M1_TIMEOUT, "SER_EV_M1_TIMEOUT"},
{SER_EV_M3_TIMEOUT, "SER_EV_M3_TIMEOUT"},
{SER_EV_FW_M5_TIMEOUT, "SER_EV_FW_M5_TIMEOUT"},
{SER_EV_L0_RESET, "SER_EV_L0_RESET"},
@@ -668,6 +710,7 @@ static const struct event_ent ser_ev_tbl[] = {
static const struct state_ent ser_st_tbl[] = {
{SER_IDLE_ST, "SER_IDLE_ST", ser_idle_st_hdl},
+ {SER_L1_RESET_PRE_ST, "SER_L1_RESET_PRE_ST", ser_l1_reset_pre_st_hdl},
{SER_RESET_TRX_ST, "SER_RESET_TRX_ST", ser_reset_trx_st_hdl},
{SER_DO_HCI_ST, "SER_DO_HCI_ST", ser_do_hci_st_hdl},
{SER_L2_RESET_ST, "SER_L2_RESET_ST", ser_l2_reset_st_hdl}
@@ -713,6 +756,9 @@ int rtw89_ser_notify(struct rtw89_dev *rtwdev, u32 err)
rtw89_info(rtwdev, "SER catches error: 0x%x\n", err);
switch (err) {
+ case MAC_AX_ERR_L1_PREERR_DMAC: /* pre-M0 */
+ event = SER_EV_L1_RESET_PREPARE;
+ break;
case MAC_AX_ERR_L1_ERR_DMAC:
case MAC_AX_ERR_L0_PROMOTE_TO_L1:
event = SER_EV_L1_RESET; /* M1 */
diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h
index 98eb9607cd21..ec96da36eacc 100644
--- a/drivers/net/wireless/realtek/rtw89/txrx.h
+++ b/drivers/net/wireless/realtek/rtw89/txrx.h
@@ -186,124 +186,64 @@
#define AX_RXD_BIP_KEYID BIT(27)
#define AX_RXD_BIP_ENC BIT(28)
-/* RX DESC helpers */
-/* Short Descriptor */
-#define RTW89_GET_RXWD_LONG_RXD(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(31))
-#define RTW89_GET_RXWD_DRV_INFO_SIZE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(30, 28))
-#define RTW89_GET_RXWD_RPKT_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(27, 24))
-#define RTW89_GET_RXWD_MAC_INFO_VALID(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(23))
-#define RTW89_GET_RXWD_BB_SEL(rxdesc) \
- le32_get_bits((rxdesc)->dword0, BIT(22))
-#define RTW89_GET_RXWD_HD_IV_LEN(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(21, 16))
-#define RTW89_GET_RXWD_SHIFT(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(15, 14))
-#define RTW89_GET_RXWD_PKT_SIZE(rxdesc) \
- le32_get_bits((rxdesc)->dword0, GENMASK(13, 0))
-#define RTW89_GET_RXWD_BW(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(31, 30))
-#define RTW89_GET_RXWD_BW_V1(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(31, 29))
-#define RTW89_GET_RXWD_GI_LTF(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(27, 25))
-#define RTW89_GET_RXWD_DATA_RATE(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(24, 16))
-#define RTW89_GET_RXWD_USER_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(15, 8))
-#define RTW89_GET_RXWD_SR_EN(rxdesc) \
- le32_get_bits((rxdesc)->dword1, BIT(7))
-#define RTW89_GET_RXWD_PPDU_CNT(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(6, 4))
-#define RTW89_GET_RXWD_PPDU_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword1, GENMASK(3, 0))
-#define RTW89_GET_RXWD_FREE_RUN_CNT(rxdesc) \
- le32_get_bits((rxdesc)->dword2, GENMASK(31, 0))
-#define RTW89_GET_RXWD_ICV_ERR(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(10))
-#define RTW89_GET_RXWD_CRC32_ERR(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(9))
-#define RTW89_GET_RXWD_HW_DEC(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(2))
-#define RTW89_GET_RXWD_SW_DEC(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(1))
-#define RTW89_GET_RXWD_A1_MATCH(rxdesc) \
- le32_get_bits((rxdesc)->dword3, BIT(0))
-
-/* Long Descriptor */
-#define RTW89_GET_RXWD_FRAG(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(31, 28))
-#define RTW89_GET_RXWD_SEQ(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(27, 16))
-#define RTW89_GET_RXWD_TYPE(rxdesc) \
- le32_get_bits((rxdesc)->dword4, GENMASK(1, 0))
-#define RTW89_GET_RXWD_ADDR_CAM_VLD(rxdesc) \
- le32_get_bits((rxdesc)->dword5, BIT(28))
-#define RTW89_GET_RXWD_RX_PL_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(27, 24))
-#define RTW89_GET_RXWD_MAC_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(23, 16))
-#define RTW89_GET_RXWD_ADDR_CAM_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(15, 8))
-#define RTW89_GET_RXWD_SEC_CAM_ID(rxdesc) \
- le32_get_bits((rxdesc)->dword5, GENMASK(7, 0))
-
-#define RTW89_GET_RXINFO_USR_NUM(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(3, 0))
-#define RTW89_GET_RXINFO_FW_DEFINE(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(15, 8))
-#define RTW89_GET_RXINFO_LSIG_LEN(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(27, 16))
-#define RTW89_GET_RXINFO_IS_TO_SELF(rpt) \
- le32_get_bits(*((const __le32 *)rpt), BIT(28))
-#define RTW89_GET_RXINFO_RX_CNT_VLD(rpt) \
- le32_get_bits(*((const __le32 *)rpt), BIT(29))
-#define RTW89_GET_RXINFO_LONG_RXD(rpt) \
- le32_get_bits(*((const __le32 *)rpt), GENMASK(31, 30))
-#define RTW89_GET_RXINFO_SERVICE(rpt) \
- le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(15, 0))
-#define RTW89_GET_RXINFO_PLCP_LEN(rpt) \
- le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(23, 16))
-#define RTW89_GET_RXINFO_MAC_ID_VALID(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(0))
-#define RTW89_GET_RXINFO_DATA(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(1))
-#define RTW89_GET_RXINFO_CTRL(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(2))
-#define RTW89_GET_RXINFO_MGMT(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(3))
-#define RTW89_GET_RXINFO_BCM(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(4))
-#define RTW89_GET_RXINFO_MACID(rpt, usr) \
- le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), GENMASK(15, 8))
-
-#define RTW89_GET_PHY_STS_IE_MAP(sts) \
- le32_get_bits(*((const __le32 *)(sts)), GENMASK(4, 0))
-#define RTW89_GET_PHY_STS_RSSI_A(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(7, 0))
-#define RTW89_GET_PHY_STS_RSSI_B(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(15, 8))
-#define RTW89_GET_PHY_STS_RSSI_C(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(23, 16))
-#define RTW89_GET_PHY_STS_RSSI_D(sts) \
- le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(31, 24))
-#define RTW89_GET_PHY_STS_LEN(sts) \
- le32_get_bits(*((const __le32 *)sts), GENMASK(15, 8))
-#define RTW89_GET_PHY_STS_RSSI_AVG(sts) \
- le32_get_bits(*((const __le32 *)sts), GENMASK(31, 24))
-#define RTW89_GET_PHY_STS_IE_TYPE(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(4, 0))
-#define RTW89_GET_PHY_STS_IE_LEN(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(11, 5))
-#define RTW89_GET_PHY_STS_IE01_CH_IDX(ie) \
- le32_get_bits(*((const __le32 *)ie), GENMASK(23, 16))
-#define RTW89_GET_PHY_STS_IE01_FD_CFO(ie) \
- le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(19, 8))
-#define RTW89_GET_PHY_STS_IE01_PREMB_CFO(ie) \
- le32_get_bits(*((const __le32 *)(ie) + 1), GENMASK(31, 20))
+struct rtw89_rxinfo_user {
+ __le32 w0;
+};
+
+#define RTW89_RXINFO_USER_MAC_ID_VALID BIT(0)
+#define RTW89_RXINFO_USER_DATA BIT(1)
+#define RTW89_RXINFO_USER_CTRL BIT(2)
+#define RTW89_RXINFO_USER_MGMT BIT(3)
+#define RTW89_RXINFO_USER_BCM BIT(4)
+#define RTW89_RXINFO_USER_MACID GENMASK(15, 8)
+
+struct rtw89_rxinfo {
+ __le32 w0;
+ __le32 w1;
+ struct rtw89_rxinfo_user user[];
+} __packed;
+
+#define RTW89_RXINFO_W0_USR_NUM GENMASK(3, 0)
+#define RTW89_RXINFO_W0_FW_DEFINE GENMASK(15, 8)
+#define RTW89_RXINFO_W0_LSIG_LEN GENMASK(27, 16)
+#define RTW89_RXINFO_W0_IS_TO_SELF BIT(28)
+#define RTW89_RXINFO_W0_RX_CNT_VLD BIT(29)
+#define RTW89_RXINFO_W0_LONG_RXD GENMASK(31, 30)
+#define RTW89_RXINFO_W1_SERVICE GENMASK(15, 0)
+#define RTW89_RXINFO_W1_PLCP_LEN GENMASK(23, 16)
+
+struct rtw89_phy_sts_hdr {
+ __le32 w0;
+ __le32 w1;
+} __packed;
+
+#define RTW89_PHY_STS_HDR_W0_IE_MAP GENMASK(4, 0)
+#define RTW89_PHY_STS_HDR_W0_LEN GENMASK(15, 8)
+#define RTW89_PHY_STS_HDR_W0_RSSI_AVG GENMASK(31, 24)
+#define RTW89_PHY_STS_HDR_W1_RSSI_A GENMASK(7, 0)
+#define RTW89_PHY_STS_HDR_W1_RSSI_B GENMASK(15, 8)
+#define RTW89_PHY_STS_HDR_W1_RSSI_C GENMASK(23, 16)
+#define RTW89_PHY_STS_HDR_W1_RSSI_D GENMASK(31, 24)
+
+struct rtw89_phy_sts_iehdr {
+ __le32 w0;
+};
+
+#define RTW89_PHY_STS_IEHDR_TYPE GENMASK(4, 0)
+#define RTW89_PHY_STS_IEHDR_LEN GENMASK(11, 5)
+
+struct rtw89_phy_sts_ie0 {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+} __packed;
+
+#define RTW89_PHY_STS_IE01_W0_CH_IDX GENMASK(23, 16)
+#define RTW89_PHY_STS_IE01_W1_FD_CFO GENMASK(19, 8)
+#define RTW89_PHY_STS_IE01_W1_PREMB_CFO GENMASK(31, 20)
+#define RTW89_PHY_STS_IE01_W2_AVG_SNR GENMASK(5, 0)
+#define RTW89_PHY_STS_IE01_W2_EVM_MAX GENMASK(15, 8)
+#define RTW89_PHY_STS_IE01_W2_EVM_MIN GENMASK(23, 16)
enum rtw89_tx_channel {
RTW89_TXCH_ACH0 = 0,
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 2ca8abb70f11..364e54622150 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -91,7 +91,7 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev)
u32 wow_reason_reg;
u8 reason;
- if (chip_id == RTL8852A || chip_id == RTL8852B)
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
wow_reason_reg = R_AX_C2HREG_DATA3 + 3;
else
wow_reason_reg = R_AX_C2HREG_DATA3_V1 + 3;
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index d09998796ac0..1911fef3bbad 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev)
rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n");
- if (hw) {
- struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
-
- if (rsi_config_wowlan(adapter, wowlan))
+ if (hw && hw->wiphy && hw->wiphy->wowlan_config) {
+ if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config))
rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
}
@@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev)
if (sdev->write_fail)
rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
- if (rsi_set_sdio_pm_caps(adapter))
- rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
-
rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
}
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 89c7a1420381..23307c8baea2 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -4,7 +4,7 @@
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2022 Intel Corporation
+ * Copyright (C) 2018 - 2023 Intel Corporation
*/
/*
@@ -1859,12 +1859,12 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
int i;
- if (!vif->valid_links)
+ if (!ieee80211_vif_is_mld(vif))
return &vif->bss_conf;
WARN_ON(is_multicast_ether_addr(hdr->addr1));
- if (WARN_ON_ONCE(!sta->valid_links))
+ if (WARN_ON_ONCE(!sta || !sta->valid_links))
return &vif->bss_conf;
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
@@ -1940,7 +1940,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
hdr, &link_sta);
}
- if (WARN_ON(!bss_conf)) {
+ if (unlikely(!bss_conf)) {
+ /* if it's an MLO STA, it might have deactivated all
+ * links temporarily - but we don't handle real PS in
+ * this code yet, so just drop the frame in that case
+ */
+ WARN(link != IEEE80211_LINK_UNSPECIFIED || !sta || !sta->mlo,
+ "link:%d, sta:%pM, sta->mlo:%d\n",
+ link, sta ? sta->addr : NULL, sta ? sta->mlo : -1);
ieee80211_free_txskb(hw, skb);
return;
}
@@ -2628,7 +2635,8 @@ static int mac80211_hwsim_sta_state(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_STATION &&
new_state == IEEE80211_STA_AUTHORIZED && !sta->tdls)
- ieee80211_set_active_links_async(vif, vif->valid_links);
+ ieee80211_set_active_links_async(vif,
+ ieee80211_vif_usable_links(vif));
return 0;
}
@@ -5617,14 +5625,15 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
+ if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
+ frame_data_len > IEEE80211_MAX_DATA_LEN)
+ goto err;
+
/* Allocate new skb here */
skb = alloc_skb(frame_data_len, GFP_KERNEL);
if (skb == NULL)
goto err;
- if (frame_data_len > IEEE80211_MAX_DATA_LEN)
- goto err;
-
/* Copy the data */
skb_put_data(skb, frame_data, frame_data_len);
diff --git a/drivers/net/wireless/zydas/zd1201.c b/drivers/net/wireless/zydas/zd1201.c
index a85fe7e4c6d4..2814df1ecc78 100644
--- a/drivers/net/wireless/zydas/zd1201.c
+++ b/drivers/net/wireless/zydas/zd1201.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Driver for ZyDAS zd1201 based wireless USB devices.
+ * Driver for ZyDAS zd1201 based USB wireless devices.
*
* Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
*
@@ -23,8 +23,8 @@
#include "zd1201.h"
static const struct usb_device_id zd1201_table[] = {
- {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
- {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
+ {USB_DEVICE(0x0586, 0x3400)}, /* Peabird USB Wireless Adapter */
+ {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 USB Wireless Adapter */
{USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */
{USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */
{USB_DEVICE(0x1044, 0x8004)}, /* Gigabyte GN-WLBZ101 */
diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c
index 829515a601b3..635301d677e1 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_imem.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c
@@ -4,6 +4,7 @@
*/
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_devlink.h"
@@ -631,6 +632,11 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
/* Complete all memory stores after setting bit */
smp_mb__after_atomic();
+ if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) {
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_imem->dev);
+ }
+
return;
err_ipc_mux_deinit:
@@ -1234,6 +1240,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem)
/* forward MDM_NOT_READY to listeners */
ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY);
+ pm_runtime_get_sync(ipc_imem->dev);
hrtimer_cancel(&ipc_imem->td_alloc_timer);
hrtimer_cancel(&ipc_imem->tdupdate_timer);
@@ -1419,6 +1426,16 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id,
set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag);
}
+
+ if (!pm_runtime_enabled(ipc_imem->dev))
+ pm_runtime_enable(ipc_imem->dev);
+
+ pm_runtime_set_autosuspend_delay(ipc_imem->dev,
+ IPC_MEM_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(ipc_imem->dev);
+ pm_runtime_allow(ipc_imem->dev);
+ pm_runtime_mark_last_busy(ipc_imem->dev);
+
return ipc_imem;
devlink_channel_fail:
ipc_devlink_deinit(ipc_imem->ipc_devlink);
diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h
index e700dc8bfe0a..0144b45e2afb 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_imem.h
+++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h
@@ -103,6 +103,8 @@ struct ipc_chnl_cfg;
#define FULLY_FUNCTIONAL 0
#define IOSM_DEVLINK_INIT 1
+#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000
+
/* List of the supported UL/DL pipes. */
enum ipc_mem_pipes {
IPC_MEM_PIPE_0 = 0,
@@ -140,17 +142,6 @@ enum ipc_channel_state {
IMEM_CHANNEL_CLOSING,
};
-/* Time Unit */
-enum ipc_time_unit {
- IPC_SEC = 0,
- IPC_MILLI_SEC = 1,
- IPC_MICRO_SEC = 2,
- IPC_NANO_SEC = 3,
- IPC_PICO_SEC = 4,
- IPC_FEMTO_SEC = 5,
- IPC_ATTO_SEC = 6,
-};
-
/**
* enum ipc_ctype - Enum defining supported channel type needed for control
* /IP traffic.
@@ -204,7 +195,6 @@ enum ipc_hp_identifier {
* @pipe_nr: Pipe identification number
* @irq: Interrupt vector
* @dir: Direction of data stream in pipe
- * @td_tag: Unique tag of the buffer queued
* @buf_size: Buffer size (in bytes) for preallocated
* buffers (for DL pipes)
* @nr_of_queued_entries: Aueued number of entries
@@ -224,7 +214,6 @@ struct ipc_pipe {
u32 pipe_nr;
u32 irq;
enum ipc_mem_pipe_dir dir;
- u32 td_tag;
u32 buf_size;
u16 nr_of_queued_entries;
u8 is_open:1;
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mux.h b/drivers/net/wwan/iosm/iosm_ipc_mux.h
index 9968bb885c1f..17ca8d1f9397 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_mux.h
+++ b/drivers/net/wwan/iosm/iosm_ipc_mux.h
@@ -333,9 +333,7 @@ struct mux_acb {
* @wwan_q_offset: This will hold the offset of the given instance
* Useful while passing or receiving packets from
* wwan/imem layer.
- * @adb_finish_timer: Timer for forcefully finishing the ADB
* @acb_tx_sequence_nr: Sequence number for the ACB header.
- * @params: user configurable parameters
* @adb_tx_sequence_nr: Sequence number for ADB header
* @acc_adb_size: Statistic data for logging
* @acc_payload_size: Statistic data for logging
@@ -367,9 +365,7 @@ struct iosm_mux {
long long ul_data_pend_bytes;
struct mux_acb acb;
int wwan_q_offset;
- struct hrtimer adb_finish_timer;
u16 acb_tx_sequence_nr;
- struct ipc_params *params;
u16 adb_tx_sequence_nr;
unsigned long long acc_adb_size;
unsigned long long acc_payload_size;
diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
index 04517bd3325a..3a259c9abefd 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <net/rtnetlink.h>
#include "iosm_ipc_imem.h"
@@ -437,7 +438,8 @@ static int __maybe_unused ipc_pcie_resume_cb(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb);
+static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb,
+ ipc_pcie_resume_cb, NULL);
static struct pci_driver iosm_ipc_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c
index 5d5b4183e14a..2ba1ddca3945 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_port.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_port.c
@@ -3,6 +3,8 @@
* Copyright (C) 2020-21 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
+
#include "iosm_ipc_chnl_cfg.h"
#include "iosm_ipc_imem_ops.h"
#include "iosm_ipc_port.h"
@@ -13,12 +15,16 @@ static int ipc_port_ctrl_start(struct wwan_port *port)
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
int ret = 0;
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem,
ipc_port->chl_id,
IPC_HP_CDEV_OPEN);
if (!ipc_port->channel)
ret = -EIO;
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
return ret;
}
@@ -27,15 +33,24 @@ static void ipc_port_ctrl_stop(struct wwan_port *port)
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
}
/* transfer control data to modem */
static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
{
struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
+ int ret;
- return ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_get_sync(ipc_port->ipc_imem->dev);
+ ret = ipc_imem_sys_cdev_write(ipc_port, skb);
+ pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
+
+ return ret;
}
static const struct wwan_port_ops ipc_wwan_ctrl_ops = {
diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c
index eeecfa3d10c5..4368373797b6 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_trace.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c
@@ -3,7 +3,9 @@
* Copyright (C) 2020-2021 Intel Corporation.
*/
+#include <linux/pm_runtime.h>
#include <linux/wwan.h>
+
#include "iosm_ipc_trace.h"
/* sub buffer size and number of sub buffer */
@@ -97,6 +99,8 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp,
if (ret)
return ret;
+ pm_runtime_get_sync(ipc_trace->ipc_imem->dev);
+
mutex_lock(&ipc_trace->trc_mutex);
if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) {
ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem,
@@ -117,6 +121,10 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp,
ret = count;
unlock:
mutex_unlock(&ipc_trace->trc_mutex);
+
+ pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev);
+
return ret;
}
diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c
index 4c9022a93e01..93d17de08786 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c
@@ -6,6 +6,7 @@
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/if_link.h>
+#include <linux/pm_runtime.h>
#include <linux/rtnetlink.h>
#include <linux/wwan.h>
#include <net/pkt_sched.h>
@@ -18,8 +19,6 @@
#define IOSM_IP_TYPE_IPV4 0x40
#define IOSM_IP_TYPE_IPV6 0x60
-#define IOSM_IF_ID_PAYLOAD 2
-
/**
* struct iosm_netdev_priv - netdev WWAN driver specific private data
* @ipc_wwan: Pointer to iosm_wwan struct
@@ -53,11 +52,13 @@ static int ipc_wwan_link_open(struct net_device *netdev)
struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
struct iosm_wwan *ipc_wwan = priv->ipc_wwan;
int if_id = priv->if_id;
+ int ret = 0;
if (if_id < IP_MUX_SESSION_START ||
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get_sync(ipc_wwan->ipc_imem->dev);
/* get channel id */
priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id);
@@ -65,7 +66,8 @@ static int ipc_wwan_link_open(struct net_device *netdev)
dev_err(ipc_wwan->dev,
"cannot connect wwan0 & id %d to the IPC mem layer",
if_id);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_out;
}
/* enable tx path, DL data may follow */
@@ -74,7 +76,11 @@ static int ipc_wwan_link_open(struct net_device *netdev)
dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d",
priv->ch_id, priv->if_id);
- return 0;
+err_out:
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
+ return ret;
}
/* Bring-down the wwan net link */
@@ -84,9 +90,12 @@ static int ipc_wwan_link_stop(struct net_device *netdev)
netif_stop_queue(netdev);
+ pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev);
ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id,
priv->ch_id);
priv->ch_id = -1;
+ pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev);
return 0;
}
@@ -108,6 +117,7 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb,
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
+ pm_runtime_get(ipc_wwan->ipc_imem->dev);
/* Send the SKB to device for transmission */
ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem,
if_id, priv->ch_id, skb);
@@ -121,9 +131,14 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb,
ret = NETDEV_TX_BUSY;
dev_err(ipc_wwan->dev, "unable to push packets");
} else {
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
goto exit;
}
+ pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev);
+ pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev);
+
return ret;
exit:
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
index aec3a18d44bd..7162bf38a8c9 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
@@ -1293,9 +1293,9 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)
for (i = 0; i < CLDMA_TXQ_NUM; i++) {
md_cd_queue_struct_init(&md_ctrl->txq[i], md_ctrl, MTK_TX, i);
md_ctrl->txq[i].worker =
- alloc_workqueue("md_hif%d_tx%d_worker",
- WQ_UNBOUND | WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI),
- 1, md_ctrl->hif_id, i);
+ alloc_ordered_workqueue("md_hif%d_tx%d_worker",
+ WQ_MEM_RECLAIM | (i ? 0 : WQ_HIGHPRI),
+ md_ctrl->hif_id, i);
if (!md_ctrl->txq[i].worker)
goto err_workqueue;
@@ -1306,9 +1306,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)
md_cd_queue_struct_init(&md_ctrl->rxq[i], md_ctrl, MTK_RX, i);
INIT_WORK(&md_ctrl->rxq[i].cldma_work, t7xx_cldma_rx_done);
- md_ctrl->rxq[i].worker = alloc_workqueue("md_hif%d_rx%d_worker",
- WQ_UNBOUND | WQ_MEM_RECLAIM,
- 1, md_ctrl->hif_id, i);
+ md_ctrl->rxq[i].worker =
+ alloc_ordered_workqueue("md_hif%d_rx%d_worker",
+ WQ_MEM_RECLAIM,
+ md_ctrl->hif_id, i);
if (!md_ctrl->rxq[i].worker)
goto err_workqueue;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
index 46514208d4f9..8dab025a088a 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
@@ -618,8 +618,9 @@ int t7xx_dpmaif_txq_init(struct dpmaif_tx_queue *txq)
return ret;
}
- txq->worker = alloc_workqueue("md_dpmaif_tx%d_worker", WQ_UNBOUND | WQ_MEM_RECLAIM |
- (txq->index ? 0 : WQ_HIGHPRI), 1, txq->index);
+ txq->worker = alloc_ordered_workqueue("md_dpmaif_tx%d_worker",
+ WQ_MEM_RECLAIM | (txq->index ? 0 : WQ_HIGHPRI),
+ txq->index);
if (!txq->worker)
return -ENOMEM;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index c1501f41e2d8..88f760a7cbc3 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -396,7 +396,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
struct xen_netif_tx_request *txp = first;
- nr_slots = shinfo->nr_frags + 1;
+ nr_slots = shinfo->nr_frags + frag_overflow + 1;
copy_count(skb) = 0;
XENVIF_TX_CB(skb)->split_mask = 0;
@@ -462,8 +462,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
}
}
- for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
- shinfo->nr_frags++, gop++) {
+ for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
+ shinfo->nr_frags++, gop++, nr_slots--) {
index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index];
xenvif_tx_create_map_op(queue, pending_idx, txp,
@@ -476,12 +476,12 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
txp++;
}
- if (frag_overflow) {
+ if (nr_slots > 0) {
shinfo = skb_shinfo(nskb);
frags = shinfo->frags;
- for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow;
+ for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
shinfo->nr_frags++, txp++, gop++) {
index = pending_index(queue->pending_cons++);
pending_idx = queue->pending_ring[index];
@@ -492,6 +492,11 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
}
skb_shinfo(skb)->frag_list = nskb;
+ } else if (nskb) {
+ /* A frag_list skb was allocated but it is no longer needed
+ * because enough slots were converted to copy ops above.
+ */
+ kfree_skb(nskb);
}
(*copy_ops) = cop - queue->tx_copy_ops;
@@ -689,7 +694,7 @@ static void xenvif_fill_frags(struct xenvif_queue *queue, struct sk_buff *skb)
prev_pending_idx = pending_idx;
txp = &queue->pending_tx_info[pending_idx].req;
- page = virt_to_page(idx_to_kaddr(queue, pending_idx));
+ page = virt_to_page((void *)idx_to_kaddr(queue, pending_idx));
__skb_fill_page_desc(skb, i, page, txp->offset, txp->size);
skb->len += txp->size;
skb->data_len += txp->size;
@@ -1128,9 +1133,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
BUG();
offset += len;
- __skb_frag_set_page(&frags[i], page);
- skb_frag_off_set(&frags[i], 0);
- skb_frag_size_set(&frags[i], len);
+ skb_frag_fill_page_desc(&frags[i], page, 0, len);
}
/* Release all the original (foreign) frags. */